summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2016-02-28 08:16:44 +0000
committerJoshua M. Clulow <jmc@joyent.com>2016-07-06 16:25:14 +0000
commitc77e6a5cd33b65f552adf2b60cacf437e43163d7 (patch)
treeb2a5271fe78a3f0cd9970932181bbf21a70d71b5 /usr/src
parent93748a271b44434294fbc444dac0eb17fee6d2d7 (diff)
downloadillumos-joyent-c77e6a5cd33b65f552adf2b60cacf437e43163d7.tar.gz
XXX massive rework; simple mode is almost working
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/Makefile.files5
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3.c187
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3.h185
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_ciss.h61
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_isr.c196
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_mem.c595
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_noe.c31
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_scsi.c430
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c921
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_transport.c338
-rw-r--r--usr/src/uts/common/io/cpqary3/cpqary3_util.c518
11 files changed, 1470 insertions, 1997 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index b86a6367e1..6556ae4119 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -2152,9 +2152,10 @@ DR_SAS_OBJS = dr_sas.o
#
# CPQARY3 module
#
-CPQARY3_OBJS = cpqary3.o cpqary3_noe.o cpqary3_talk2ctlr.o \
+# XXX disabled cpqary3_noe.o cpqary3_ioctl.o
+CPQARY3_OBJS = cpqary3.o cpqary3_talk2ctlr.o \
cpqary3_isr.o cpqary3_transport.o cpqary3_mem.o \
- cpqary3_scsi.o cpqary3_util.o cpqary3_ioctl.o \
+ cpqary3_scsi.o cpqary3_util.o \
cpqary3_bd.o
#
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3.c b/usr/src/uts/common/io/cpqary3/cpqary3.c
index 85fbdaa01a..5482e5969e 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3.c
@@ -36,7 +36,9 @@ int8_t cpqary3_detect_target_geometry(cpqary3_t *);
* External Variable Definitions
*/
+#if 0
extern cpqary3_driver_info_t gdriver_info;
+#endif
/*
* Global Variables Definitions
@@ -183,37 +185,28 @@ static struct modlinkage cpqary3_modlinkage = {
int
_init()
{
- int retvalue;
+ int r;
/*
* Allocate Soft State Resources; if failure, return.
*/
- retvalue = ddi_soft_state_init(&cpqary3_state,
- sizeof (cpqary3_t), MAX_CTLRS);
- VERIFY(retvalue == 0);
+ VERIFY0(ddi_soft_state_init(&cpqary3_state, sizeof (cpqary3_t),
+ MAX_CTLRS));
- /*
- * Initialise the HBA Interface.
- */
- if (!(retvalue = scsi_hba_init(&cpqary3_modlinkage))) {
- /* Load the driver */
- if ((retvalue = mod_install(&cpqary3_modlinkage))) {
- /*
- * Failed to load the driver, undo HBA interface
- * and soft state allocation.
- */
- scsi_hba_fini(&cpqary3_modlinkage);
- ddi_soft_state_fini(&cpqary3_state);
- }
- } else {
- /*
- * Failed to register HBA interface, undo all soft state
- * allocation
- */
- ddi_soft_state_fini(&cpqary3_state);
+ if ((r = scsi_hba_init(&cpqary3_modlinkage)) != 0) {
+ goto fail;
}
- return (retvalue);
+ if ((r = mod_install(&cpqary3_modlinkage)) != 0) {
+ scsi_hba_fini(&cpqary3_modlinkage);
+ goto fail;
+ }
+
+ return (r);
+
+fail:
+ ddi_soft_state_fini(&cpqary3_state);
+ return (r);
}
/*
@@ -282,76 +275,74 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
uint32_t instance;
uint32_t retvalue;
uint32_t cleanstatus = 0;
- cpqary3_t *cpqary3p; /* per-controller */
+ cpqary3_t *cpq; /* per-controller */
ddi_dma_attr_t tmp_dma_attr;
-
- /* Return Failure, If the Command is other than - DDI_ATTACH. */
+ uint_t (*hw_isr)(caddr_t);
if (attach_cmd != DDI_ATTACH)
return (DDI_FAILURE);
/* Get the Instance of the Device */
-
instance = ddi_get_instance(dip);
/* Allocate the per-device-instance soft state structure */
-
- retvalue = ddi_soft_state_zalloc(cpqary3_state, instance);
- VERIFY(retvalue == 0);
-
+ if (ddi_soft_state_zalloc(cpqary3_state, instance) != 0) {
+ dev_err(dip, CE_WARN, "could not allocate soft state");
+ }
cleanstatus |= CPQARY3_SOFTSTATE_ALLOC_DONE;
/* Per Controller Pointer */
- cpqary3p = ddi_get_soft_state(cpqary3_state, instance);
- if (!cpqary3p) {
- cmn_err(CE_WARN, "CPQary3: Soft State Retrieval Failed");
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ if ((cpq = ddi_get_soft_state(cpqary3_state, instance)) == NULL) {
+ dev_err(dip, CE_WARN, "could not get soft state");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
/* Maintain a record in per-ctlr structure */
- cpqary3p->dip = dip;
- cpqary3p->instance = instance;
+ cpq->dip = dip;
+ cpq->instance = instance;
+ cpq->cpq_next_tag = 0x54321;
/* Get the User Configuration information from Driver's conf File */
- cpqary3_read_conf_file(dip, cpqary3p);
+ cpqary3_read_conf_file(dip, cpq);
/* Get and Map the HW Configuration */
- retvalue = cpqary3_update_ctlrdetails(cpqary3p, &cleanstatus);
- if (retvalue == CPQARY3_FAILURE) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ if (cpqary3_update_ctlrdetails(cpq, &cleanstatus) != CPQARY3_SUCCESS) {
+ dev_err(dip, CE_WARN, "cpqary3_update_ctlrdetails failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
/* Get the Cookie for hardware Interrupt Handler */
- if (ddi_get_iblock_cookie(dip, 0, &cpqary3p->hw_iblock_cookie) !=
+ if (ddi_get_iblock_cookie(dip, 0, &cpq->hw_iblock_cookie) !=
DDI_SUCCESS) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ dev_err(dip, CE_WARN, "ddi_get_iblock_cookie (hw) failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
/* Initialize Per Controller Mutex */
- mutex_init(&cpqary3p->hw_mutex, NULL, MUTEX_DRIVER,
- (void *)cpqary3p->hw_iblock_cookie);
-
+ mutex_init(&cpq->hw_mutex, NULL, MUTEX_DRIVER,
+ (void *)cpq->hw_iblock_cookie);
cleanstatus |= CPQARY3_MUTEX_INIT_DONE;
/* Get the Cookie for Soft(low level) Interrupt Handler */
if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_HIGH,
- &cpqary3p->sw_iblock_cookie) != DDI_SUCCESS) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ &cpq->sw_iblock_cookie) != DDI_SUCCESS) {
+ dev_err(dip, CE_WARN, "ddi_get_iblock_cookie (sw) failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
/* Initialize the s/w Mutex */
- mutex_init(&cpqary3p->sw_mutex, NULL, MUTEX_DRIVER,
- (void *)cpqary3p->sw_iblock_cookie);
+ mutex_init(&cpq->sw_mutex, NULL, MUTEX_DRIVER,
+ (void *)cpq->sw_iblock_cookie);
cleanstatus |= CPQARY3_SW_MUTEX_INIT_DONE;
/* Initialize per Controller private details */
- retvalue = cpqary3_init_ctlr_resource(cpqary3p);
- if (retvalue != CPQARY3_SUCCESS) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ if (cpqary3_init_ctlr_resource(cpq) != CPQARY3_SUCCESS) {
+ dev_err(dip, CE_WARN, "cpqary3_init_ctlr_resource failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
cleanstatus |= CPQARY3_CTLR_CONFIG_DONE;
@@ -359,9 +350,10 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
/*
* Allocate HBA transport structure
*/
- cpqary3p->hba_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
- if (!cpqary3p->hba_tran) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ if ((cpq->hba_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP)) ==
+ NULL) {
+ dev_err(dip, CE_WARN, "scsi_hba_tran_alloc failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
cleanstatus |= CPQARY3_HBA_TRAN_ALLOC_DONE;
@@ -371,21 +363,19 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
* Initialise the HBA tran entry points.
* Attach the controller to HBA.
*/
- cpqary3_init_hbatran(cpqary3p);
+ cpqary3_init_hbatran(cpq);
- /* PERF */
- /* SG */
tmp_dma_attr = cpqary3_dma_attr;
- tmp_dma_attr.dma_attr_sgllen = cpqary3p->sg_cnt;
- /* SG */
- /* PERF */
+ tmp_dma_attr.dma_attr_sgllen = cpq->sg_cnt;
+
/*
* Register the DMA attributes and the transport vectors
* of each instance of the HBA device.
*/
- if (scsi_hba_attach_setup(dip, &tmp_dma_attr, cpqary3p->hba_tran,
+ if (scsi_hba_attach_setup(dip, &tmp_dma_attr, cpq->hba_tran,
SCSI_HBA_TRAN_CLONE) == DDI_FAILURE) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ dev_err(dip, CE_WARN, "scsi_hba_attach_setup failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
cleanstatus |= CPQARY3_HBA_TRAN_ATTACH_DONE;
@@ -408,37 +398,54 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
cleanstatus |= CPQARY3_CREATE_MINOR_NODE;
} else {
cmn_err(CE_NOTE, "CPQary3 : Failed to create minor node");
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
-
/* Register Software Interrupt Handler */
if (ddi_add_softintr(dip, DDI_SOFTINT_HIGH,
- &cpqary3p->cpqary3_softintr_id, &cpqary3p->sw_iblock_cookie, NULL,
- cpqary3_sw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ &cpq->cpqary3_softintr_id, &cpq->sw_iblock_cookie, NULL,
+ cpqary3_sw_isr, (caddr_t)cpq) != DDI_SUCCESS) {
+ dev_err(dip, CE_WARN, "ddi_add_softintr failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
cleanstatus |= CPQARY3_SW_INTR_HDLR_SET;
+ /*
+ * Select the correct hardware interrupt service routine for the
+ * Transport Method we have configured:
+ */
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ hw_isr = cpqary3_isr_hw_simple;
+ break;
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ hw_isr = cpqary3_isr_hw_performant;
+ break;
+ default:
+ panic("unknown controller mode");
+ }
+
/* Register Interrupt Handler */
- if (ddi_add_intr(dip, 0, &cpqary3p->hw_iblock_cookie, NULL,
- cpqary3_hw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) {
- cpqary3_cleanup(cpqary3p, cleanstatus);
+ if (ddi_add_intr(dip, 0, &cpq->hw_iblock_cookie, NULL, hw_isr,
+ (caddr_t)cpq) != DDI_SUCCESS) {
+ dev_err(dip, CE_WARN, "ddi_add_intr (hw) failed");
+ cpqary3_cleanup(cpq, cleanstatus);
return (DDI_FAILURE);
}
cleanstatus |= CPQARY3_INTR_HDLR_SET;
/* Enable the Controller Interrupt */
- cpqary3_intr_onoff(cpqary3p, CPQARY3_INTR_ENABLE);
- if (cpqary3p->host_support & 0x4)
- cpqary3_lockup_intr_onoff(cpqary3p, CPQARY3_LOCKUP_INTR_ENABLE);
+ cpqary3_intr_onoff(cpq, CPQARY3_INTR_ENABLE);
+ if (cpq->host_support & 0x4) {
+ cpqary3_lockup_intr_onoff(cpq, CPQARY3_LOCKUP_INTR_ENABLE);
+ }
/*
* Register a periodic function to be called every 15 seconds.
*/
- cpqary3p->cpq_periodic = ddi_periodic_add(cpqary3_periodic, cpqary3p,
+ cpq->cpq_periodic = ddi_periodic_add(cpqary3_periodic, cpq,
15 * NANOSEC, DDI_IPL_0);
cleanstatus |= CPQARY3_TICK_TMOUT_REGD;
@@ -448,6 +455,10 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
* the driver
*/
+ /*
+ * XXX OK, maybe later...
+ */
+#if 0
/* NOE */
if (cpqary3p->noe_support == 1) {
/* Enable the Notification on Event in this controller */
@@ -461,6 +472,7 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
}
}
/* NOE */
+#endif
/* Report that an Instance of the Driver is Attached Successfully */
ddi_report_dev(dip);
@@ -470,10 +482,12 @@ cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd)
* This is required for the agents
*/
+#if 0
gdriver_info.num_ctlr++;
+#endif
+ dev_err(dip, CE_WARN, "attach complete");
return (DDI_SUCCESS);
-
}
/*
@@ -531,6 +545,7 @@ int
cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
int *retvaluep)
{
+
minor_t cpqary3_minor_num;
cpqary3_t *cpqary3p;
int instance;
@@ -578,6 +593,7 @@ cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
/* HPQacucli Changes */
switch (cmd) {
+#if 0
case CPQARY3_IOCTL_DRIVER_INFO:
*retvaluep =
cpqary3_ioctl_driver_info(arg, mode);
@@ -598,13 +614,13 @@ cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
cpqary3_ioctl_scsi_pass(arg, cpqary3p, mode);
break;
+#endif
default:
*retvaluep = EINVAL;
break;
}
return (*retvaluep);
-
}
@@ -631,6 +647,10 @@ cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status)
*/
/*
+ * XXX maybe later
+ */
+#if 0
+ /*
* We have removed NOE functionality from the
* driver. So commenting the below piece of code
*/
@@ -650,6 +670,7 @@ cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status)
mutex_exit(&cpqary3p->hw_mutex);
}
}
+#endif
/*
* Detach the device
@@ -697,14 +718,16 @@ cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status)
for (targ = 0; targ < CPQARY3_MAX_TGT; targ++) {
if (cpqary3p->cpqary3_tgtp[targ] == NULL)
continue;
- MEM_SFREE(cpqary3p->cpqary3_tgtp[targ],
+ kmem_free(cpqary3p->cpqary3_tgtp[targ],
sizeof (cpqary3_tgt_t));
}
mutex_exit(&cpqary3p->hw_mutex);
+#if 0
cpqary3_memfini(cpqary3p, CPQARY3_MEMLIST_DONE |
CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE);
+#endif
}
if (status & CPQARY3_SW_MUTEX_INIT_DONE)
@@ -832,7 +855,7 @@ cpqary3_update_ctlrdetails(cpqary3_t *cpqary3p, uint32_t *cleanstatus)
mem_bar0 = mem_64_bar0;
mem_bar1 = mem_64_bar1;
- MEM_SFREE(regp, reglen);
+ kmem_free(regp, reglen);
/*
* Setup resources to access the Local PCI Bus
@@ -869,6 +892,8 @@ cpqary3_update_ctlrdetails(cpqary3_t *cpqary3p, uint32_t *cleanstatus)
map_len = cpqary3p->bddef->bd_maplen;
(void) strcpy(cpqary3p->hba_name, cpqary3p->bddef->bd_dispname);
+ dev_err(cpqary3p->dip, CE_WARN, "controller: %s", cpqary3p->hba_name);
+
/*
* Set up a mapping for the following registers:
* Inbound Doorbell
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3.h b/usr/src/uts/common/io/cpqary3/cpqary3.h
index e79b398e3e..b2b937ea7c 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3.h
+++ b/usr/src/uts/common/io/cpqary3/cpqary3.h
@@ -86,6 +86,23 @@ extern "C" {
#define CPQARY3_CLEAN_ALL 0x0FFF
/*
+ * Definitions to support waiting for the controller to converge on a
+ * particular state; ready or not ready. These are used with
+ * cpqary3_ctlr_wait_for_state().
+ */
+#define CPQARY3_WAIT_DELAY_SECONDS 120
+typedef enum cpqary3_wait_state {
+ CPQARY3_WAIT_STATE_READY = 1,
+ CPQARY3_WAIT_STATE_UNREADY
+} cpqary3_wait_state_t;
+
+typedef enum cpqary3_ctlr_mode {
+ CPQARY3_CTLR_MODE_UNKNOWN = 0,
+ CPQARY3_CTLR_MODE_SIMPLE,
+ CPQARY3_CTLR_MODE_PERFORMANT
+} cpqary3_ctlr_mode_t;
+
+/*
* Defines for Maximum and Default Settings.
*/
@@ -157,12 +174,6 @@ extern "C" {
#define CPQARY3_SEC2HZ(x) drv_usectohz((x) * 1000000)
/*
- * Macros for memory allocation/deallocations
- */
-#define MEM_ZALLOC(x) kmem_zalloc(x, KM_NOSLEEP)
-#define MEM_SFREE(x, y) if (x) kmem_free((void*)x, y)
-
-/*
* Convenient macros for reading/writing Configuration table registers
*/
#define DDI_GET8(ctlr, regp) \
@@ -268,11 +279,20 @@ typedef struct cpqary3_target {
#define INTR_SIMPLE_5I_MASK 0x00000004l
#define INTR_SIMPLE_5I_LOCKUP_MASK 0x0000000cl
-typedef struct cpqary3_per_controller CTLR;
+typedef struct cpqary3_replyq {
+ unsigned cprq_cycle_indicator;
+ size_t cprq_ntags;
+ uint32_t *cprq_tags;
+ size_t cprq_read_index;
+ uint32_t cprq_tags_pa; /* XXX wrong type */
+ cpqary3_phyctg_t cprq_phyctg;
+} cpqary3_replyq_t;
+
+typedef struct cpqary3 cpqary3_t;
/*
* Per Controller Structure
*/
-typedef struct cpqary3_per_controller {
+struct cpqary3 {
/* System Dependent Entities */
uint8_t bus;
uint8_t dev : 5;
@@ -281,14 +301,25 @@ typedef struct cpqary3_per_controller {
dev_info_t *dip;
/* Controller Specific Information */
+ cpqary3_ctlr_mode_t cpq_ctlr_mode;
int8_t hba_name[38];
ulong_t num_of_targets;
uint32_t board_id;
cpqary3_bd_t *bddef;
+ /*
+ * Controller Heartbeat Tracking
+ */
uint32_t cpq_last_heartbeat;
clock_t cpq_last_heartbeat_lbolt;
+ uint32_t cpq_next_tag;
+
+ boolean_t cpq_intr_off;
+
+ cpqary3_replyq_t cpq_replyq;
+ avl_tree_t cpq_inflight;
+
/* Condition Variables used */
kcondvar_t cv_immediate_wait;
kcondvar_t cv_noe_wait;
@@ -310,16 +341,15 @@ typedef struct cpqary3_per_controller {
ddi_iblock_cookie_t sw_iblock_cookie; /* cookie for s/w intr */
kmutex_t sw_mutex; /* s/w mutex */
ddi_softintr_t cpqary3_softintr_id; /* s/w intr identifier */
- uint8_t swintr_flag;
+ boolean_t cpq_swintr_flag;
ddi_periodic_t cpq_periodic;
uint8_t cpqary3_tick_hdlr;
scsi_hba_tran_t *hba_tran; /* transport structure */
cpqary3_cmdmemlist_t *cmdmemlistp; /* database - Memory Pool */
cpqary3_tgt_t *cpqary3_tgtp[CPQARY3_MAX_TGT];
- cpqary3_drvr_replyq_t *drvr_replyq;
- uint8_t (*check_ctlr_intr)(CTLR *);
+ uint8_t (*check_ctlr_intr)(cpqary3_t *);
/*
* PCI Configuration Registers
@@ -370,7 +400,6 @@ typedef struct cpqary3_per_controller {
CfgTrans_Perf_t *cp;
ddi_acc_handle_t cp_handle;
- uint32_t legacy_mapping;
uint32_t noe_support;
/* SG */
uint32_t sg_cnt;
@@ -380,17 +409,66 @@ typedef struct cpqary3_per_controller {
uint8_t controller_lockup;
uint8_t lockup_logged;
uint32_t poll_flag;
-} cpqary3_t;
+ list_t cpq_commands; /* List of all commands. */
+};
-/*
- * Private Structure for Self Issued Commands
- */
+typedef struct cpqary3_command cpqary3_command_t;
+typedef struct cpqary3_command_internal cpqary3_command_internal_t;
+typedef struct cpqary3_pkt cpqary3_pkt_t;
+
+typedef enum cpqary3_synccmd_status {
+ CPQARY3_SYNCCMD_STATUS_NONE = 0,
+ CPQARY3_SYNCCMD_STATUS_SUBMITTED,
+ CPQARY3_SYNCCMD_STATUS_TIMEOUT
+} cpqary3_synccmd_status_t;
+
+typedef enum cpqary3_command_type {
+ CPQARY3_CMDTYPE_NONE = 0,
+ CPQARY3_CMDTYPE_OS,
+ CPQARY3_CMDTYPE_SYNCCMD,
+} cpqary3_command_type_t;
+
+struct cpqary3_command {
+ uint32_t cpcm_tag;
+ cpqary3_command_type_t cpcm_type;
+
+ cpqary3_t *cpcm_ctlr;
+
+ list_node_t cpcm_link; /* Linkage for allocated list. */
+ avl_node_t cpcm_node; /* Inflight AVL membership. */
+ boolean_t cpcm_inflight;
+ boolean_t cpcm_error;
+ boolean_t cpcm_free_on_complete;
+ boolean_t cpcm_used;
+
+ cpqary3_synccmd_status_t cpcm_synccmd_status;
+
+ cpqary3_pkt_t *cpcm_private;
+ cpqary3_command_internal_t *cpcm_internal;
+
+ void (*cpcm_complete)(cpqary3_command_t *);
+
+ /*
+ * Physical allocation tracking:
+ */
+ cpqary3_phyctg_t cpcm_phyctg;
+
+ CommandList_t *cpcm_va_cmd;
+ uint32_t cpcm_pa_cmd; /* XXX wrong type */
+
+ ErrorInfo_t *cpcm_va_err;
+ uint32_t cpcm_pa_err; /* XXX wrong type */
+};
+
+struct cpqary3_command_internal {
+ cpqary3_phyctg_t cpcmi_phyctg;
+
+ void *cpcmi_va;
+ uint32_t cpcmi_pa; /* XXX wrong type */
+ size_t cpcmi_len;
+};
-typedef struct cpqary3_driver_private {
- void *sg;
- cpqary3_phyctg_t *phyctgp;
-}cpqary3_private_t;
/* cmd_flags */
#define CFLAG_DMASEND 0x01
@@ -400,7 +478,7 @@ typedef struct cpqary3_driver_private {
/*
* Driver Private Packet
*/
-typedef struct cpqary3_pkt {
+struct cpqary3_pkt {
struct scsi_pkt *scsi_cmd_pkt;
ddi_dma_win_t prev_winp;
ddi_dma_seg_t prev_segp;
@@ -422,8 +500,8 @@ typedef struct cpqary3_pkt {
uint32_t cmd_flags;
uint32_t cdb_len;
uint32_t scb_len;
- cpqary3_cmdpvt_t *memp;
-} cpqary3_pkt_t;
+ cpqary3_command_t *cmd_command;
+};
#pragma pack(1)
@@ -455,42 +533,73 @@ typedef struct cpqary3_ioctlreq {
void cpqary3_init_hbatran(cpqary3_t *);
void cpqary3_read_conf_file(dev_info_t *, cpqary3_t *);
void cpqary3_periodic(void *);
-void cpqary3_flush_cache(cpqary3_t *);
+int cpqary3_flush_cache(cpqary3_t *);
void cpqary3_intr_onoff(cpqary3_t *, uint8_t);
void cpqary3_lockup_intr_onoff(cpqary3_t *, uint8_t);
uint8_t cpqary3_disable_NOE_command(cpqary3_t *);
uint8_t cpqary3_send_NOE_command(cpqary3_t *, cpqary3_cmdpvt_t *, uint8_t);
uint16_t cpqary3_init_ctlr_resource(cpqary3_t *);
-uint32_t cpqary3_hw_isr(caddr_t);
-uint32_t cpqary3_sw_isr(caddr_t);
int32_t cpqary3_ioctl_driver_info(uintptr_t, int);
int32_t cpqary3_ioctl_ctlr_info(uintptr_t, cpqary3_t *, int);
int32_t cpqary3_ioctl_bmic_pass(uintptr_t, cpqary3_t *, int);
int32_t cpqary3_ioctl_scsi_pass(uintptr_t, cpqary3_t *, int);
uint8_t cpqary3_probe4targets(cpqary3_t *);
void cpqary3_cmdlist_release(cpqary3_cmdpvt_t *, uint8_t);
-int cpqary3_submit(cpqary3_t *, uint32_t);
-void cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *, uint8_t);
-caddr_t cpqary3_alloc_phyctgs_mem(cpqary3_t *, size_t, uint32_t *,
- cpqary3_phyctg_t *);
+int cpqary3_submit(cpqary3_t *, cpqary3_command_t *);
cpqary3_cmdpvt_t *cpqary3_cmdlist_occupy(cpqary3_t *);
-void cpqary3_synccmd_complete(cpqary3_cmdpvt_t *);
void cpqary3_NOE_handler(cpqary3_cmdpvt_t *);
-uint8_t cpqary3_retrieve(cpqary3_t *);
-void cpqary3_synccmd_cleanup(cpqary3_cmdpvt_t *);
+int cpqary3_retrieve(cpqary3_t *);
+void cpqary3_retrieve_simple(cpqary3_t *, uint32_t, boolean_t *);
+void cpqary3_retrieve_performant(cpqary3_t *, uint32_t, boolean_t *);
int cpqary3_target_geometry(struct scsi_address *);
uint8_t cpqary3_send_abortcmd(cpqary3_t *, uint16_t, CommandList_t *);
void cpqary3_memfini(cpqary3_t *, uint8_t);
-uint8_t cpqary3_init_ctlr(cpqary3_t *);
int16_t cpqary3_meminit(cpqary3_t *);
void cpqary3_noe_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp);
-cpqary3_cmdpvt_t *cpqary3_synccmd_alloc(cpqary3_t *, size_t);
-void cpqary3_synccmd_free(cpqary3_t *, cpqary3_cmdpvt_t *);
-int cpqary3_synccmd_send(cpqary3_t *, cpqary3_cmdpvt_t *, clock_t, int);
uint8_t cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag);
-uint8_t cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid);
+uint8_t cpqary3_build_cmdlist(cpqary3_command_t *cpqary3_cmdpvtp, uint32_t tid);
void cpqary3_lockup_check(cpqary3_t *);
+/*
+ * Memory management.
+ */
+#if 0
+void cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *, uint8_t);
+caddr_t cpqary3_alloc_phyctgs_mem(cpqary3_t *, size_t, uint32_t *,
+ cpqary3_phyctg_t *);
+#endif
+
+/*
+ * Synchronous command routines.
+ */
+cpqary3_command_t *cpqary3_synccmd_alloc(cpqary3_t *, size_t);
+void cpqary3_synccmd_free(cpqary3_t *, cpqary3_command_t *);
+int cpqary3_synccmd_send(cpqary3_t *, cpqary3_command_t *, clock_t, int);
+void cpqary3_synccmd_complete(cpqary3_command_t *);
+
+/*
+ * Interrupt service routines.
+ */
+uint32_t cpqary3_isr_hw_simple(caddr_t);
+uint32_t cpqary3_isr_hw_performant(caddr_t);
+uint32_t cpqary3_sw_isr(caddr_t);
+
+/*
+ * Controller initialisation routines.
+ */
+int cpqary3_ctlr_init(cpqary3_t *);
+int cpqary3_ctlr_wait_for_state(cpqary3_t *, cpqary3_wait_state_t);
+
+/*
+ * Command object management.
+ */
+cpqary3_command_t *cpqary3_command_alloc(cpqary3_t *);
+cpqary3_command_internal_t *cpqary3_command_internal_alloc(cpqary3_t *, size_t);
+void cpqary3_command_free(cpqary3_command_t *);
+
+cpqary3_command_t *cpqary3_lookup_inflight(cpqary3_t *, uint32_t);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h b/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h
index 58b4e18cb1..31f95cb427 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_ciss.h
@@ -135,8 +135,6 @@ extern "C" {
#pragma pack(1)
-typedef uint64_t QWORD;
-
/*
* Structure for Tag field in the controller command structure
* Bit 0 : Unused
@@ -144,16 +142,18 @@ typedef uint64_t QWORD;
* Bits 2 & 3 : Used by this driver to signify a host of situations
* Bits 4-31 : Used by driver to fill in tag and then used by controller
* Bits 32-63 : Reserved
+ *
+ * XXX NOOOOOOOOOOOOOOOOOOO
*/
#define CISS_CMD_ERROR 0x2
typedef struct cpqary3_tag {
uint32_t reserved:1;
- uint32_t drvinfo_n_err:3;
- uint32_t tag_value:28;
+ uint32_t error:1;
+ uint32_t tag_value:30;
uint32_t unused;
} cpqary3_tag_t;
-typedef union _SCSI3Addr_t {
+typedef union SCSI3Addr {
struct {
uint8_t Bus:6;
uint8_t Mode:2;
@@ -172,27 +172,27 @@ typedef union _SCSI3Addr_t {
} LogUnit;
} SCSI3Addr_t;
-typedef struct _PhysDevAddr_t {
+typedef struct PhysDevAddr {
uint32_t TargetId:24;
uint32_t Bus:6;
uint32_t Mode:2;
SCSI3Addr_t Target[2];
} PhysDevAddr_t;
-typedef struct _LogDevAddr_t {
+typedef struct LogDevAddr {
uint32_t VolId:30;
uint32_t Mode:2;
uint8_t reserved[4];
} LogDevAddr_t;
-typedef union _LUNAddr_t {
+typedef union LUNAddr {
uint8_t LunAddrBytes[8];
SCSI3Addr_t SCSI3Lun[4];
PhysDevAddr_t PhysDev;
LogDevAddr_t LogDev;
} LUNAddr_t;
-typedef struct _CommandListHeader_t {
+typedef struct CommandListHeader {
uint8_t ReplyQueue;
uint8_t SGList;
uint16_t SGTotal;
@@ -200,7 +200,7 @@ typedef struct _CommandListHeader_t {
LUNAddr_t LUN; /* 20 */
} CommandListHeader_t;
-typedef struct _RequestBlock_t {
+typedef struct RequestBlock {
uint8_t CDBLen;
struct {
uint8_t Type:3;
@@ -211,25 +211,25 @@ typedef struct _RequestBlock_t {
uint8_t CDB[16]; /* 20 */
} RequestBlock_t;
-typedef struct _ErrDescriptor_t {
- QWORD Addr;
+typedef struct ErrDescriptor {
+ uint64_t Addr;
uint32_t Len; /* 12 */
} ErrDescriptor_t;
-typedef struct _SGDescriptor_t {
- QWORD Addr;
+typedef struct SGDescriptor {
+ uint64_t Addr;
uint32_t Len;
uint32_t Ext; /* 16 */
} SGDescriptor_t;
-typedef struct _CommandList_t {
+typedef struct CommandList {
CommandListHeader_t Header; /* 20 */
RequestBlock_t Request; /* 20, 40 */
ErrDescriptor_t ErrDesc; /* 12, 52 */
SGDescriptor_t SG[CISS_MAXSGENTRIES]; /* 16*SG_MAXENTRIES=512, 564 */
} CommandList_t;
-typedef union _MoreErrInfo_t {
+typedef union MoreErrInfo {
struct {
uint8_t Reserved[3];
uint8_t Type;
@@ -243,7 +243,7 @@ typedef union _MoreErrInfo_t {
} Invalid_Cmd;
} MoreErrInfo_t;
-typedef struct _ErrorInfo_t {
+typedef struct ErrorInfo {
uint8_t ScsiStatus;
uint8_t SenseLen;
uint16_t CommandStatus;
@@ -253,14 +253,14 @@ typedef struct _ErrorInfo_t {
} ErrorInfo_t;
/* Configuration Table Structure */
-typedef struct _HostWrite_t {
+typedef struct HostWrite {
uint32_t TransportRequest;
uint32_t Upper32Addr;
uint32_t CoalIntDelay;
uint32_t CoalIntCount;
} HostWrite_t;
-typedef struct _CfgTable_t {
+typedef struct CfgTable {
uint8_t Signature[4];
uint32_t SpecValence;
uint32_t TransportSupport;
@@ -282,7 +282,7 @@ typedef struct _CfgTable_t {
/* PERF */
} CfgTable_t;
-typedef struct _CfgTrans_Perf_t {
+typedef struct CfgTrans_Perf {
uint32_t BlockFetchCnt[8];
uint32_t ReplyQSize;
uint32_t ReplyQCount;
@@ -292,34 +292,21 @@ typedef struct _CfgTrans_Perf_t {
uint32_t ReplyQAddr0High32;
} CfgTrans_Perf_t;
-typedef struct _CfgTrans_MemQ_t {
+typedef struct CfgTrans_MemQ {
uint32_t BlockFetchCnt[8];
uint32_t CmdQSize;
uint32_t CmdQOffset;
uint32_t ReplyQSize;
uint32_t ReplyQCount;
- QWORD ReplyQCntrAddr;
- QWORD ReplyQAddr[CISS_MAXREPLYQS];
+ uint64_t ReplyQCntrAddr;
+ uint64_t ReplyQAddr[CISS_MAXREPLYQS];
} CfgTrans_MemQ_t;
-typedef union _CfgTrans_t {
+typedef union CfgTrans {
CfgTrans_Perf_t *Perf;
CfgTrans_MemQ_t *MemQ;
} CfgTrans_t;
-#define CPQARY3_REPLYQ_INIT_CYCLIC_IND 0x1
-typedef struct cpqary3_drvr_replyq {
- uchar_t cyclic_indicator;
- uchar_t simple_cyclic_indicator;
- caddr_t replyq_start_addr;
- uint32_t replyq_start_paddr;
- uint32_t *replyq_headptr;
- uint32_t *replyq_simple_ptr;
- uint32_t index;
- uint32_t simple_index;
- uint32_t max_index;
-} cpqary3_drvr_replyq_t;
-
#pragma pack()
#ifdef __cplusplus
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_isr.c b/usr/src/uts/common/io/cpqary3/cpqary3_isr.c
index 963cdcaf39..5884fa1068 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_isr.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_isr.c
@@ -16,119 +16,86 @@
#include "cpqary3.h"
-/*
- * Function : cpqary3_hw_isr
- * Description : This routine determines if this instance of the
- * HBA interrupted and if positive triggers a software
- * interrupt.
- * For SAS controllers which operate in performant mode
- * we clear the interrupt.
- * For CISS controllers which operate in simple mode
- * we get the tag value.
- * Called By : kernel
- * Parameters : per-controller
- * Calls : cpqary3_check_ctlr_intr()
- * Return Values: DDI_INTR_CLAIMED/UNCLAIMED
- * [We either CLAIM the interrupt or Discard it]
- */
-uint_t
-cpqary3_hw_isr(caddr_t per_ctlr)
+
+static void
+cpqary3_trigger_sw_isr(cpqary3_t *cpq)
{
- boolean_t need_swintr;
- cpqary3_t *cpqary3p = (cpqary3_t *)per_ctlr;
- cpqary3_drvr_replyq_t *replyq_ptr;
- volatile CfgTable_t *ctp = cpqary3p->ct;
- uint32_t spr0;
- uint32_t doorbell_status;
- uint32_t tag;
+ boolean_t trigger = B_FALSE;
- replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+ if (!cpq->cpq_swintr_flag) {
+ trigger = B_TRUE;
+ cpq->cpq_swintr_flag = B_TRUE;
+ }
- /*
- * Check the Interrupt Status Register to see if the Outbound
- * Post List FIFO is not empty.
- */
- if (cpqary3p->check_ctlr_intr(cpqary3p) != CPQARY3_SUCCESS) {
+ if (trigger) {
+ ddi_trigger_softintr(cpq->cpqary3_softintr_id);
+ }
+}
+
+uint_t
+cpqary3_isr_hw_simple(caddr_t arg)
+{
+ cpqary3_t *cpq = (cpqary3_t *)arg;
+ uint32_t isr = ddi_get32(cpq->isr_handle, cpq->isr);
+
+ mutex_enter(&cpq->hw_mutex);
+ if ((isr & cpq->bddef->bd_intrpendmask) == 0) {
/*
* Check to see if the firmware has come to rest. If it has,
* this routine will panic the system.
*/
- cpqary3_lockup_check(cpqary3p);
+ cpqary3_lockup_check(cpq);
+ mutex_exit(&cpq->hw_mutex);
return (DDI_INTR_UNCLAIMED);
}
/*
- * We decided that we will have only one retrieve function for
- * both simple and performant mode. To achieve this we have to mimic
- * what controller does for performant mode in simple mode.
- * For simple mode we are making replq_simple_ptr and
- * replq_headptr of performant
- * mode point to the same location in the reply queue.
- * For the performant mode, we clear the interrupt
+ * Disable interrupts until the soft interrupt handler has had a chance
+ * to read and process replies.
*/
+ cpqary3_intr_onoff(cpq, CPQARY3_INTR_DISABLE);
- if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
- while ((tag = ddi_get32(cpqary3p->opq_handle,
- (uint32_t *)cpqary3p->opq)) != 0xFFFFFFFF) {
- replyq_ptr->replyq_simple_ptr[0] = tag;
- replyq_ptr->replyq_simple_ptr[0] |=
- replyq_ptr->simple_cyclic_indicator;
- ++replyq_ptr->simple_index;
-
- if (replyq_ptr->simple_index == replyq_ptr->max_index) {
- replyq_ptr->simple_index = 0;
- /* Toggle at wraparound */
- replyq_ptr->simple_cyclic_indicator =
- (replyq_ptr->simple_cyclic_indicator == 0) ?
- 1 : 0;
- replyq_ptr->replyq_simple_ptr =
- /* LINTED: alignment */
- (uint32_t *)(replyq_ptr->replyq_start_addr);
- } else {
- replyq_ptr->replyq_simple_ptr += 2;
- }
- }
- } else {
- doorbell_status = ddi_get32(cpqary3p->odr_handle,
- (uint32_t *)cpqary3p->odr);
- if (doorbell_status & 0x1) {
- ddi_put32(cpqary3p->odr_cl_handle,
- (uint32_t *)cpqary3p->odr_cl,
- (ddi_get32(cpqary3p->odr_cl_handle,
- (uint32_t *)cpqary3p->odr_cl) | 0x1));
- doorbell_status = ddi_get32(cpqary3p->odr_handle,
- (uint32_t *)cpqary3p->odr);
- }
- }
+ cpqary3_trigger_sw_isr(cpq);
- /* PERF */
+ mutex_exit(&cpq->hw_mutex);
+ return (DDI_INTR_CLAIMED);
+}
- /*
- * If s/w interrupt handler is already running, do not trigger another
- * since packets have already been transferred to Retrieved Q.
- * Else, Set swintr_flag to state to the s/w interrupt handler
- * that it has a job to do.
- * trigger the s/w interrupt handler
- * Claim the interrupt
- */
+uint_t
+cpqary3_isr_hw_performant(caddr_t arg)
+{
+ cpqary3_t *cpq = (cpqary3_t *)arg;
+ uint32_t isr = ddi_get32(cpq->isr_handle, cpq->isr);
- mutex_enter(&cpqary3p->hw_mutex);
+ if (isr == 0) {
+ /*
+ * Check to see if the firmware has come to rest. If it has,
+ * this routine will panic the system.
+ */
+ cpqary3_lockup_check(cpq);
- if (cpqary3p->swintr_flag == CPQARY3_TRUE) {
- need_swintr = B_FALSE;
- } else {
- need_swintr = B_TRUE;
- cpqary3p->swintr_flag = CPQARY3_TRUE;
+ return (DDI_INTR_UNCLAIMED);
}
- mutex_exit(&cpqary3p->hw_mutex);
+ uint32_t odr = ddi_get32(cpq->odr_handle, cpq->odr);
+ if ((odr & 0x1) != 0) {
+ uint32_t odr_cl = ddi_get32(cpq->odr_cl_handle, cpq->odr_cl);
+
+ odr_cl |= 0x1;
+ ddi_put32(cpq->odr_cl_handle, cpq->odr_cl, odr_cl);
- if (need_swintr) {
- ddi_trigger_softintr(cpqary3p->cpqary3_softintr_id);
+ /*
+ * Read the status register again to ensure the write to clear
+ * is flushed to the controller.
+ */
+ (void) ddi_get32(cpq->odr_handle, cpq->odr);
}
+ cpqary3_trigger_sw_isr(cpq);
+
return (DDI_INTR_CLAIMED);
}
@@ -145,33 +112,46 @@ cpqary3_hw_isr(caddr_t per_ctlr)
* [We either CLAIM the interrupr or DON'T]
*/
uint_t
-cpqary3_sw_isr(caddr_t per_ctlr)
+cpqary3_sw_isr(caddr_t arg)
{
- cpqary3_t *cpqary3p;
-
- cpqary3p = (void *)per_ctlr;
- if (!cpqary3p) {
- cmn_err(CE_PANIC, "CPQary3 : Software Interrupt Service "
- "Routine invoked with NULL pointer argument \n");
- }
+ cpqary3_t *cpq = (cpqary3_t *)arg;
/*
- * Ensure that our hardware routine actually triggered this routine.
- * If it was not the case, do NOT CLAIM the interrupt
+ * Confirm that the hardware interrupt routine scheduled this
+ * software interrupt, and if so, acknowledge it.
*/
-
- mutex_enter(&cpqary3p->hw_mutex);
- if (CPQARY3_TRUE != cpqary3p->swintr_flag) {
- mutex_exit(&cpqary3p->hw_mutex);
+ mutex_enter(&cpq->sw_mutex);
+ mutex_enter(&cpq->hw_mutex);
+ if (!cpq->cpq_swintr_flag) {
+ mutex_exit(&cpq->hw_mutex);
+ mutex_exit(&cpq->sw_mutex);
return (DDI_INTR_UNCLAIMED);
}
- cpqary3p->swintr_flag = CPQARY3_FALSE;
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ cpqary3_retrieve_simple(cpq, 0, NULL);
+ /*
+ * XXX need to manage interrupts better
+ */
+ if (!cpq->cpq_intr_off) {
+ cpqary3_intr_onoff(cpq, CPQARY3_INTR_ENABLE);
+ }
+ goto complete;
+
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ cpqary3_retrieve_performant(cpq, 0, NULL);
+ goto complete;
+
+ case CPQARY3_CTLR_MODE_UNKNOWN:
+ break;
+ }
- /* PERF */
- mutex_exit(&cpqary3p->hw_mutex);
- (void) cpqary3_retrieve(cpqary3p);
- /* PERF */
+ panic("unknown controller mode");
+complete:
+ cpq->cpq_swintr_flag = B_FALSE;
+ mutex_exit(&cpq->hw_mutex);
+ mutex_exit(&cpq->sw_mutex);
return (DDI_INTR_CLAIMED);
}
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_mem.c b/usr/src/uts/common/io/cpqary3/cpqary3_mem.c
index 1d0248dffa..de3e268f59 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_mem.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_mem.c
@@ -16,6 +16,10 @@
#include <sys/sdt.h>
#include "cpqary3.h"
+static caddr_t cpqary3_alloc_phyctgs_mem(cpqary3_t *, size_t, uint32_t *,
+ cpqary3_phyctg_t *);
+static void cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *, uint8_t);
+
/*
* Local Functions Definitions
*/
@@ -45,452 +49,6 @@ static ddi_dma_attr_t cpqary3_ctlr_dma_attr = {
extern ddi_device_acc_attr_t cpqary3_dev_attributes;
/*
- * Function : cpqary3_meminit
- * Description : This routine initialises memory for the command list.
- * Allocation of Physical contigous blocks and maintenance
- * of lists to these.
- * Called By : cpqary3_init_ctlr_resource()
- * Parameters : per_controller
- * Calls : cpqary3_alloc_phyctgs_mem, cpqary3_memfini
- * Return Values: SUCCESS / FAILURE
- * [If the required initialization and setup of memory
- * is successful, send back a success. Else, failure]
- */
-int16_t
-cpqary3_meminit(cpqary3_t *cpqary3p)
-{
- size_t mempool_size;
- caddr_t mempool_addr;
- uint16_t i = 0;
- uint32_t mem_size = 0;
- uint32_t no_cmds = 0;
- uint32_t cntr;
- uint32_t maxmemcnt;
- uint32_t phyaddr;
- uint32_t temp_phyaddr;
- uint32_t size_of_cmdlist = 0;
- uint32_t size_of_HRE = 0; /* Header + Request + Error */
- uint32_t unused_mem = 0;
- uint32_t mempoolnum;
- uint32_t CmdsOutMax;
- CommandList_t *cmdlist_memaddr;
- cpqary3_phyctg_t *cpqary3_phyctgp;
- cpqary3_cmdpvt_t *ptr;
- cpqary3_cmdpvt_t *head_pvtp;
- cpqary3_cmdpvt_t *tail_pvtp;
- cpqary3_cmdmemlist_t *memlistp = NULL;
- cpqary3_phys_hdl_addr_t *blk_ptr = NULL;
-
- RETURN_FAILURE_IF_NULL(cpqary3p);
-
- CmdsOutMax = cpqary3p->ctlr_maxcmds;
-
-
- /*
- * Allocate memory for the Structure to hold details about the
- * Command Memory Pool.
- * Update per_controller pointer to this.
- */
-
- cpqary3p->cmdmemlistp = memlistp =
- MEM_ZALLOC(sizeof (cpqary3_cmdmemlist_t));
-
- if (!cpqary3p->cmdmemlistp) {
- cmn_err(CE_NOTE, "CPQary3: Memory Initialization: "
- "Low Kernel Memory");
- return (CPQARY3_FAILURE);
- }
- cleanstatus |= CPQARY3_MEMLIST_DONE; /* For cleaning purpose. */
-
- /*
- * Allocate a Virtual Memory Pool of size
- * NO_OF_CMDLIST_BLKS * NO_OF_CMDLIST_IN_A_BLK * sizeof (cmdmem_pvt_t)
- * to store details of the above allocated Memory for
- * NO_OF_CMDLIST_BLKS * NO_OF_CMDLIST_IN_A_BLK Commands
- * Initialize this memory to act as a linked list to parse
- * thru the entire list
- * Initialize the Memory Mutex
- */
- no_cmds = (uint32_t)((CmdsOutMax / 3) * NO_OF_CMDLIST_IN_A_BLK);
- mem_size = (uint32_t)(no_cmds * sizeof (cpqary3_cmdpvt_t));
-
- head_pvtp = ptr = (cpqary3_cmdpvt_t *)(MEM_ZALLOC(mem_size));
- if (NULL == head_pvtp) {
- MEM_SFREE(cpqary3p->cmdmemlistp, sizeof (cpqary3_cmdmemlist_t));
- cpqary3p->cmdmemlistp = NULL;
- cleanstatus &= ~CPQARY3_MEMLIST_DONE; /* For cleaning. */
- cmn_err(CE_NOTE, "CPQary3: Memory Initialization: "
- "Low Kernel Memory");
- return (CPQARY3_FAILURE);
- }
-
- tail_pvtp = &ptr[no_cmds - 1];
- cleanstatus |= CPQARY3_CMDMEM_DONE; /* For cleaning purpose. */
-
- DTRACE_PROBE4(cmd_init_start, uint32_t, no_cmds, uint32_t, mem_size,
- cpqary3_cmdpvt_t *, head_pvtp, cpqary3_cmdpvt_t *, tail_pvtp);
-
- for (i = 0; i < no_cmds; i++) {
- ptr = &head_pvtp[i];
- ptr->occupied = CPQARY3_FREE;
- ptr->tag.tag_value = i;
- ptr->cmdlist_phyaddr = 0;
- ptr->cmdlist_erraddr = 0;
- ptr->cmdpvt_flag = 0;
- ptr->cmdlist_memaddr = (CommandList_t *)NULL;
- ptr->errorinfop = (ErrorInfo_t *)NULL;
- ptr->next = (cpqary3_cmdpvt_t *)((i == (no_cmds - 1)) ?
- NULL : &head_pvtp[i+1]);
- ptr->prev = (cpqary3_cmdpvt_t *)((i == 0) ?
- NULL : &head_pvtp[i-1]);
- ptr->ctlr = cpqary3p;
- ptr->pvt_pkt = (cpqary3_pkt_t *)NULL;
- ptr->sprev = (cpqary3_cmdpvt_t *)NULL;
- ptr->snext = (cpqary3_cmdpvt_t *)NULL;
- }
- cpqary3p->cmdmemlistp->head = head_pvtp; /* head Command Memory List */
- cpqary3p->cmdmemlistp->tail = tail_pvtp; /* tail Command Memory List */
- cpqary3p->cmdmemlistp->pool = head_pvtp; /* head Command Memory List */
- cpqary3p->cmdmemlistp->max_memcnt = 0; /* Maximum commands for ctlr */
-
- ptr = head_pvtp;
-
- DTRACE_PROBE(memlist_init_done);
-
- /*
- * We require the size of the commandlist and the combined
- * size of the Command Header, Request Block and the Error Desriptor
- * In CPQary3, it is 564 and 52 respectively.
- */
- size_of_cmdlist = sizeof (CommandList_t);
- size_of_HRE = size_of_cmdlist -
- (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
-
- /*
- * uint32_t alignment of cmdlist
- * In CPQary3, after alignment, the size of each commandlist is 576
- */
- if (size_of_cmdlist & 0x1F)
- size_of_cmdlist = ((size_of_cmdlist + 31) / 32) * 32;
-
- /*
- * The CmdsOutMax member in the Configuration Table states the maximum
- * outstanding commands supported by this controller.
- * The following code allocates memory in blocks; each block holds
- * 3 commands.
- */
-
- for (mempoolnum = 0; mempoolnum < ((CmdsOutMax / 3)); mempoolnum++) {
- /* Allocate Memory for handle to maintain the Cmd Lists */
- cpqary3_phyctgp = (cpqary3_phyctg_t *)
- MEM_ZALLOC(sizeof (cpqary3_phyctg_t));
- if (!cpqary3_phyctgp) {
- cpqary3_memfini(cpqary3p, cleanstatus);
- cmn_err(CE_NOTE, "CPQary3: Mem Initialization: "
- "Low Kernel Memory");
- return (CPQARY3_FAILURE);
- }
-
- /*
- * Get the Physically Contiguous Memory
- * Allocate 32 extra bytes of memory such as to get atleast
- * 2 Command Blocks from every allocation even if we add any
- * extra bytes after the initial allocation to make it 32 bit
- * aligned.
- */
- if (mempoolnum == 0) { /* Head of Memory Blocks' Linked List */
- memlistp->cpqary3_phyctgp = blk_ptr =
- (cpqary3_phys_hdl_addr_t *)
- MEM_ZALLOC(sizeof (cpqary3_phys_hdl_addr_t));
- blk_ptr->blk_addr = cpqary3_phyctgp;
- blk_ptr->next = NULL;
- } else {
- blk_ptr->next = (cpqary3_phys_hdl_addr_t *)
- MEM_ZALLOC(sizeof (cpqary3_phys_hdl_addr_t));
- blk_ptr = blk_ptr->next;
- blk_ptr->blk_addr = cpqary3_phyctgp;
- blk_ptr->next = NULL;
- }
-
- phyaddr = 0;
- mempool_size = (size_of_cmdlist * NO_OF_CMDLIST_IN_A_BLK) + 32;
- mempool_addr = cpqary3_alloc_phyctgs_mem(cpqary3p,
- mempool_size, &phyaddr, cpqary3_phyctgp);
-
- if (!mempool_addr) {
- if (!mempoolnum) { /* Failue in the first attempt */
- MEM_SFREE(blk_ptr,
- sizeof (cpqary3_phys_hdl_addr_t));
- memlistp->cpqary3_phyctgp = NULL;
- cmn_err(CE_WARN, "CPQary3 : Memory "
- "Initialization : Low Kernel Memory");
- return (CPQARY3_FAILURE);
- }
-
- /*
- * Some memory allocation has already been suucessful.
- * The driver shall continue its initialization and
- * working with whatever memory has been allocated.
- *
- * Free the latest virtual memory allocated.
- * NULLify the last node created to maintain the memory
- * block list.
- * Terminate the Memory Q here by marking the Tail.
- */
- blk_ptr->blk_addr = NULL;
- ptr--;
- ptr->next = NULL;
- memlistp->tail = ptr;
- return (CPQARY3_SUCCESS);
- }
- cleanstatus |= CPQARY3_PHYCTGS_DONE;
-
- bzero(mempool_addr, cpqary3_phyctgp->real_size);
-
- /*
- * The 32 bit alignment is stated in the attribute structure.
- * In case, it is not aligned as per requirement, we align it.
- * uint32_t alignment of the first CMDLIST in the memory list
- */
- temp_phyaddr = phyaddr;
- if (phyaddr & 0x1F) {
- phyaddr = (uint32_t)(((phyaddr + 31) / 32) * 32);
- unused_mem = (uint32_t)(phyaddr - temp_phyaddr);
- }
-
- /*
- * If the memory allocated is not 32 byte aligned then unused
- * will give the total no of bytes that must remain unused to
- * make it 32 byte aligned memory
- */
- mempool_addr = (char *)((char *)mempool_addr + unused_mem);
-
- /*
- * Update Counter for no. of Command Blocks.
- */
- maxmemcnt = 0;
- maxmemcnt = ((uint32_t)
- (cpqary3_phyctgp->real_size - (uint32_t)unused_mem)) /
- size_of_cmdlist;
- memlistp->max_memcnt = memlistp->max_memcnt + maxmemcnt;
-
- /*
- * Get the base of mempool which is 32 Byte aligned
- * Initialize each Command Block with its corresponding
- * Physical Address, Virtual address and the Physical Addres
- * of the Error Info Descriptor
- */
- cmdlist_memaddr = (CommandList_t *)mempool_addr;
-
- for (cntr = 0; cntr < maxmemcnt; cntr++) {
- ptr->cmdlist_phyaddr = phyaddr;
- ptr->cmdlist_memaddr = cmdlist_memaddr;
- ptr->cmdlist_erraddr = phyaddr + size_of_HRE;
- ptr->errorinfop = (ErrorInfo_t *)
- ((ulong_t)cmdlist_memaddr + size_of_HRE);
- phyaddr += size_of_cmdlist;
- cmdlist_memaddr = (CommandList_t *)
- ((ulong_t)cmdlist_memaddr + size_of_cmdlist);
- ptr++;
- }
- }
-
-#ifdef MEM_DEBUG
- ptr = memlistp->head;
- cmn_err(CE_CONT, "CPQary3 : _meminit : max_memcnt = %d \n",
- memlistp->max_memcnt);
- for (cntr = 0; cntr <= memlistp->max_memcnt; cntr++) {
- cmn_err(CE_CONT, "CPQary3: %d %x |",
- cntr, ptr->cmdlist_phyaddr);
- if (cntr == 0)
- debug_enter("");
- ptr++;
- }
- cmn_err(CE_CONT, "\nCPQary3 : _meminit : "
- "cpqary3_cmdpvt starts at %x \n", memlistp->head);
- cmn_err(CE_CONT, "CPQary3 : _meminit : cpqary3_cmdpvt ends at %x \n",
- memlistp->tail);
- cmn_err(CE_CONT, "CPQary3 : _meminit : Leaving Successfully \n");
-#endif
-
- return (CPQARY3_SUCCESS);
-}
-
-/*
- * Function : cpqary3_cmdlist_occupy
- * Description : This routine fetches a command block from the
- * initialised memory pool.
- * Called By : cpqary3_transport(), cpqary3_send_NOE_command(),
- * cpqary3_disable_NOE_command(), cpqary3_synccmd_alloc()
- * Parameters : per_controller
- * Calls : None
- * Return Values: pointer to a valid Command Block /
- * NULL if none is available
- */
-cpqary3_cmdpvt_t *
-cpqary3_cmdlist_occupy(cpqary3_t *ctlr)
-{
- cpqary3_cmdpvt_t *memp = NULL;
- cpqary3_cmdmemlist_t *memlistp;
-
- RETURN_NULL_IF_NULL(ctlr);
- memlistp = ctlr->cmdmemlistp;
-
- /*
- * If pointer is NULL, we have no Command Memory Blocks available now.
- * Else, occupy it and
- * zero the commandlist so that old data is not existent.
- * update tag, Error descriptor address & length in the CommandList
- */
-
- mutex_enter(&ctlr->sw_mutex);
- memp = memlistp->head;
- if (NULL == memp) {
- mutex_exit(&ctlr->sw_mutex);
- return ((cpqary3_cmdpvt_t *)NULL);
- }
-
- memp->occupied = CPQARY3_OCCUPIED;
- bzero(memp->cmdlist_memaddr, sizeof (CommandList_t));
- memp->cmdlist_memaddr->Header.Tag.tag_value = memp->tag.tag_value;
- memp->cmdlist_memaddr->ErrDesc.Addr = memp->cmdlist_erraddr;
- memp->cmdlist_memaddr->ErrDesc.Len = sizeof (ErrorInfo_t);
- memlistp->head = memp->next;
-
- DTRACE_PROBE1(cmdlist_occupy, cpqary3_cmdpvt_t *, memp);
-
- if (memlistp->head) /* Atleast one more item is left in the Memory Q */
- memp->next->prev = NULL;
- else /* No more items left in the Memory q */
- memlistp->tail = NULL;
-
- mutex_exit(&ctlr->sw_mutex);
- return (memp);
-}
-
-/*
- * Function : cpqary3_cmdlist_release
- * Description : This routine releases a command block back to the
- * initialised memory pool.
- * Called By : cpqary3_transport(), cpqary3_process_pkt(),
- * cpqary3_send_NOE_command(), cpqary3_NOE_handler()
- * cpqary3_transport(), cpqary3_handle_flag_nointr()
- * cpqary3_synccmd_cleanup()
- * Parameters : pointer to Command Memory
- * flag to specify if mutex is to be held
- * Calls : None
- * Return Values: None
- */
-void
-cpqary3_cmdlist_release(cpqary3_cmdpvt_t *memp, uint8_t flag)
-{
- cpqary3_cmdmemlist_t *memlistp;
-
- if (memp == NULL)
- return;
-
- /*
- * Hold The mutex ONLY if asked to (Else it means it is already held!)
- * If both head & tail of the per-controller-memory-list are NULL,
- * add this command list to the Available Q and Update head & tail.
- * Else, append it to the Available Q.
- */
-
- memlistp =
- (cpqary3_cmdmemlist_t *)((cpqary3_t *)memp->ctlr)->cmdmemlistp;
-
- if (CPQARY3_HOLD_SW_MUTEX == flag)
- mutex_enter(&memp->ctlr->sw_mutex);
-
- if (memlistp->head == NULL) { /* obviously, tail is also NULL */
- memlistp->head = memp;
- memlistp->tail = memp;
- memp->next = NULL;
- memp->prev = NULL;
- } else {
- memlistp->tail->next = memp;
- memp->prev = memlistp->tail;
- memp->next = NULL;
- memlistp->tail = memp;
- }
-
- memp->occupied = CPQARY3_FREE;
- memp->cmdpvt_flag = 0;
- memp->pvt_pkt = NULL;
-
- if (CPQARY3_HOLD_SW_MUTEX == flag)
- mutex_exit(&memp->ctlr->sw_mutex);
-}
-
-/*
- * Function : cpqary3_memfini
- * Description : This routine frees all command blocks that was
- * initialised for the Command Memory Pool.
- * It also fress any related memory that was occupied.
- * Called By : cpqary3_cleanup(), cpqary3_meminit(),
- * cpqary3_init_ctlr_resource()
- * Parameters : per-controller, identifier(what all to clean up)
- * Calls : cpqary3_free_phyctgs_mem
- * Return Values: None
- */
-void
-cpqary3_memfini(cpqary3_t *ctlr, uint8_t level)
-{
- uint32_t mem_size;
- uint32_t CmdsOutMax;
- cpqary3_cmdpvt_t *memp;
- cpqary3_phys_hdl_addr_t *blk_ptr;
- cpqary3_phys_hdl_addr_t *tptr;
-
- ASSERT(ctlr != NULL);
- blk_ptr = (cpqary3_phys_hdl_addr_t *)ctlr->cmdmemlistp->cpqary3_phyctgp;
-
- CmdsOutMax = ctlr->ctlr_maxcmds;
-
- DTRACE_PROBE1(memfini_start, uint32_t, CmdsOutMax);
-
- /*
- * Depending upon the identifier,
- * Free Physical memory & Memory allocated to hold Block Details
- * Virtual Memory used to maintain linked list of Command Memory Pool
- * Memory which stores data relating to the Command Memory Pool
- */
-
- mutex_enter(&ctlr->sw_mutex);
- if (level & CPQARY3_PHYCTGS_DONE) {
- if (blk_ptr) {
- while (blk_ptr->next) {
- tptr = blk_ptr;
- blk_ptr = blk_ptr->next;
- cpqary3_free_phyctgs_mem(
- tptr->blk_addr, CPQARY3_FREE_PHYCTG_MEM);
- MEM_SFREE(tptr,
- sizeof (cpqary3_phys_hdl_addr_t));
- }
- cpqary3_free_phyctgs_mem(
- blk_ptr->blk_addr, CPQARY3_FREE_PHYCTG_MEM);
- MEM_SFREE(blk_ptr, sizeof (cpqary3_phys_hdl_addr_t));
- }
- }
-
- if (level & CPQARY3_CMDMEM_DONE) {
- mem_size = (uint32_t)((CmdsOutMax / 3) *
- NO_OF_CMDLIST_IN_A_BLK * sizeof (cpqary3_cmdpvt_t));
- memp = ctlr->cmdmemlistp->pool;
-
- DTRACE_PROBE2(memfini, uint32_t, mem_size, void *, memp);
- MEM_SFREE(memp, mem_size);
- }
- mutex_exit(&ctlr->sw_mutex);
-
- if (level & CPQARY3_MEMLIST_DONE) {
- mutex_enter(&ctlr->hw_mutex);
- MEM_SFREE(ctlr->cmdmemlistp, sizeof (cpqary3_cmdmemlist_t));
- mutex_exit(&ctlr->hw_mutex);
- }
-}
-
-/*
* Function : cpqary3_alloc_phyctgs_mem
* Description : This routine allocates Physically Contiguous Memory
* for Commands or Scatter/Gather.
@@ -506,7 +64,7 @@ cpqary3_memfini(cpqary3_t *ctlr, uint8_t level)
* Virtual Memory Pointer to the allocated Memory(caddr_t),
* Physical Address of the allocated Memory(phyaddr)
*/
-caddr_t
+static caddr_t
cpqary3_alloc_phyctgs_mem(cpqary3_t *ctlr, size_t size_mempool,
uint32_t *phyaddr, cpqary3_phyctg_t *phyctgp)
{
@@ -516,9 +74,6 @@ cpqary3_alloc_phyctgs_mem(cpqary3_t *ctlr, size_t size_mempool,
uint8_t cleanstat = 0;
uint32_t cookiecnt;
- RETURN_NULL_IF_NULL(ctlr);
- RETURN_NULL_IF_NULL(phyctgp);
-
/*
* Allocation of Physical Contigous Memory follws:
* allocate a handle for this memory
@@ -549,8 +104,8 @@ cpqary3_alloc_phyctgs_mem(cpqary3_t *ctlr, size_t size_mempool,
cmn_err(CE_CONT, "CPQary3: Unexpected Value %x from "
"call to allocate the DMA Handle \n", retvalue);
}
- /* Calling MEM_SFREE to free the memory */
- MEM_SFREE(phyctgp, sizeof (cpqary3_phyctg_t));
+ /* Calling kmem_free to free the memory */
+ kmem_free(phyctgp, sizeof (cpqary3_phyctg_t));
return (NULL);
}
@@ -632,7 +187,7 @@ cpqary3_alloc_phyctgs_mem(cpqary3_t *ctlr, size_t size_mempool,
* Parameters : per-physical, identifier(what all to free)
* Calls : None
*/
-void
+static void
cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *cpqary3_phyctgp, uint8_t cleanstat)
{
@@ -656,6 +211,138 @@ cpqary3_free_phyctgs_mem(cpqary3_phyctg_t *cpqary3_phyctgp, uint8_t cleanstat)
if (cleanstat & CPQARY3_DMA_ALLOC_HANDLE_DONE) {
ddi_dma_free_handle(&cpqary3_phyctgp->cpqary3_dmahandle);
}
+}
+
+static size_t
+cpqary3_round_up(size_t offset)
+{
+ size_t gran = 0x20;
+
+ return ((offset + (gran - 1)) & ~(gran - 1));
+}
+
+cpqary3_command_t *
+cpqary3_command_alloc(cpqary3_t *cpq)
+{
+ cpqary3_command_t *cpcm;
+
+ if ((cpcm = kmem_zalloc(sizeof (*cpcm), KM_NOSLEEP)) == NULL) {
+ return (NULL);
+ }
+
+ cpcm->cpcm_ctlr = cpq;
+
+ /*
+ * Grab a new tag number for this command. We aim to avoid reusing tag
+ * numbers as much as possible, so as to avoid spurious double
+ * completion from the controller.
+ */
+ mutex_enter(&cpq->sw_mutex);
+ cpcm->cpcm_tag = cpq->cpq_next_tag;
+ if (++cpq->cpq_next_tag > 0xfffff) {
+ cpq->cpq_next_tag = 0x54321;
+ }
+ mutex_exit(&cpq->sw_mutex);
+
+ size_t contig_size = 0;
+ size_t errorinfo_offset;
+
+ contig_size += cpqary3_round_up(sizeof (CommandList_t));
+
+ errorinfo_offset = contig_size;
+ contig_size += cpqary3_round_up(sizeof (ErrorInfo_t));
+
+ /*
+ * Allocate physmem for CommandList_t (cpcm_va_cmd), and ErrorInfo_t
+ * (cpcm_va_err).
+ * XXX
+ *
+ * - 0x20 aligned CommandList_t
+ * header
+ * request block
+ * error descriptor
+ * scatter/gather list
+ * - 0x20 aligned ErrorInfo_t
+ * - ...?
+ */
+
+ if ((cpcm->cpcm_va_cmd = (void *)cpqary3_alloc_phyctgs_mem(cpq,
+ contig_size, &cpcm->cpcm_pa_cmd, &cpcm->cpcm_phyctg)) == NULL) {
+ kmem_free(cpcm, sizeof (*cpcm));
+ return (NULL);
+ }
+ cpcm->cpcm_va_err = (void *)((caddr_t)cpcm->cpcm_va_cmd +
+ errorinfo_offset);
+ cpcm->cpcm_pa_err = cpcm->cpcm_pa_cmd + errorinfo_offset;
+
+ /*
+ * Ensure we asked for, and received, the correct physical alignment:
+ */
+ VERIFY0(cpcm->cpcm_pa_cmd & 0x1f);
+ VERIFY0(cpcm->cpcm_pa_err & 0x1f);
+
+ /*
+ * XXX Populate Fields.
+ */
+ bzero(cpcm->cpcm_va_cmd, contig_size);
+ cpcm->cpcm_va_cmd->Header.Tag.tag_value = cpcm->cpcm_tag;
+ cpcm->cpcm_va_cmd->ErrDesc.Addr = cpcm->cpcm_pa_err;
+ cpcm->cpcm_va_cmd->ErrDesc.Len = sizeof (ErrorInfo_t);
+
+ /*
+ * Insert into the per-controller command list.
+ */
+ mutex_enter(&cpq->sw_mutex);
+ list_insert_tail(&cpq->cpq_commands, cpcm);
+ mutex_exit(&cpq->sw_mutex);
+
+ return (cpcm);
+}
+
+cpqary3_command_internal_t *
+cpqary3_command_internal_alloc(cpqary3_t *cpq, size_t len)
+{
+ cpqary3_command_internal_t *cpcmi;
+
+ if ((cpcmi = kmem_zalloc(sizeof (*cpcmi), KM_NOSLEEP)) == NULL) {
+ return (NULL);
+ }
+
+ if ((cpcmi->cpcmi_va = (void *)cpqary3_alloc_phyctgs_mem(cpq, len,
+ &cpcmi->cpcmi_pa, &cpcmi->cpcmi_phyctg)) == NULL) {
+ kmem_free(cpcmi, sizeof (*cpcmi));
+ return (NULL);
+ }
+
+ bzero(cpcmi->cpcmi_va, cpcmi->cpcmi_len);
+
+ return (cpcmi);
+}
+
+void
+cpqary3_command_free(cpqary3_command_t *cpcm)
+{
+ cpqary3_t *cpq = cpcm->cpcm_ctlr;
+
+ /*
+ * Ensure the object we are about to free is not currently in the
+ * inflight AVL.
+ */
+ VERIFY(!cpcm->cpcm_inflight);
+
+ if (cpcm->cpcm_internal != NULL) {
+ cpqary3_command_internal_t *cpcmi = cpcm->cpcm_internal;
+
+ cpqary3_free_phyctgs_mem(&cpcmi->cpcmi_phyctg,
+ CPQARY3_FREE_PHYCTG_MEM);
+ kmem_free(cpcmi, sizeof (*cpcmi));
+ }
+
+ cpqary3_free_phyctgs_mem(&cpcm->cpcm_phyctg, CPQARY3_FREE_PHYCTG_MEM);
+
+ mutex_enter(&cpq->sw_mutex);
+ list_remove(&cpq->cpq_commands, cpcm);
+ mutex_exit(&cpq->sw_mutex);
- MEM_SFREE(cpqary3_phyctgp, sizeof (cpqary3_phyctg_t));
+ kmem_free(cpcm, sizeof (*cpcm));
}
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_noe.c b/usr/src/uts/common/io/cpqary3/cpqary3_noe.c
index 38a2d979eb..de2b4fb70d 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_noe.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_noe.c
@@ -106,10 +106,10 @@ char *log_vol_status[] = {
* [Shall fail only if memory allocation issues exist]
*/
uint8_t
-cpqary3_send_NOE_command(cpqary3_t *ctlr, cpqary3_cmdpvt_t *memp, uint8_t flag)
+cpqary3_send_NOE_command(cpqary3_t *ctlr, cpqary3_command_t *cpcm,
+ uint8_t flag)
{
uint32_t phys_addr = 0;
- NoeBuffer *databuf;
CommandList_t *cmdlist;
cpqary3_phyctg_t *phys_handle;
int rv;
@@ -135,37 +135,42 @@ cpqary3_send_NOE_command(cpqary3_t *ctlr, cpqary3_cmdpvt_t *memp, uint8_t flag)
* If Failure, WARN and RETURN.
*/
if (CPQARY3_NOE_RESUBMIT == flag) {
- if ((NULL == memp) || (NULL == memp->cmdlist_memaddr)) {
+ return (CPQARY3_FAILURE);
+#if 0
+ if (cpcm == NULL) {
cmn_err(CE_WARN, " CPQary3 : _send_NOE_command : "
"Re-Use Not possible; CommandList NULL");
return (CPQARY3_FAILURE);
}
bzero(MEM2DRVPVT(memp)->sg, sizeof (NoeBuffer));
- memp->cmdlist_memaddr->Header.Tag.drvinfo_n_err =
+ cpcm->cpcm_va_cmd->Header.Tag.drvinfo_n_err =
CPQARY3_NOECMD_SUCCESS;
+#endif
+
} else if (CPQARY3_NOE_INIT == flag) {
- phys_handle =
- (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (cpqary3_phyctg_t));
- if (!phys_handle)
+ NoeBuffer *databuf;
+
+ if ((phys_handle = kmem_zalloc(sizeof (cpqary3_phyctg_t),
+ KM_NOSLEEP)) == NULL) {
return (CPQARY3_FAILURE);
+ }
databuf = (NoeBuffer *)cpqary3_alloc_phyctgs_mem(ctlr,
sizeof (NoeBuffer), &phys_addr, phys_handle);
- if (!databuf) {
+ if (databuf == NULL) {
return (CPQARY3_FAILURE);
}
- bzero(databuf, sizeof (NoeBuffer));
+ bzero(databuf, sizeof (*databuf));
- if (NULL == (memp = cpqary3_cmdlist_occupy(ctlr))) {
+ if ((memp = cpqary3_cmdlist_occupy(ctlr)) == NULL) {
cpqary3_free_phyctgs_mem(phys_handle,
CPQARY3_FREE_PHYCTG_MEM);
return (CPQARY3_FAILURE);
}
- memp->driverdata = (cpqary3_private_t *)
- MEM_ZALLOC(sizeof (cpqary3_private_t));
- if (NULL == memp->driverdata) {
+ if ((memp->driverdata = kmem_zalloc(sizeof (cpqary3_private_t),
+ KM_NOSLEEP)) == NULL) {
cpqary3_free_phyctgs_mem(phys_handle,
CPQARY3_FREE_PHYCTG_MEM);
cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c b/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c
index 51d3c0288c..bc87d1a9f3 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_scsi.c
@@ -42,20 +42,15 @@ cpqary3_probe4targets(cpqary3_t *cpqary3p)
{
uint8_t rv;
- rv = cpqary3_probe4LVs(cpqary3p);
-
- if (CPQARY3_FAILURE == rv) {
+ if ((rv = cpqary3_probe4LVs(cpqary3p)) != CPQARY3_SUCCESS) {
return (rv);
}
- rv = cpqary3_probe4Tapes(cpqary3p);
-
- if (CPQARY3_FAILURE == rv) {
+ if ((rv = cpqary3_probe4Tapes(cpqary3p)) != CPQARY3_SUCCESS) {
return (rv);
}
return (CPQARY3_SUCCESS);
-
}
/*
@@ -69,33 +64,24 @@ cpqary3_probe4targets(cpqary3_t *cpqary3p)
* FAILURE : Build has Failed
*/
uint8_t
-cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid)
+cpqary3_build_cmdlist(cpqary3_command_t *cpcm, uint32_t tid)
{
int cntr;
- cpqary3_t *cpqary3p;
- struct buf *bfp;
+ cpqary3_t *cpq = cpcm->cpcm_ctlr;
cpqary3_tgt_t *tgtp;
CommandList_t *cmdlistp;
+ cpqary3_pkt_t *pkt = cpcm->cpcm_private;
+ struct buf *bfp = pkt->bf;
- RETURN_FAILURE_IF_NULL(cpqary3_cmdpvtp);
-
- if (NULL == (cpqary3p = cpqary3_cmdpvtp->ctlr))
- return (CPQARY3_FAILURE);
-
- bfp = (struct buf *)cpqary3_cmdpvtp->pvt_pkt->bf;
-
- tgtp = cpqary3p->cpqary3_tgtp[tid];
-
- if (!tgtp) {
+ if ((tgtp = cpq->cpqary3_tgtp[tid]) == NULL) {
return (CPQARY3_FAILURE);
}
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
+ cmdlistp = cpcm->cpcm_va_cmd;
/* Update Cmd Header */
- cmdlistp->Header.SGList = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
- cmdlistp->Header.SGTotal = cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_OSCMD_SUCCESS;
+ cmdlistp->Header.SGList = pkt->cmd_cookiecnt;
+ cmdlistp->Header.SGTotal = pkt->cmd_cookiecnt;
if (tgtp->type == CPQARY3_TARGET_CTLR) {
cmdlistp->Header.LUN.PhysDev.TargetId = 0;
@@ -112,11 +98,9 @@ cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid)
}
/* Cmd Request */
- cmdlistp->Request.CDBLen = cpqary3_cmdpvtp->pvt_pkt->cdb_len;
-
- bcopy((caddr_t)cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_cdbp,
- (caddr_t)cmdlistp->Request.CDB, cpqary3_cmdpvtp->pvt_pkt->cdb_len);
+ cmdlistp->Request.CDBLen = pkt->cdb_len;
+ bcopy(pkt->scsi_cmd_pkt->pkt_cdbp, cmdlistp->Request.CDB, pkt->cdb_len);
cmdlistp->Request.Type.Type = CISS_TYPE_CMD;
cmdlistp->Request.Type.Attribute = CISS_ATTR_ORDERED;
@@ -137,28 +121,27 @@ cpqary3_build_cmdlist(cpqary3_cmdpvt_t *cpqary3_cmdpvtp, uint32_t tid)
*/
switch (cmdlistp->Request.CDB[0]) {
- case 0x08:
- case 0x28:
- cmdlistp->Request.Type.Direction = CISS_XFER_READ;
- break;
- case 0x0A:
- case 0x2A:
- cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
- break;
+ case 0x08: /* XXX ? */
+ case 0x28: /* XXX ? */
+ cmdlistp->Request.Type.Direction = CISS_XFER_READ;
+ break;
+ case 0x0A: /* XXX ? */
+ case 0x2A: /* XXX ? */
+ cmdlistp->Request.Type.Direction = CISS_XFER_WRITE;
+ break;
}
+
/*
* NEED to increase this TimeOut value when the concerned
* targets are tape devices(i.e., we need to do it here manually).
*/
- cmdlistp->Request.Timeout = 2 *
- (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_time);
+ cmdlistp->Request.Timeout = 2 * pkt->scsi_cmd_pkt->pkt_time;
- for (cntr = 0; cntr < cpqary3_cmdpvtp->pvt_pkt->cmd_cookiecnt; cntr++) {
+ for (cntr = 0; cntr < pkt->cmd_cookiecnt; cntr++) {
cmdlistp->SG[cntr].Addr =
- cpqary3_cmdpvtp->pvt_pkt->
- cmd_dmacookies[cntr].dmac_laddress;
+ pkt->cmd_dmacookies[cntr].dmac_laddress;
cmdlistp->SG[cntr].Len = (uint32_t)
- cpqary3_cmdpvtp->pvt_pkt->cmd_dmacookies[cntr].dmac_size;
+ pkt->cmd_dmacookies[cntr].dmac_size;
}
return (CPQARY3_SUCCESS);
@@ -183,20 +166,13 @@ cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
CommandList_t *cmdlistp;
cpqary3_tgt_t *cpqtgtp;
cpqary3_tag_t *cpqary3_tagp;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
+ cpqary3_command_t *cpcm;
- /*
- * NOTE : DO NOT perform this operation for cmdlist2abortp.
- * It may be NULL
- */
- RETURN_FAILURE_IF_NULL(cpqary3p);
-
- if (target_id == CTLR_SCSI_ID)
+ if (target_id == CTLR_SCSI_ID) {
return (CPQARY3_FAILURE);
+ }
- cpqtgtp = cpqary3p->cpqary3_tgtp[target_id];
-
- if (!cpqtgtp) {
+ if ((cpqtgtp = cpqary3p->cpqary3_tgtp[target_id]) == NULL) {
return (CPQARY3_FAILURE);
}
@@ -207,15 +183,12 @@ cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
*/
/* BGB: CVFIX -> Introduced the call to cpqary3_synccmd_alloc */
- cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, 0);
- if (cpqary3_cmdpvtp == NULL)
+ if ((cpcm = cpqary3_synccmd_alloc(cpqary3p, 0)) == NULL) {
return (CPQARY3_FAILURE);
+ }
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
+ cmdlistp = cpcm->cpcm_va_cmd;
- cmdlistp->Header.SGList = 0;
- cmdlistp->Header.SGTotal = 0;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
cmdlistp->Header.LUN.PhysDev.TargetId = 0;
cmdlistp->Header.LUN.PhysDev.Bus = 0;
cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
@@ -227,11 +200,9 @@ cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
cmdlistp->Request.CDB[0] = CISS_MSG_ABORT;
- if (cmdlist2abortp) { /* Abort this Particular Task */
+ if (cmdlist2abortp != NULL) { /* Abort this Particular Task */
cmdlistp->Request.CDB[1] = CISS_ABORT_TASK;
cpqary3_tagp = (cpqary3_tag_t *)&cmdlistp->Request.CDB[4];
- cpqary3_tagp->drvinfo_n_err =
- cmdlist2abortp->Header.Tag.drvinfo_n_err;
cpqary3_tagp->tag_value = cmdlist2abortp->Header.Tag.tag_value;
} else { /* Abort all tasks for this Target */
cmdlistp->Request.CDB[1] = CISS_ABORT_TASKSET;
@@ -248,26 +219,21 @@ cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
}
}
- /* PERF */
-
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
-
- /* PERF */
+ cpcm->cpcm_complete = cpqary3_synccmd_complete;
/* BGB: CVFIX -> Introduced a call to cpqary3_synccmd_send */
- if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 30000,
+ if (cpqary3_synccmd_send(cpqary3p, cpcm, 30000,
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- if (cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
- CPQARY3_SYNCCMD_FAILURE) {
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ if (cmdlistp->Header.Tag.error != 0) {
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_SUCCESS);
@@ -283,11 +249,11 @@ cpqary3_send_abortcmd(cpqary3_t *cpqary3p, uint16_t target_id,
* cpqary3_synccmd_free()
* Return Values: None
*/
-void
+int
cpqary3_flush_cache(cpqary3_t *cpqary3p)
{
- CommandList_t *cmdlistp;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
+ cpqary3_command_t *cpcm;
+ CommandList_t *cmdlistp;
/*
* Occupy the Command List
@@ -299,15 +265,14 @@ cpqary3_flush_cache(cpqary3_t *cpqary3p)
ASSERT(cpqary3p != NULL);
/* grab a command and allocate a dma buffer */
- cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p,
- sizeof (flushcache_buf_t));
- if (cpqary3_cmdpvtp == NULL)
- return;
+ if ((cpcm = cpqary3_synccmd_alloc(cpqary3p,
+ sizeof (flushcache_buf_t))) == NULL) {
+ dev_err(cpqary3p->dip, CE_WARN, "flush cache failed: memory");
+ return (ENOMEM);
+ }
+
+ cmdlistp = cpcm->cpcm_va_cmd;
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
- cmdlistp->Header.SGList = 1;
- cmdlistp->Header.SGTotal = 1;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
cmdlistp->Header.LUN.PhysDev.TargetId = 0;
cmdlistp->Header.LUN.PhysDev.Bus = 0;
cmdlistp->Header.LUN.PhysDev.Mode = PERIPHERIAL_DEV_ADDR;
@@ -321,21 +286,17 @@ cpqary3_flush_cache(cpqary3_t *cpqary3p)
cmdlistp->Request.CDB[6] = CISS_FLUSH_CACHE; /* 0xC2 */
cmdlistp->Request.CDB[8] = 0x02;
- /* PERF */
+ cpcm->cpcm_complete = cpqary3_synccmd_complete;
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
-
- /* PERF */
-
- if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
+ if (cpqary3_synccmd_send(cpqary3p, cpcm, 90000,
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
- cmn_err(CE_WARN, "CPQary3 %s : Flush Cache Operation"
- "Failed, Timeout", cpqary3p->hba_name);
- return;
+ dev_err(cpqary3p->dip, CE_WARN, "flush cache failed: timeout");
+ cpqary3_synccmd_free(cpqary3p, cpcm);
+ return (ETIMEDOUT);
}
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
+ return (0);
}
/*
@@ -359,7 +320,7 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p)
uint32_t data_addr_len;
rll_data_t *rllp;
CommandList_t *cmdlistp;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
+ cpqary3_command_t *cpcm;
/*
* Occupy the Command List
@@ -369,19 +330,14 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p)
* Submit and Poll for completion
*/
- RETURN_FAILURE_IF_NULL(cpqary3p);
-
- /* Sync Changes */
- cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rll_data_t));
- if (cpqary3_cmdpvtp == NULL)
+ if ((cpcm = cpqary3_synccmd_alloc(cpqary3p,
+ sizeof (rll_data_t))) == NULL) {
return (CPQARY3_FAILURE);
+ }
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
- rllp = (rll_data_t *)cpqary3_cmdpvtp->driverdata->sg;
+ cmdlistp = cpcm->cpcm_va_cmd;
+ rllp = cpcm->cpcm_internal->cpcmi_va;
- cmdlistp->Header.SGList = 1;
- cmdlistp->Header.SGTotal = 1;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_12;
@@ -399,30 +355,25 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p)
cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
DTRACE_PROBE2(rll_cmd_send, CommandList_t *, cmdlistp,
- cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
+ cpqary3_cmdpvt_t *, cpcm);
- /* PERF */
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
- /* PERF */
+ cpcm->cpcm_complete = cpqary3_synccmd_complete;
- if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
+ if (cpqary3_synccmd_send(cpqary3p, cpcm, 90000,
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
- CPQARY3_SYNCCMD_FAILURE) &&
- (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
- CISS_CMD_DATA_UNDERRUN)) {
- cmn_err(CE_WARN, "CPQary3 : Probe for logical targets "
- "returned ERROR !");
+ if ((cmdlistp->Header.Tag.error != 0) &&
+ (cpcm->cpcm_va_err->CommandStatus != CISS_CMD_DATA_UNDERRUN)) {
+ dev_err(cpqary3p->dip, CE_WARN, "probe for logical targets "
+ "failed");
DTRACE_PROBE1(rll_cmd_fail,
- ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ ErrorInfo_t *, cpcm->cpcm_va_err);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- /* Sync Changes */
log_lun_no = ((rllp->lunlist_byte0 + (rllp->lunlist_byte1 << 8) +
(rllp->lunlist_byte2 << 16) + (rllp->lunlist_byte3 << 24)) / 8);
@@ -433,6 +384,7 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p)
* The following is to restrict the maximum number of supported logical
* volumes to 32. This is very important as controller support upto 128
* logical volumes and this driver implementation supports only 32.
+ * XXX ... what?
*/
if (log_lun_no > MAX_LOGDRV) {
@@ -454,128 +406,81 @@ cpqary3_probe4LVs(cpqary3_t *cpqary3p)
/*
- * Depending upon the value of the variable legacy_mapping set in
- * cpqary3_attach(),
- * the target mapping algorithm to be used by the driver is decided.
- *
- * If the value of legacy_mapping is set to one, in the case of
- * Logical Drives with holes,
- * Targets will be renumbered by the driver as shown below
- * Below example makes the mapping logic clear.
+ * The Logical Drive numbers will not be renumbered in the case of
+ * holes, and the mapping will be done as shown below:
*
- * Logical Drive 0 in the HBA -> Target ID 0 i.e., cXt0dXsx
- * Logical Drive 2 in the HBA -> Target ID 1 i.e., cXt1dXsX
- * Logical Drive 3 in the HBA -> Target ID 2 i.e., cXt2dXsX
- *
- * If the value of legacy_mapping is not one, then the Logical
- * Drive numbers will
- * not be renumbered in the case of holes, and the mapping
- * will be done as shown below
- * This will be the default mapping from 1.80 cpqary3 driver.
- *
- * Logical Drive 0 in the HBA -> Target ID 0 i.e. cXt0dXsx
+ * Logical Drive 0 in the HBA -> Target ID 0 i.e. cXt0dXsx
* Logical Drive 2 in the HBA -> Target ID 2 i.e. cXt2dXsX
* Logical Drive 3 in the HBA -> Target ID 3 i.e. cXt3dXsX
*/
+ /*
+ * Fix for QXCR1000446657: Logical drives are re numbered after
+ * deleting a Logical drive.
+ * We are using new indexing mechanism to fill the
+ * cpqary3_tgtp[],
+ * Check given during memory allocation of cpqary3_tgtp
+ * elements, so that memory is not re-allocated each time the
+ * cpqary3_probe4LVs() is called.
+ * Check given while freeing the memory of the cpqary3_tgtp[]
+ * elements, when a hole is found in the Logical Drives
+ * configured.
+ */
- if (cpqary3p->legacy_mapping == 1) {
- for (cntr = 0; cntr < log_lun_no; cntr++) {
- i = ((cntr < CTLR_SCSI_ID) ?
- cntr : cntr + CPQARY3_TGT_ALIGNMENT);
- if (!(cpqary3p->cpqary3_tgtp[i] = (cpqary3_tgt_t *)
- MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
- cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
- "targets, Memory Allocation Failure");
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ /* ensure that the loop will break for cntr = 32 in any case */
+ for (cntr = 0; ((ld_count < log_lun_no) && (cntr < MAX_LOGDRV));
+ cntr++) {
+ i = ((cntr < CTLR_SCSI_ID) ?
+ cntr : cntr + CPQARY3_TGT_ALIGNMENT);
+ lun_id = (rllp->ll_data[ld_count].logical_id & 0xFFFF);
+ if (cntr != lun_id) {
+ if (cpqary3p->cpqary3_tgtp[i]) {
+ kmem_free(cpqary3p->cpqary3_tgtp[i],
+ sizeof (cpqary3_tgt_t));
+ cpqary3p->cpqary3_tgtp[i] = NULL;
+ }
+ } else {
+ if (cpqary3p->cpqary3_tgtp[i] == NULL &&
+ !(cpqary3p->cpqary3_tgtp[i] =
+ (cpqary3_tgt_t *)kmem_zalloc(
+ sizeof (cpqary3_tgt_t), KM_NOSLEEP))) {
+ cmn_err(CE_WARN,
+ "CPQary3 : Failed to Detect "
+ "targets, Memory Allocation "
+ "Failure");
+ /* Sync Changes */
+ cpqary3_synccmd_free(cpqary3p, cpcm);
+ /* Sync Changes */
return (CPQARY3_FAILURE);
}
-
cpqary3p->cpqary3_tgtp[i]->logical_id =
- rllp->ll_data[cntr].logical_id;
-
+ rllp->ll_data[ld_count].logical_id;
cpqary3p->cpqary3_tgtp[i]->type =
CPQARY3_TARGET_LOG_VOL;
- DTRACE_PROBE2(lvlun_remapped,
- cpqary3_tgt_t *, cpqary3p->cpqary3_tgtp[i],
- rpl_data_t *, &rllp->ll_data[cntr]);
- }
- } else {
- /*
- * Fix for QXCR1000446657: Logical drives are re numbered after
- * deleting a Logical drive.
- * We are using new indexing mechanism to fill the
- * cpqary3_tgtp[],
- * Check given during memory allocation of cpqary3_tgtp
- * elements, so that memory is not re-allocated each time the
- * cpqary3_probe4LVs() is called.
- * Check given while freeing the memory of the cpqary3_tgtp[]
- * elements, when a hole is found in the Logical Drives
- * configured.
- */
+ /*
+ * Send "BMIC sense logical drive status
+ * command to set the target type to
+ * CPQARY3_TARGET_NONE in case of logical
+ * drive failure
+ */
- /* ensure that the loop will break for cntr = 32 in any case */
- for (cntr = 0; ((ld_count < log_lun_no) && (cntr < MAX_LOGDRV));
- cntr++) {
- i = ((cntr < CTLR_SCSI_ID) ?
- cntr : cntr + CPQARY3_TGT_ALIGNMENT);
- lun_id = (rllp->ll_data[ld_count].logical_id & 0xFFFF);
- if (cntr != lun_id) {
- if (cpqary3p->cpqary3_tgtp[i]) {
- MEM_SFREE(cpqary3p->cpqary3_tgtp[i],
- sizeof (cpqary3_tgt_t));
- cpqary3p->cpqary3_tgtp[i] = NULL;
- }
- } else {
- if (cpqary3p->cpqary3_tgtp[i] == NULL &&
- !(cpqary3p->cpqary3_tgtp[i] =
- (cpqary3_tgt_t *)MEM_ZALLOC(
- sizeof (cpqary3_tgt_t)))) {
- cmn_err(CE_WARN,
- "CPQary3 : Failed to Detect "
- "targets, Memory Allocation "
- "Failure");
- /* Sync Changes */
- cpqary3_synccmd_free(cpqary3p,
- cpqary3_cmdpvtp);
- /* Sync Changes */
- return (CPQARY3_FAILURE);
- }
- cpqary3p->cpqary3_tgtp[i]->logical_id =
- rllp->ll_data[ld_count].logical_id;
- cpqary3p->cpqary3_tgtp[i]->type =
- CPQARY3_TARGET_LOG_VOL;
-
- /*
- * Send "BMIC sense logical drive status
- * command to set the target type to
- * CPQARY3_TARGET_NONE in case of logical
- * drive failure
- */
-
- ld_count++;
- }
+ ld_count++;
}
-
}
- /* HPQacucli Changes */
for (; cntr < MAX_LOGDRV; cntr++) {
cpqary3_tgt_t *t;
i = ((cntr < CTLR_SCSI_ID) ?
cntr : cntr + CPQARY3_TGT_ALIGNMENT);
t = cpqary3p->cpqary3_tgtp[i];
cpqary3p->cpqary3_tgtp[i] = NULL;
- if (t) {
- MEM_SFREE(t, sizeof (*t));
+ if (t != NULL) {
+ kmem_free(t, sizeof (*t));
}
}
- /* HPQacucli Changes */
- /* Sync Changes */
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
- /* Sync Changes */
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_SUCCESS);
}
@@ -599,7 +504,7 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
uint32_t data_addr_len;
rpl_data_t *rplp;
CommandList_t *cmdlistp;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
+ cpqary3_command_t *cpcm;
/*
* Occupy the Command List
@@ -609,21 +514,16 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
* Submit and Poll for completion
*/
- RETURN_FAILURE_IF_NULL(cpqary3p);
-
- /* Sync Changes */
- cpqary3_cmdpvtp = cpqary3_synccmd_alloc(cpqary3p, sizeof (rpl_data_t));
- if (cpqary3_cmdpvtp == NULL)
+ if ((cpcm = cpqary3_synccmd_alloc(cpqary3p, sizeof (rpl_data_t))) ==
+ NULL) {
return (CPQARY3_FAILURE);
+ };
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
- rplp = (rpl_data_t *)cpqary3_cmdpvtp->driverdata->sg;
+ cmdlistp = cpcm->cpcm_va_cmd;
+ rplp = cpcm->cpcm_internal->cpcmi_va;
/* Sync Changes */
- cmdlistp->Header.SGList = 1;
- cmdlistp->Header.SGTotal = 1;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
cmdlistp->Header.LUN.PhysDev.TargetId = 0;
cmdlistp->Header.LUN.PhysDev.Bus = 0;
cmdlistp->Header.LUN.PhysDev.Mode = MASK_PERIPHERIAL_DEV_ADDR;
@@ -643,32 +543,25 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
cmdlistp->Request.CDB[9] = (data_addr_len) & 0xff;
DTRACE_PROBE2(tape_probe_cmd_send,
- CommandList_t *, cmdlistp, cpqary3_cmdpvt_t *, cpqary3_cmdpvtp);
+ CommandList_t *, cmdlistp, cpqary3_command_t *, cpcm);
- /* PERF */
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
- /* PERF */
-
- /* Sync Changes */
+ cpcm->cpcm_complete = cpqary3_synccmd_complete;
- if (cpqary3_synccmd_send(cpqary3p, cpqary3_cmdpvtp, 90000,
+ if (cpqary3_synccmd_send(cpqary3p, cpcm, 90000,
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- if ((cpqary3_cmdpvtp->cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
- CPQARY3_SYNCCMD_FAILURE) &&
- (cpqary3_cmdpvtp->errorinfop->CommandStatus !=
- CISS_CMD_DATA_UNDERRUN)) {
+ if ((cmdlistp->Header.Tag.error != 0) &&
+ (cpcm->cpcm_va_err->CommandStatus != CISS_CMD_DATA_UNDERRUN)) {
cmn_err(CE_WARN, "CPQary3 : Probe for physical targets "
"returned ERROR !");
DTRACE_PROBE1(tape_probe_cmdfail,
- ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
+ ErrorInfo_t *, cpcm->cpcm_va_err);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
- /* Sync Changes */
phy_lun_no = ((rplp->lunlist_byte0 +
(rplp->lunlist_byte1 << 8) +
@@ -693,7 +586,6 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
* if the controller is SAS or CISS and then assigning the value of the
* TAPE BASE accordingly
*/
-
if (cpqary3p->bddef->bd_flags & SA_BD_SAS) {
ii = 0x41; /* MAX_LOGDRV + 1 - 64 + 1 */
} else {
@@ -705,11 +597,10 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
if (cpqary3p->cpqary3_tgtp[ii] == NULL &&
!(cpqary3p->cpqary3_tgtp[ii] =
(cpqary3_tgt_t *)
- MEM_ZALLOC(sizeof (cpqary3_tgt_t)))) {
+ kmem_zalloc(sizeof (cpqary3_tgt_t), KM_NOSLEEP))) {
cmn_err(CE_WARN, "CPQary3 : Failed to Detect "
"targets, Memory Allocation Failure");
- cpqary3_synccmd_free(cpqary3p,
- cpqary3_cmdpvtp);
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_FAILURE);
}
@@ -726,9 +617,7 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
}
}
- /* Sync Changes */
- cpqary3_synccmd_free(cpqary3p, cpqary3_cmdpvtp);
- /* Sync Changes */
+ cpqary3_synccmd_free(cpqary3p, cpcm);
return (CPQARY3_SUCCESS);
@@ -745,30 +634,36 @@ cpqary3_probe4Tapes(cpqary3_t *cpqary3p)
* Return Values: None
*/
void
-cpqary3_synccmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
+cpqary3_synccmd_complete(cpqary3_command_t *cpcm)
{
- cpqary3_t *cpqary3p;
+ cpqary3_t *cpq = cpcm->cpcm_ctlr;
- ASSERT(cpqary3_cmdpvtp != NULL);
+ VERIFY(MUTEX_HELD(&cpq->sw_mutex));
+ /*
+ * XXX This flag is set by the periodic function which we have
+ * disabled for now...
+ */
+#if 0
if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) {
cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
return;
}
+#endif
- cpqary3p = cpqary3_cmdpvtp->ctlr;
-
- if (cpqary3_cmdpvtp->cmdpvt_flag == CPQARY3_SYNC_TIMEOUT) {
+ switch (cpcm->cpcm_synccmd_status) {
+ case CPQARY3_SYNCCMD_STATUS_TIMEOUT:
/*
* The submitter has abandoned this command, so we
* have to free the resources here.
*/
- mutex_exit(&(cpqary3p->sw_mutex));
- cpqary3_synccmd_cleanup(cpqary3_cmdpvtp);
- mutex_enter(&(cpqary3p->sw_mutex));
- } else {
- /* submitter is waiting; wake him up */
- cpqary3_cmdpvtp->cmdpvt_flag = 0;
+ mutex_exit(&cpq->sw_mutex);
+ cpqary3_command_free(cpcm);
+ mutex_enter(&cpq->sw_mutex);
+ return;
+
+ case CPQARY3_SYNCCMD_STATUS_SUBMITTED:
+ cpcm->cpcm_synccmd_status = CPQARY3_SYNCCMD_STATUS_NONE;
/*
* Fix for Flush Cache Operation Timed out issue:
@@ -776,6 +671,13 @@ cpqary3_synccmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
* We need to use cv_broadcast which unblocks
* all the blocked threads()
*/
- cv_broadcast(&(cpqary3p->cv_ioctl_wait));
+ cv_broadcast(&cpq->cv_ioctl_wait);
+ return;
+
+ case CPQARY3_SYNCCMD_STATUS_NONE:
+ panic("synccmd completed but status is NONE");
+ break;
}
+
+ panic("unknown synccmd status");
}
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c b/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c
index 7275c656a1..66fc0dbd14 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c
@@ -30,7 +30,6 @@
uint8_t cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p);
uint8_t cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p);
uint8_t cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p);
-uint8_t cpqary3_check_ctlr_init(cpqary3_t *);
/*
* Function : cpqary3_check_simple_ctlr_intr
@@ -112,80 +111,105 @@ cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p)
return (CPQARY3_FAILURE);
}
-
/*
- * Function : cpqary3_retrieve
- * Description : This routine retrieves the completed command from the
- * controller reply queue.
- * and processes the completed commands.
- * Called By : cpqary3_sw_isr(), cpqary3_handle_flag_nointr()
- * Parameters : per-controller
- * Calls : packet completion routines
- * Return Values: SUCCESS : A completed command has been retrieved
- * and processed.
- * FAILURE : No completed command was in the controller.
+ * Read tags and process completion of the associated command until the supply
+ * of tags is exhausted.
*/
-uint8_t
-cpqary3_retrieve(cpqary3_t *cpqary3p)
+void
+cpqary3_retrieve_simple(cpqary3_t *cpq, uint32_t watchfor, boolean_t *found)
{
- uint32_t tag;
- uint32_t CmdsOutMax;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
- cpqary3_drvr_replyq_t *replyq_ptr;
+ uint32_t opq;
- /*
- * Get the Reply Command List Addr
- * Update the returned Tag in that particular command structure.
- * If a valid one, de-q that from the SUBMITTED Q and
- * enqueue that to the RETRIEVED Q.
- */
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+ VERIFY(MUTEX_HELD(&cpq->sw_mutex));
- RETURN_FAILURE_IF_NULL(cpqary3p);
+ while ((opq = ddi_get32(cpq->opq_handle, cpq->opq)) != 0xffffffff) {
+ cpqary3_command_t *cpcm;
+ uint32_t tag = opq >> 2; /* XXX */
- /* PERF */
- replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
- CmdsOutMax = cpqary3p->ctlr_maxcmds;
+ if ((cpcm = cpqary3_lookup_inflight(cpq, tag)) == NULL) {
+ dev_err(cpq->dip, CE_WARN, "spurious tag %x", tag);
+ continue;
+ }
- while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
- replyq_ptr->cyclic_indicator) {
- /* command has completed */
- /* Get the tag */
+ avl_remove(&cpq->cpq_inflight, cpcm);
+ cpcm->cpcm_inflight = B_FALSE;
+ cpcm->cpcm_error = (opq & (0x1 << 1)) != 0;
- tag = replyq_ptr->replyq_headptr[0];
- if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax / 3) * 3) {
- cmn_err(CE_WARN,
- "CPQary3 : HBA returned Spurious Tag");
- return (CPQARY3_FAILURE);
+ if (found != NULL && cpcm->cpcm_tag == watchfor) {
+ *found = B_TRUE;
}
- cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
- tag >> CPQARY3_GET_MEM_TAG];
- cpqary3_cmdpvtp->cmdlist_memaddr->
- Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
- mutex_enter(&cpqary3p->sw_mutex);
- cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
- mutex_exit(&cpqary3p->sw_mutex);
-
- /* Traverse to the next command in reply queue */
-
- ++replyq_ptr->index;
- if (replyq_ptr->index == replyq_ptr->max_index) {
- replyq_ptr->index = 0;
- /* Toggle at wraparound */
- replyq_ptr->cyclic_indicator =
- (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
- replyq_ptr->replyq_headptr =
- /* LINTED: alignment */
- (uint32_t *)(replyq_ptr->replyq_start_addr);
- } else {
- replyq_ptr->replyq_headptr += 2;
- }
+ mutex_exit(&cpq->hw_mutex);
+ cpcm->cpcm_complete(cpcm);
+ mutex_enter(&cpq->hw_mutex);
}
- /* PERF */
+}
- return (CPQARY3_SUCCESS);
+void
+cpqary3_retrieve_performant(cpqary3_t *cpq, uint32_t watchfor, boolean_t *found)
+{
+ cpqary3_replyq_t *cprq = &cpq->cpq_replyq;
+
+ for (;;) {
+ uint32_t ent = cprq->cprq_tags[2 * cprq->cprq_read_index];
+ uint32_t tag = ent >> 2; /* XXX */
+ cpqary3_command_t *cpcm;
+
+ if ((ent & 0x1) != cprq->cprq_cycle_indicator) {
+ break;
+ }
+
+ if ((cpcm = cpqary3_lookup_inflight(cpq, tag)) == NULL) {
+ dev_err(cpq->dip, CE_WARN, "spurious tag %x", tag);
+ continue;
+ }
+
+ avl_remove(&cpq->cpq_inflight, cpcm);
+ cpcm->cpcm_inflight = B_FALSE;
+ cpcm->cpcm_error = (ent & (0x1 << 1)) != 0;
+
+ if (found != NULL && cpcm->cpcm_tag == watchfor) {
+ *found = B_TRUE;
+ }
+
+ cpcm->cpcm_complete(cpcm);
+
+ if (++cprq->cprq_read_index >= cprq->cprq_ntags) {
+ cprq->cprq_read_index = 0;
+ if (cprq->cprq_cycle_indicator == 1) {
+ cprq->cprq_cycle_indicator = 0;
+ } else {
+ cprq->cprq_cycle_indicator = 1;
+ }
+ }
+ }
}
+/*
+ * XXX
+ */
+int
+cpqary3_retrieve(cpqary3_t *cpq)
+{
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+ VERIFY(MUTEX_HELD(&cpq->sw_mutex));
+
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ cpqary3_retrieve_simple(cpq, 0, NULL);
+ return (CPQARY3_SUCCESS);
+
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ cpqary3_retrieve_performant(cpq, 0, NULL);
+ return (CPQARY3_SUCCESS);
+
+ case CPQARY3_CTLR_MODE_UNKNOWN:
+ break;
+ }
+
+ panic("unknown controller mode");
+}
/*
* Function : cpqary3_poll_retrieve
@@ -199,79 +223,27 @@ cpqary3_retrieve(cpqary3_t *cpqary3p)
* If not return failure.
*/
uint8_t
-cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag)
+cpqary3_poll_retrieve(cpqary3_t *cpq, uint32_t poll_tag)
{
- uint32_t tag;
- uint32_t CmdsOutMax;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
- cpqary3_drvr_replyq_t *replyq_ptr;
- uint32_t temp_tag;
- uint8_t tag_flag = 0;
+ boolean_t found = B_FALSE;
- RETURN_FAILURE_IF_NULL(cpqary3p);
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+ VERIFY(MUTEX_HELD(&cpq->sw_mutex));
- /* PERF */
- replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
- CmdsOutMax = cpqary3p->cmdmemlistp->max_memcnt;
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ cpqary3_retrieve_simple(cpq, poll_tag, &found);
+ break;
- if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
- while ((tag = ddi_get32(cpqary3p->opq_handle,
- (uint32_t *)cpqary3p->opq)) != 0xFFFFFFFF) {
- cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
- tag >> CPQARY3_GET_MEM_TAG];
- cpqary3_cmdpvtp->cmdlist_memaddr->
- Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
- temp_tag = cpqary3_cmdpvtp->tag.tag_value;
-
- if (temp_tag == poll_tag)
- tag_flag = 1;
- cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
- }
- } else {
- while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
- replyq_ptr->cyclic_indicator) {
- /* command has completed */
- /* Get the tag */
- tag = replyq_ptr->replyq_headptr[0];
-
- if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax/3)*3) {
- cmn_err(CE_WARN,
- "CPQary3 : HBA returned Spurious Tag");
- return (CPQARY3_FAILURE);
- }
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ cpqary3_retrieve_performant(cpq, poll_tag, &found);
+ break;
- cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
- tag >> CPQARY3_GET_MEM_TAG];
- cpqary3_cmdpvtp->cmdlist_memaddr->
- Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
- temp_tag = cpqary3_cmdpvtp->tag.tag_value;
-
- if (temp_tag == poll_tag)
- tag_flag = 1;
-
- cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
-
- /* Traverse to the next command in reply queue */
- ++replyq_ptr->index;
- if (replyq_ptr->index == replyq_ptr->max_index) {
- replyq_ptr->index = 0;
- /* Toggle at wraparound */
- replyq_ptr->cyclic_indicator =
- (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
- replyq_ptr->replyq_headptr =
- /* LINTED: alignment */
- (uint32_t *)(replyq_ptr->replyq_start_addr);
- } else {
- replyq_ptr->replyq_headptr += 2;
- }
- }
- }
- /* PERF */
- if (tag_flag) {
- return (CPQARY3_SUCCESS);
+ default:
+ panic("unknown controller mode");
}
- return (CPQARY3_FAILURE);
+ return (found ? CPQARY3_SUCCESS : CPQARY3_FAILURE);
}
/*
@@ -286,38 +258,59 @@ cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag)
* Return Values: None
*/
int
-cpqary3_submit(cpqary3_t *cpqary3p, uint32_t cmd_phyaddr)
+cpqary3_submit(cpqary3_t *cpq, cpqary3_command_t *cpcm)
{
- ASSERT(cpqary3p != NULL);
- ASSERT(MUTEX_HELD(&cpqary3p->hw_mutex));
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
/*
* If a controller lockup has been detected, reject new command
* submissions.
*/
- if (cpqary3p->controller_lockup == CPQARY3_TRUE) {
+ if (cpq->controller_lockup == CPQARY3_TRUE) {
return (EIO);
}
/*
- * Write the Physical Address of the command-to-be-submitted
- * into the Controller's Inbound Post Q.
+ * XXX
+ * At present, we have no good way to "re-use" an allocated
+ * command structure. Let's catch any places where this happens.
*/
- if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
- ddi_put32(cpqary3p->ipq_handle, cpqary3p->ipq, cmd_phyaddr);
- } else {
- /* The driver always uses the 0th block fetch count always */
- uint32_t phys_addr = cmd_phyaddr | 0 | 0x1;
-
- ddi_put32(cpqary3p->ipq_handle, cpqary3p->ipq, phys_addr);
- }
+ VERIFY(!cpcm->cpcm_used);
+ cpcm->cpcm_used = B_TRUE;
/*
- * Command submission can NEVER FAIL since the number of commands that
- * can reside in the controller at any time is 1024 and our memory
- * allocation is for 225 commands ONLY. Thus, at any given time the
- * maximum number of commands in the controller is 225.
+ * Insert this command into the inflight AVL.
*/
+ avl_index_t where;
+ if (avl_find(&cpq->cpq_inflight, cpcm, &where) != NULL) {
+ dev_err(cpq->dip, CE_PANIC, "duplicate submit tag %x",
+ cpcm->cpcm_tag);
+ }
+ avl_insert(&cpq->cpq_inflight, cpcm, where);
+
+ VERIFY(cpcm->cpcm_inflight == B_FALSE);
+ cpcm->cpcm_inflight = B_TRUE;
+
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ ddi_put32(cpq->ipq_handle, cpq->ipq, cpcm->cpcm_pa_cmd);
+ break;
+
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ /*
+ * XXX The driver always uses the 0th block fetch count always
+ *
+ * (NB: from spec, the 0x1 here sets "pull from host memory"
+ * mode, and the 0 represents "pull just one command record"
+ */
+ ddi_put32(cpq->ipq_handle, cpq->ipq,
+ cpcm->cpcm_pa_cmd | 0 | 0x1);
+ break;
+
+ default:
+ panic("unknown controller mode");
+ }
+
return (0);
}
@@ -332,25 +325,34 @@ cpqary3_submit(cpqary3_t *cpqary3p, uint32_t cmd_phyaddr)
* Return Values: None
*/
void
-cpqary3_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag)
+cpqary3_intr_onoff(cpqary3_t *cpq, uint8_t flag)
{
/*
* Read the Interrupt Mask Register.
*/
- uint32_t imr = ddi_get32(cpqary3p->imr_handle, cpqary3p->imr);
+ uint32_t imr = ddi_get32(cpq->imr_handle, cpq->imr);
- /*
- * Enable or disable interrupts from the controller based on the flag.
- */
- if (flag == CPQARY3_INTR_ENABLE) {
- imr &= ~cpqary3p->bddef->bd_intrmask;
- } else {
- VERIFY(flag == CPQARY3_INTR_DISABLE);
+ VERIFY(flag == CPQARY3_INTR_ENABLE || flag == CPQARY3_INTR_DISABLE);
+
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ if (flag == CPQARY3_INTR_ENABLE) {
+ imr &= ~INTR_SIMPLE_MASK;
+ } else {
+ imr |= INTR_SIMPLE_MASK;
+ }
+ break;
- imr |= cpqary3p->bddef->bd_intrmask;
+ default:
+ if (flag == CPQARY3_INTR_ENABLE) {
+ imr &= ~cpq->bddef->bd_intrmask;
+ } else {
+ imr |= cpq->bddef->bd_intrmask;
+ }
+ break;
}
- ddi_put32(cpqary3p->imr_handle, cpqary3p->imr, imr);
+ ddi_put32(cpq->imr_handle, cpq->imr, imr);
}
/*
@@ -501,340 +503,327 @@ cpqary3_cfgtbl_transport_confirm(cpqary3_t *cpqary3p, int xport)
return (CPQARY3_SUCCESS);
}
-/*
- * Function : cpqary3_init_ctlr
- * Description : This routine initialises the HBA to Simple Transport
- * Method. Refer to CISS for more information.
- * It checks the readiness of the HBA.
- * Called By : cpqary3_init_ctlr_resource()
- * Parameters : per-controller(), physical address()
- * Calls : cpqary3_check_ctlr_init
- * Return Values: SUCCESS / FAILURE
- * [Shall return failure if the initialization of the
- * controller to the Simple Transport Method fails]
- */
-uint8_t
-cpqary3_init_ctlr(cpqary3_t *cpqary3p)
+uint32_t
+cpqary3_ctlr_get_cmdsoutmax(cpqary3_t *cpq)
{
- uint8_t signature[4] = { 'C', 'I', 'S', 'S' };
- CfgTable_t *ctp;
- volatile CfgTrans_Perf_t *perf_cfg;
- cpqary3_phyctg_t *cpqary3_phyctgp;
- uint32_t phy_addr;
- size_t cmd_size;
- uint32_t queue_depth;
- uint32_t CmdsOutMax;
- uint32_t BlockFetchCnt[8];
- caddr_t replyq_start_addr = NULL;
- /* SG */
- uint32_t max_blk_fetch_cnt = 0;
- uint32_t max_sg_cnt = 0;
- uint32_t optimal_sg = 0;
- uint32_t optimal_sg_size = 0;
- /* Header + Request + Error */
- uint32_t size_of_HRE = 0;
- uint32_t size_of_cmdlist = 0;
- /* SG */
+ uint32_t val;
- RETURN_FAILURE_IF_NULL(cpqary3p);
- ctp = (CfgTable_t *)cpqary3p->ct;
- perf_cfg = (CfgTrans_Perf_t *)cpqary3p->cp;
+ if (cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_PERFORMANT) {
+ if ((val = ddi_get32(cpq->ct_handle,
+ &cpq->ct->MaxPerfModeCmdsOutMax)) != 0) {
+ return (val);
+ }
+ }
- /* QUEUE CHANGES */
- cpqary3p->drvr_replyq =
- (cpqary3_drvr_replyq_t *)MEM_ZALLOC(sizeof (cpqary3_drvr_replyq_t));
- /* QUEUE CHANGES */
+ return (ddi_get32(cpq->ct_handle, &cpq->ct->CmdsOutMax));
+}
- if (!cpqary3_check_ctlr_init(cpqary3p))
- return (CPQARY3_FAILURE);
+uint32_t
+cpqary3_ctlr_get_hostdrvsup(cpqary3_t *cpq)
+{
+ if ((!cpq->bddef->bd_is_e200) && (!cpq->bddef->bd_is_ssll)) {
+ uint32_t val = ddi_get32(cpq->ct_handle,
+ &cpq->ct->HostDrvrSupport);
- DTRACE_PROBE1(ctlr_init_start, CfgTable_t *, ctp);
+ /*
+ * XXX This is "bit 2" in the "Host Driver Specific Support"
+ * field of the Configuration Table. According to the CISS
+ * spec, this is "Interrupt Host upon Controller Lockup"
+ * Enable.
+ *
+ * It's not clear why we _set_ this bit, but then it's not yet
+ * clear how this table entry is even supposed to work.
+ */
+ val |= 0x04;
- /*
- * The configuration table contains an ASCII signature ("CISS") which
- * should be checked as we initialise the controller.
- * See: "9.1 Configuration Table" in CISS Specification.
- */
- for (unsigned i = 0; i < 4; i++) {
- if (ddi_get8(cpqary3p->ct_handle, &ctp->Signature[i]) !=
- signature[i]) {
- dev_err(cpqary3p->dip, CE_WARN, "invalid signature "
- "detected");
- return (CPQARY3_FAILURE);
- }
+ ddi_put32(cpq->ct_handle, &cpq->ct->HostDrvrSupport, val);
}
- if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
-
- if (CmdsOutMax == 0) {
- cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
- "Commands set to Zero\n");
- cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
- "initialization \n");
- return (CPQARY3_FAILURE);
- }
+ return (ddi_get32(cpq->ct_handle, &cpq->ct->HostDrvrSupport));
+}
- cpqary3p->ctlr_maxcmds = CmdsOutMax;
- cpqary3p->sg_cnt = CPQARY3_SG_CNT;
-
- queue_depth = cpqary3p->ctlr_maxcmds;
- cmd_size = (8 * queue_depth);
- /* QUEUE CHANGES */
- cpqary3p->drvr_replyq->cyclic_indicator =
- CPQARY3_REPLYQ_INIT_CYCLIC_IND;
- cpqary3p->drvr_replyq->simple_cyclic_indicator =
- CPQARY3_REPLYQ_INIT_CYCLIC_IND;
- cpqary3p->drvr_replyq->max_index = cpqary3p->ctlr_maxcmds;
- cpqary3p->drvr_replyq->simple_index = 0;
- replyq_start_addr = MEM_ZALLOC(cmd_size);
- bzero(replyq_start_addr, cmd_size);
- cpqary3p->drvr_replyq->replyq_headptr =
- /* LINTED: alignment */
- (uint32_t *)replyq_start_addr;
- cpqary3p->drvr_replyq->replyq_simple_ptr =
- /* LINTED: alignment */
- (uint32_t *)replyq_start_addr;
- cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
-
- /* PERF */
-
- if (cpqary3_cfgtbl_transport_has_support(cpqary3p,
- CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+int
+cpqary3_ctlr_init_simple(cpqary3_t *cpq)
+{
+ VERIFY(cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_UNKNOWN);
- /*
- * Set the Transport Method and flush the changes to the
- * Configuration Table.
- */
- cpqary3_cfgtbl_transport_set(cpqary3p,
- CISS_CFGTBL_XPORT_SIMPLE);
- if (cpqary3_cfgtbl_flush(cpqary3p) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+ if (cpqary3_cfgtbl_transport_has_support(cpq,
+ CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) {
+ return (ENOTTY);
+ }
+ cpq->cpq_ctlr_mode = CPQARY3_CTLR_MODE_SIMPLE;
- if (cpqary3_cfgtbl_transport_confirm(cpqary3p,
- CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+ if ((cpq->ctlr_maxcmds = cpqary3_ctlr_get_cmdsoutmax(cpq)) == 0) {
+ dev_err(cpq->dip, CE_WARN, "maximum outstanding commands set "
+ "to zero");
+ return (EPROTO);
+ }
- /*
- * Check if the maximum number of oustanding commands for the
- * initialized controller is something greater than Zero.
- */
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
-
- if (CmdsOutMax == 0) {
- cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
- "Commands set to Zero\n");
- cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
- "initialization \n");
- return (CPQARY3_FAILURE);
- }
- cpqary3p->ctlr_maxcmds = CmdsOutMax;
+ cpq->sg_cnt = CPQARY3_SG_CNT;
- /*
- * Zero the Upper 32 Address in the Controller
- */
- DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
+ /*
+ * Set the Transport Method and flush the changes to the
+ * Configuration Table.
+ */
+ cpqary3_cfgtbl_transport_set(cpq, CISS_CFGTBL_XPORT_SIMPLE);
+ if (cpqary3_cfgtbl_flush(cpq) != CPQARY3_SUCCESS) {
+ return (EPROTO);
+ }
- /* Set the controller interrupt check routine */
- cpqary3p->check_ctlr_intr = cpqary3_check_simple_ctlr_intr;
+ if (cpqary3_cfgtbl_transport_confirm(cpq,
+ CISS_CFGTBL_XPORT_SIMPLE) != CPQARY3_SUCCESS) {
+ return (EPROTO);
+ }
- cpqary3p->host_support =
- DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
- DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
- (cpqary3p->host_support | 0x4));
- cpqary3p->host_support =
- DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
- } else {
- /* PERF */
+ /*
+ * XXX It's not clear why we check this a second time, but the original
+ * driver did.
+ */
+ uint32_t check_again = cpqary3_ctlr_get_cmdsoutmax(cpq);
+ if (check_again != cpq->ctlr_maxcmds) {
+ dev_err(cpq->dip, CE_WARN, "maximum outstanding commands "
+ "changed during initialisation (was %u, now %u)",
+ cpq->ctlr_maxcmds, check_again);
+ return (EPROTO);
+ }
- if (cpqary3_cfgtbl_transport_has_support(cpqary3p,
- CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+ /*
+ * Zero the upper 32 bits of the address in the Controller.
+ */
+ ddi_put32(cpq->ct_handle, &cpq->ct->HostWrite.Upper32Addr, 0);
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
- if (CmdsOutMax == 0)
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
- if (CmdsOutMax == 0) {
- cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
- "Commands set to Zero\n");
- cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
- "initialization \n");
- return (CPQARY3_FAILURE);
- }
+ /*
+ * Set the controller interrupt check routine.
+ */
+ cpq->check_ctlr_intr = cpqary3_check_simple_ctlr_intr;
- cpqary3p->ctlr_maxcmds = CmdsOutMax;
+ cpq->host_support = cpqary3_ctlr_get_hostdrvsup(cpq);
+ return (0);
+}
- /* Initialize the Performant Method Transport Method Table */
+/*
+ * XXX
+ */
+#if 0
+int
+cpqary3_ctlr_init_performant(cpqary3_t *cpq)
+{
+ cpqary3_replyq_t *cprq = &cpq->cpq_replyq;
- queue_depth = cpqary3p->ctlr_maxcmds;
+ VERIFY(cpq->cpq_ctlr_mode == CPQARY3_CTLR_MODE_UNKNOWN);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQSize, queue_depth);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCount, 1);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrLow32, 0);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrHigh32, 0);
+ if (cpqary3_cfgtbl_transport_has_support(cpq,
+ CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) {
+ return (ENOTTY);
+ }
+ cpq->cpq_ctlr_mode = CPQARY3_CTLR_MODE_PERFORMANT;
- cpqary3_phyctgp =
- (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (cpqary3_phyctg_t));
+ if ((cpq->ctlr_maxcmds = cpqary3_ctlr_get_cmdsoutmax(cpq)) == 0) {
+ dev_err(cpq->dip, CE_WARN, "maximum outstanding commands set "
+ "to zero");
+ return (EPROTO);
+ }
- if (!cpqary3_phyctgp) {
- cmn_err(CE_NOTE,
- "CPQary3: Initial mem zalloc failed");
- return (CPQARY3_FAILURE);
- }
- cmd_size = (8 * queue_depth);
- phy_addr = 0;
- replyq_start_addr = cpqary3_alloc_phyctgs_mem(cpqary3p,
- cmd_size, &phy_addr, cpqary3_phyctgp);
-
- if (!replyq_start_addr) {
- cmn_err(CE_WARN, "MEMALLOC returned failure");
- return (CPQARY3_FAILURE);
- }
+ /*
+ * Initialize the Performant Method Transport Method Table.
+ *
+ * XXX "Number of 4-byte nodes in each reply queue. Same for all reply
+ * queues." Here we are passing the number of COMMANDS, which is the
+ * number of 8-byte nodes...
+ */
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQSize, cpq->ctlr_maxcmds);
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQCount, 1);
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQCntrAddrLow32, 0);
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQCntrAddrHigh32, 0);
- bzero(replyq_start_addr, cmd_size);
- cpqary3p->drvr_replyq->replyq_headptr =
- /* LINTED: alignment */
- (uint32_t *)replyq_start_addr;
- cpqary3p->drvr_replyq->index = 0;
- cpqary3p->drvr_replyq->max_index = queue_depth;
- cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
- cpqary3p->drvr_replyq->cyclic_indicator =
- CPQARY3_REPLYQ_INIT_CYCLIC_IND;
- cpqary3p->drvr_replyq->replyq_start_paddr = phy_addr;
+ /*
+ * Each slot in the Reply Queue consists of two 4 byte integer
+ * fields.
+ */
+ size_t qsize = cpq->ctlr_maxcmds * 2 * sizeof (uint32_t);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0Low32, phy_addr);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0High32, 0);
+ if ((cprq->cprq_tags = (void *)cpqary3_alloc_phyctgs_mem(cpq, qsize,
+ &cprq->cprq_tags_pa, &cprq->cprq_phyctg)) == NULL) {
+ dev_err(cpq->dip, CE_WARN, "could not allocate replyq");
+ return (ENOMEM);
+ }
- max_blk_fetch_cnt =
- DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
+ bzero(cprq->cprq_tags, qsize);
+ cprq->cprq_ntags = cpq->ctlr_maxcmds;
+ cprq->cprq_cycle_indicator = 1;
+ cprq->cprq_read_index = 0;
- /*
- * For non-proton FW controllers, max_blk_fetch_count is not
- * implemented in the firmware
- */
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQAddr0Low32, cprq->cprq_tags_pa);
+ DDI_PUT32_CP(cpq, &cpq->cp->ReplyQAddr0High32, 0);
- /*
- * When blk fetch count is 0, FW auto fetches 564 bytes
- * corresponding to an optimal S/G of 31
- */
- if (max_blk_fetch_cnt == 0) {
- BlockFetchCnt[0] = 35;
- } else {
- /*
- * With MAX_PERF_SG_CNT set to 64, block fetch count
- * is got by:(sizeof (CommandList_t) + 15)/16
- */
- if (max_blk_fetch_cnt > 68)
- BlockFetchCnt[0] = 68;
- else
- BlockFetchCnt[0] = max_blk_fetch_cnt;
- }
+ max_blk_fetch_cnt = DDI_GET32(cpq, &ctp->MaxBlockFetchCount);
- DDI_PUT32_CP(cpqary3p, &perf_cfg->BlockFetchCnt[0],
- BlockFetchCnt[0]);
+ /*
+ * For non-proton FW controllers, max_blk_fetch_count is not
+ * implemented in the firmware
+ */
+ /*
+ * When blk fetch count is 0, FW auto fetches 564 bytes
+ * corresponding to an optimal S/G of 31
+ */
+ if (max_blk_fetch_cnt == 0) {
+ BlockFetchCnt[0] = 35;
+ } else {
/*
- * Set the Transport Method and flush the changes to the
- * Configuration Table.
+ * With MAX_PERF_SG_CNT set to 64, block fetch count
+ * is got by:(sizeof (CommandList_t) + 15)/16
*/
- cpqary3_cfgtbl_transport_set(cpqary3p,
- CISS_CFGTBL_XPORT_PERFORMANT);
- if (cpqary3_cfgtbl_flush(cpqary3p) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+ if (max_blk_fetch_cnt > 68)
+ BlockFetchCnt[0] = 68;
+ else
+ BlockFetchCnt[0] = max_blk_fetch_cnt;
+ }
- if (cpqary3_cfgtbl_transport_confirm(cpqary3p,
- CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) {
- return (CPQARY3_FAILURE);
- }
+ DDI_PUT32_CP(cpq, &perf_cfg->BlockFetchCnt[0], BlockFetchCnt[0]);
+ /*
+ * Set the Transport Method and flush the changes to the
+ * Configuration Table.
+ */
+ cpqary3_cfgtbl_transport_set(cpq, CISS_CFGTBL_XPORT_PERFORMANT);
+ if (cpqary3_cfgtbl_flush(cpq) != CPQARY3_SUCCESS) {
+ return (EPROTO);
+ }
+
+ if (cpqary3_cfgtbl_transport_confirm(cpq,
+ CISS_CFGTBL_XPORT_PERFORMANT) != CPQARY3_SUCCESS) {
+ return (EPROTO);
+ }
+
+ /*
+ * XXX It's not clear why we check this a second time, but the original
+ * driver did.
+ */
+ uint32_t check_again = cpqary3_ctlr_get_cmdsoutmax(cpq);
+ if (check_again != cpq->ctlr_maxcmds) {
+ dev_err(cpq->dip, CE_WARN, "maximum outstanding commands "
+ "changed during initialisation (was %u, now %u)",
+ cpq->ctlr_maxcmds, check_again);
+ return (EPROTO);
+ }
+
+ /* SG */
+ max_sg_cnt = DDI_GET32(cpq, &ctp->MaxSGElements);
+ max_blk_fetch_cnt = DDI_GET32(cpq, &ctp->MaxBlockFetchCount);
+
+ /* 32 byte aligned - size_of_cmdlist */
+ size_of_cmdlist = ((sizeof (CommandList_t) + 31) / 32) * 32;
+ size_of_HRE = size_of_cmdlist -
+ (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
+
+ if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) ||
+ ((max_blk_fetch_cnt * 16) <= size_of_HRE)) {
+ cpq->sg_cnt = CPQARY3_PERF_SG_CNT;
+ } else {
/*
- * Check if the maximum number of oustanding commands for the
- * initialized controller is something greater than Zero.
+ * Get the optimal_sg - no of the SG's that will fit
+ * into the max_blk_fetch_cnt
*/
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
- if (CmdsOutMax == 0)
- CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
-
- if (CmdsOutMax == 0) {
- cmn_err(CE_NOTE, "CPQary3 : HBA Maximum Outstanding "
- "Commands set to Zero");
- cmn_err(CE_NOTE, "CPQary3 : Cannot continue driver "
- "initialization");
- return (CPQARY3_FAILURE);
- }
- cpqary3p->ctlr_maxcmds = CmdsOutMax;
+ optimal_sg_size = (max_blk_fetch_cnt * 16) - size_of_HRE;
- /* SG */
- max_sg_cnt = DDI_GET32(cpqary3p, &ctp->MaxSGElements);
- max_blk_fetch_cnt =
- DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
+ if (optimal_sg_size < sizeof (SGDescriptor_t)) {
+ optimal_sg = CPQARY3_PERF_SG_CNT;
+ } else {
+ optimal_sg = optimal_sg_size / sizeof (SGDescriptor_t);
+ }
- /* 32 byte aligned - size_of_cmdlist */
- size_of_cmdlist = ((sizeof (CommandList_t) + 31) / 32) * 32;
- size_of_HRE = size_of_cmdlist -
- (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
+ cpq->sg_cnt = MIN(max_sg_cnt, optimal_sg);
- if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) ||
- ((max_blk_fetch_cnt * 16) <= size_of_HRE)) {
- cpqary3p->sg_cnt = CPQARY3_PERF_SG_CNT;
- } else {
- /*
- * Get the optimal_sg - no of the SG's that will fit
- * into the max_blk_fetch_cnt
- */
+ if (cpq->sg_cnt > MAX_PERF_SG_CNT) {
+ cpq->sg_cnt = MAX_PERF_SG_CNT;
+ }
+ }
- optimal_sg_size =
- (max_blk_fetch_cnt * 16) - size_of_HRE;
+ /* SG */
- if (optimal_sg_size < sizeof (SGDescriptor_t)) {
- optimal_sg = CPQARY3_PERF_SG_CNT;
- } else {
- optimal_sg =
- optimal_sg_size / sizeof (SGDescriptor_t);
- }
+ /*
+ * Zero the Upper 32 Address in the Controller
+ */
- cpqary3p->sg_cnt = MIN(max_sg_cnt, optimal_sg);
+ DDI_PUT32(cpq, &ctp->HostWrite.Upper32Addr, 0x00000000);
- if (cpqary3p->sg_cnt > MAX_PERF_SG_CNT)
- cpqary3p->sg_cnt = MAX_PERF_SG_CNT;
- }
+ /* Set the controller interrupt check routine */
- /* SG */
+ if (cpq->bddef->bd_is_e200) {
+ cpq->check_ctlr_intr = cpqary3_check_perf_e200_intr;
+ } else {
+ cpq->check_ctlr_intr = cpqary3_check_perf_ctlr_intr;
+ }
- /*
- * Zero the Upper 32 Address in the Controller
- */
+ cpq->host_support = cpqary3_ctlr_get_hostdrvsup(cpq);
- DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
+ return (0);
+}
+#endif
- /* Set the controller interrupt check routine */
+int
+cpqary3_ctlr_init(cpqary3_t *cpqary3p)
+{
+ uint8_t signature[4] = { 'C', 'I', 'S', 'S' };
+ CfgTable_t *ctp = cpqary3p->ct;
+ cpqary3_phyctg_t *cpqary3_phyctgp;
+ uint32_t phy_addr;
+ size_t cmd_size;
+ uint32_t queue_depth;
+ uint32_t CmdsOutMax;
+ uint32_t BlockFetchCnt[8];
+ caddr_t replyq_start_addr = NULL;
+ /* SG */
+ uint32_t max_blk_fetch_cnt = 0;
+ uint32_t max_sg_cnt = 0;
+ uint32_t optimal_sg = 0;
+ uint32_t optimal_sg_size = 0;
+ /* Header + Request + Error */
+ uint32_t size_of_HRE = 0;
+ uint32_t size_of_cmdlist = 0;
+ /* SG */
+ int e;
- if (cpqary3p->bddef->bd_is_e200) {
- cpqary3p->check_ctlr_intr =
- cpqary3_check_perf_e200_intr;
- } else {
- cpqary3p->check_ctlr_intr =
- cpqary3_check_perf_ctlr_intr;
+ if ((e = cpqary3_ctlr_wait_for_state(cpqary3p,
+ CPQARY3_WAIT_STATE_READY) != 0)) {
+ return (e);
+ }
+
+ /*
+ * The configuration table contains an ASCII signature ("CISS") which
+ * should be checked as we initialise the controller.
+ * See: "9.1 Configuration Table" in CISS Specification.
+ */
+ for (unsigned i = 0; i < 4; i++) {
+ if (ddi_get8(cpqary3p->ct_handle, &ctp->Signature[i]) !=
+ signature[i]) {
+ dev_err(cpqary3p->dip, CE_WARN, "invalid signature "
+ "detected");
+ return (EPROTO);
}
+ }
- if ((!cpqary3p->bddef->bd_is_e200) &&
- (!cpqary3p->bddef->bd_is_ssll)) {
- cpqary3p->host_support =
- DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
- DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
- (cpqary3p->host_support | 0x4));
+ /*
+ * XXX Let's just do Simple mode for now...
+ */
+#if 0
+ if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
+ if ((e = cpqary3_ctlr_init_simple(cpqary3p)) != 0) {
+ return (e);
+ }
+ } else {
+ if ((e = cpqary3_ctlr_init_performant(cpqary3p)) != 0) {
+ return (e);
}
- cpqary3p->host_support =
- DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
}
+#else
+ if ((e = cpqary3_ctlr_init_simple(cpqary3p)) != 0) {
+ return (e);
+ }
+#endif
/*
* Read initial controller heartbeat value and mark the current
@@ -844,39 +833,49 @@ cpqary3_init_ctlr(cpqary3_t *cpqary3p)
&ctp->HeartBeat);
cpqary3p->cpq_last_heartbeat_lbolt = ddi_get_lbolt();
- return (CPQARY3_SUCCESS);
+ return (0);
}
-/*
- * Function : cpqary3_check_ctlr_init
- * Description : This routine checks to see if the HBA is initialized.
- * Called By : cpqary3_init_ctlr()
- * Parameters : per-controller
- * Calls : None
- * Return Values: SUCCESS / FAILURE
- */
-uint8_t
-cpqary3_check_ctlr_init(cpqary3_t *cpqary3p)
+int
+cpqary3_ctlr_wait_for_state(cpqary3_t *cpq, cpqary3_wait_state_t state)
{
+ VERIFY(state == CPQARY3_WAIT_STATE_READY ||
+ state == CPQARY3_WAIT_STATE_UNREADY);
+
/*
- * Read from the Scratchpad Register until the expected ready
- * signature is detected. This behaviour is not described in
- * the CISS specification.
+ * Read from the Scratchpad Register until the expected ready signature
+ * is detected. This behaviour is not described in the CISS
+ * specification.
*
- * If the device is not ready immediate, sleep for a second and
- * try again. If the device has not become ready in 300 seconds,
- * give up.
+ * If the device is not in the desired state immediately, sleep for a
+ * second and try again. If the device has not become ready in 300
+ * seconds, give up.
*/
- for (unsigned i = 0; i < 300; i++) {
- uint32_t spr = ddi_get32(cpqary3p->spr0_handle,
- cpqary3p->spr0);
+ for (unsigned i = 0; i < CPQARY3_WAIT_DELAY_SECONDS; i++) {
+ uint32_t spr = ddi_get32(cpq->spr0_handle, cpq->spr0);
- if (spr == CISS_SCRATCHPAD_INITIALISED) {
- return (CPQARY3_SUCCESS);
+ switch (state) {
+ case CPQARY3_WAIT_STATE_READY:
+ if (spr == CISS_SCRATCHPAD_INITIALISED) {
+ return (0);
+ }
+ break;
+
+ case CPQARY3_WAIT_STATE_UNREADY:
+ if (spr != CISS_SCRATCHPAD_INITIALISED) {
+ return (0);
+ }
+ break;
}
+
+ /*
+ * Wait for a second and try again.
+ */
+ delay(drv_usectohz(1000000));
}
- dev_err(cpqary3p->dip, CE_WARN, "time out waiting for controller "
- "to become ready");
- return (CPQARY3_FAILURE);
+ dev_err(cpq->dip, CE_WARN, "time out waiting for controller "
+ "to enter state \"%s\"", state == CPQARY3_WAIT_STATE_READY ?
+ "ready": "unready");
+ return (ETIMEDOUT);
}
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_transport.c b/usr/src/uts/common/io/cpqary3/cpqary3_transport.c
index af2f9bd036..b729ae6022 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_transport.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_transport.c
@@ -32,7 +32,7 @@ static int cpqary3_setcap(struct scsi_address *, char *, int, int);
static int cpqary3_dma_alloc(cpqary3_t *, struct scsi_pkt *,
struct buf *, int, int (*)());
static int cpqary3_dma_move(struct scsi_pkt *, struct buf *, cpqary3_t *);
-static int cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t *, struct scsi_pkt *);
+static int cpqary3_handle_flag_nointr(cpqary3_command_t *, struct scsi_pkt *);
static int cpqary3_poll(cpqary3_t *, uint32_t);
static void cpqary3_dmafree(struct scsi_address *, struct scsi_pkt *);
static void cpqary3_dma_sync(struct scsi_address *, struct scsi_pkt *);
@@ -41,7 +41,7 @@ static struct scsi_pkt *cpqary3_init_pkt(struct scsi_address *,
struct scsi_pkt *, struct buf *, int, int, int, int, int (*callback)(),
caddr_t);
static int cpqary3_additional_cmd(struct scsi_pkt *scsi_pktp, cpqary3_t *);
-void cpqary3_oscmd_complete(cpqary3_cmdpvt_t *);
+void cpqary3_oscmd_complete(cpqary3_command_t *);
static uint8_t cpqary3_is_scsi_read_write(struct scsi_pkt *scsi_pktp);
/*
@@ -119,15 +119,12 @@ cpqary3_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
ctlr = (cpqary3_t *)hba_tran->tran_hba_private;
- /* HPQacucli Changes */
-
extern int8_t cpqary3_detect_target_geometry(cpqary3_t *);
if ((CPQARY3_SUCCESS == cpqary3_probe4targets(ctlr)) &&
(ctlr->num_of_targets > 0)) {
(void) cpqary3_detect_target_geometry(ctlr);
}
- /* HPQacucli Changes */
/*
* Validate the Target ID
* Validate Lun --Ver1.10--
@@ -178,10 +175,6 @@ cpqary3_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
static int
cpqary3_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
{
-#ifdef CPQARY3_DEBUG
- int status;
-#endif
-
/*
* Probe for the presence of the target, using the scsi_hba_probe().
* It inturn issues the SCSI inquiry command that is serviced by our
@@ -200,18 +193,6 @@ cpqary3_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
/* HPQacucli Changes */
return (scsi_hba_probe(sd, waitfunc));
-
-#ifdef CPQARY3_DEBUG
-
- /* Comment the previous line of code */
- status = scsi_hba_probe(sd, waitfunc);
- cmn_err(CE_CONT, "CPQary3 : _tgt_probe : target = %d \n", SD2TGT(sd));
- cmn_err(CE_CONT, "CPQary3 : _tgt_probe : scsi_hba_probe returned %d \n",
- status);
- cmn_err(CE_CONT, "CPQary3 : _tgt_probe : Leaving \n");
- return (status);
-
-#endif
}
/*
@@ -245,7 +226,7 @@ cpqary3_init_pkt(struct scsi_address *sa, struct scsi_pkt *scsi_pktp,
* Else, get the next available resources for the same
*/
- if (!scsi_pktp) {
+ if (scsi_pktp == NULL) {
scsi_pktp = scsi_hba_pkt_alloc(dip, sa, cmdlen, statuslen,
tgtlen, sizeof (cpqary3_pkt_t), callback, NULL);
if (!scsi_pktp)
@@ -263,7 +244,7 @@ cpqary3_init_pkt(struct scsi_address *sa, struct scsi_pkt *scsi_pktp,
cpqary3_pktp->cdb_len = cmdlen;
cpqary3_pktp->scb_len = statuslen;
cpqary3_pktp->cmd_dmahandle = NULL;
- cpqary3_pktp->memp = (cpqary3_cmdpvt_t *)NULL;
+ cpqary3_pktp->cmd_command = NULL;
/*
* Initialize to NULL all the fields of scsi_pktp, except
@@ -549,8 +530,9 @@ cpqary3_dma_move(struct scsi_pkt *scsi_pktp, struct buf *bp,
/* SG */
/* no. of DATA SEGMENTS */
if (i == cpqary3p->sg_cnt ||
- cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies)
+ cpqary3_pktp->cmd_cookie == cpqary3_pktp->cmd_ncookies) {
break;
+ }
/* SG */
ddi_dma_nextcookie(cpqary3_pktp->cmd_dmahandle,
@@ -582,7 +564,8 @@ cpqary3_transport(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
cpqary3_t *ctlr;
cpqary3_pkt_t *cpqary3_pktp;
cpqary3_tgt_t *tgtp;
- cpqary3_cmdpvt_t *memp;
+ cpqary3_command_t *cpcm;
+ int r;
ASSERT(sa != NULL);
ctlr = SA2CTLR(sa);
@@ -610,43 +593,44 @@ cpqary3_transport(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
* return TRAN_ACCEPT
*/
- if (NULL == (memp = cpqary3_cmdlist_occupy(ctlr)))
+ if ((cpcm = cpqary3_command_alloc(ctlr)) == NULL) {
return (TRAN_BUSY);
+ }
- cpqary3_pktp->memp = memp;
- memp->pvt_pkt = cpqary3_pktp;
+ cpcm->cpcm_type = CPQARY3_CMDTYPE_OS;
+ cpqary3_pktp->cmd_command = cpcm;
+ cpcm->cpcm_private = cpqary3_pktp;
if ((cpqary3_pktp->cmd_flags & DDI_DMA_CONSISTENT) &&
cpqary3_pktp->cmd_dmahandle) {
(void) ddi_dma_sync(cpqary3_pktp->cmd_dmahandle, 0, 0,
DDI_DMA_SYNC_FORDEV);
}
- /* SG */
- ASSERT(cpqary3_pktp->cmd_cookiecnt <= ctlr->sg_cnt);
- /* SG */
- /* PERF */
- memp->complete = cpqary3_oscmd_complete;
- /* PERF */
+ VERIFY(cpqary3_pktp->cmd_cookiecnt <= ctlr->sg_cnt);
- if (cpqary3_build_cmdlist(memp, SA2TGT(sa)) == CPQARY3_SUCCESS) {
- if (scsi_pktp->pkt_flags & FLAG_NOINTR) {
- return (cpqary3_handle_flag_nointr(memp, scsi_pktp));
- }
- cpqary3_pktp->cmd_start_time = ddi_get_lbolt();
+ cpcm->cpcm_complete = cpqary3_oscmd_complete;
- mutex_enter(&ctlr->hw_mutex);
- if (cpqary3_submit(ctlr, memp->cmdlist_phyaddr) != 0) {
- mutex_exit(&ctlr->hw_mutex);
- cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
- return (TRAN_FATAL_ERROR);
- }
- mutex_exit(&ctlr->hw_mutex);
+ if (cpqary3_build_cmdlist(cpcm, SA2TGT(sa)) != CPQARY3_SUCCESS) {
+ goto fail;
+ }
- return (TRAN_ACCEPT);
+ if ((scsi_pktp->pkt_flags & FLAG_NOINTR) != 0) {
+ return (cpqary3_handle_flag_nointr(cpcm, scsi_pktp));
+ }
+ cpqary3_pktp->cmd_start_time = ddi_get_lbolt();
+
+ mutex_enter(&ctlr->hw_mutex);
+ r = cpqary3_submit(ctlr, cpcm);
+ mutex_exit(&ctlr->hw_mutex);
+ if (r != 0) {
+ goto fail;
}
- cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
+ return (TRAN_ACCEPT);
+
+fail:
+ cpqary3_command_free(cpcm);
return (TRAN_FATAL_ERROR);
}
@@ -786,12 +770,9 @@ cpqary3_reset(struct scsi_address *sa, int level)
static int
cpqary3_abort(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
{
- uint32_t tid;
- cpqary3_t *ctlr;
-
- ASSERT(sa != NULL);
- tid = SA2TGT(sa);
- ctlr = SA2CTLR(sa);
+ uint32_t tid = SA2TGT(sa);
+ cpqary3_t *cpq = SA2CTLR(sa);
+ CommandList_t *clp = NULL;
/*
* If SCSI packet exists, abort that particular command.
@@ -799,13 +780,14 @@ cpqary3_abort(struct scsi_address *sa, struct scsi_pkt *scsi_pktp)
* In either of the cases, we shall have to wait after the abort
* functions are called to return the status.
*/
+ if (scsi_pktp != NULL) {
+ cpqary3_pkt_t *pktp = (cpqary3_pkt_t *)scsi_pktp->
+ pkt_ha_private;
- if (!scsi_pktp) {
- return (cpqary3_send_abortcmd(ctlr, tid,
- (CommandList_t *)NULL));
- } else {
- return (cpqary3_send_abortcmd(ctlr, tid, SP2CMD(scsi_pktp)));
+ clp = pktp->cmd_command->cpcm_va_cmd;
}
+
+ return (cpqary3_send_abortcmd(cpq, tid, clp));
}
/*
@@ -950,130 +932,82 @@ cpqary3_setcap(struct scsi_address *sa, char *capstr, int value, int tgtonly)
* Return Values: TRAN_ACCEPT
*/
static int
-cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t *memp, struct scsi_pkt *scsi_pktp)
+cpqary3_handle_flag_nointr(cpqary3_command_t *cpcm, struct scsi_pkt *scsi_pktp)
{
- uint32_t tag;
+ uint32_t tag = cpcm->cpcm_tag;
uint32_t simple_tag;
uint32_t i;
- cpqary3_t *ctlr;
+ cpqary3_t *ctlr = cpcm->cpcm_ctlr;
cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
uint32_t CmdsOutMax;
uint32_t no_cmds;
+ int ret;
- RETURN_FAILURE_IF_NULL(memp);
- tag = memp->tag.tag_value;
- ctlr = memp->ctlr;
- ctlr->poll_flag = CPQARY3_FALSE;
+ /*
+ * XXX this function is totally fucked with the mutexes and so on.
+ * fix it.
+ */
/*
* Before sumitting this command, ensure all commands pending
* with the controller are completed.
*/
-
+ mutex_enter(&ctlr->sw_mutex);
+ mutex_enter(&ctlr->hw_mutex);
+ ctlr->cpq_intr_off = B_TRUE;
cpqary3_intr_onoff(ctlr, CPQARY3_INTR_DISABLE);
if (ctlr->host_support & 0x4)
cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_DISABLE);
- no_cmds = (uint32_t)((ctlr->ctlr_maxcmds / 3) * NO_OF_CMDLIST_IN_A_BLK);
- mutex_enter(&ctlr->sw_mutex);
-
- for (;;) {
- ctlr->poll_flag = CPQARY3_FALSE;
- for (i = 0; i < no_cmds; i++) {
- cpqary3_cmdpvtp = &ctlr->cmdmemlistp->pool[i];
- ASSERT(cpqary3_cmdpvtp != NULL);
-
- if ((tag != cpqary3_cmdpvtp->tag.tag_value) &&
- (cpqary3_cmdpvtp->occupied == CPQARY3_OCCUPIED)) {
- if (ctlr->noe_support == 1) {
- if ((cpqary3_cmdpvtp->cmdlist_memaddr->
- Header.Tag.drvinfo_n_err ==
- CPQARY3_NOECMD_SUCCESS) ||
- (cpqary3_cmdpvtp->cmdpvt_flag ==
- CPQARY3_TIMEOUT)) {
- continue;
- }
- } else {
- if (cpqary3_cmdpvtp->cmdpvt_flag ==
- CPQARY3_TIMEOUT) {
- continue;
- }
- }
- ctlr->poll_flag = CPQARY3_TRUE;
- }
- /* NOE */
+ while (avl_numnodes(&ctlr->cpq_inflight) > 0) {
+ (void) cpqary3_retrieve(ctlr);
+ drv_usecwait(1000);
+ }
- if (ctlr->poll_flag == CPQARY3_TRUE) {
- break;
- }
+ if (cpqary3_submit(ctlr, cpcm) != 0) {
+ ctlr->cpq_intr_off = B_FALSE;
+ cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
+ if (ctlr->host_support & 0x4) {
+ cpqary3_lockup_intr_onoff(ctlr,
+ CPQARY3_LOCKUP_INTR_ENABLE);
}
- if (ctlr->poll_flag == CPQARY3_TRUE) {
- if (!(ctlr->bddef->bd_flags & SA_BD_SAS)) {
- while ((simple_tag =
- ddi_get32(ctlr->opq_handle,
- (uint32_t *)ctlr->opq)) != 0xFFFFFFFF) {
- CmdsOutMax = ctlr->ctlr_maxcmds;
- if ((simple_tag >>
- CPQARY3_GET_MEM_TAG) >=
- ((CmdsOutMax / 3) * 3)) {
- cmn_err(CE_WARN,
- "CPQary3 : HBA returned "
- "Spurious Tag");
- return (CPQARY3_FAILURE);
- }
-
- cpqary3_cmdpvtp =
- &ctlr->cmdmemlistp->pool[
- simple_tag >> CPQARY3_GET_MEM_TAG];
- cpqary3_cmdpvtp->cmdlist_memaddr->
- Header.Tag.drvinfo_n_err =
- (simple_tag & 0xF) >> 1;
- cpqary3_cmdpvtp->complete(
- cpqary3_cmdpvtp);
- }
- } else {
- mutex_exit(&ctlr->sw_mutex);
- if (CPQARY3_SUCCESS != cpqary3_retrieve(ctlr)) {
- drv_usecwait(1000);
- }
- mutex_enter(&ctlr->sw_mutex); /* Changes */
- }
- } else {
- break;
- }
- }
-
- mutex_enter(&ctlr->hw_mutex);
- if (EIO == cpqary3_submit(ctlr, memp->cmdlist_phyaddr)) {
mutex_exit(&ctlr->hw_mutex);
mutex_exit(&ctlr->sw_mutex);
- cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
+
+ cpqary3_command_free(cpcm);
return (TRAN_FATAL_ERROR);
}
- if (CPQARY3_FAILURE == cpqary3_poll(ctlr, tag)) {
+ if (cpqary3_poll(ctlr, tag) != CPQARY3_SUCCESS) {
scsi_pktp->pkt_reason = CMD_TIMEOUT;
scsi_pktp->pkt_statistics = STAT_TIMEOUT;
scsi_pktp->pkt_state = 0;
- mutex_exit(&ctlr->hw_mutex);
- mutex_exit(&ctlr->sw_mutex);
- cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
- cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
- if (ctlr->host_support & 0x4)
- cpqary3_lockup_intr_onoff(ctlr,
- CPQARY3_LOCKUP_INTR_ENABLE);
- return (TRAN_ACCEPT);
- } else {
- mutex_exit(&ctlr->hw_mutex);
- mutex_exit(&ctlr->sw_mutex);
+
+ ctlr->cpq_intr_off = B_FALSE;
cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
if (ctlr->host_support & 0x4) {
cpqary3_lockup_intr_onoff(ctlr,
CPQARY3_LOCKUP_INTR_ENABLE);
}
+
+ mutex_exit(&ctlr->hw_mutex);
+ mutex_exit(&ctlr->sw_mutex);
+
+ cpqary3_command_free(cpcm);
return (TRAN_ACCEPT);
}
+
+ ctlr->cpq_intr_off = B_FALSE;
+ cpqary3_intr_onoff(ctlr, CPQARY3_INTR_ENABLE);
+ if (ctlr->host_support & 0x4) {
+ cpqary3_lockup_intr_onoff(ctlr, CPQARY3_LOCKUP_INTR_ENABLE);
+ }
+
+ mutex_exit(&ctlr->hw_mutex);
+ mutex_exit(&ctlr->sw_mutex);
+
+ return (TRAN_ACCEPT);
}
/*
@@ -1085,13 +1019,16 @@ cpqary3_handle_flag_nointr(cpqary3_cmdpvt_t *memp, struct scsi_pkt *scsi_pktp)
* Return Values: TRAN_ACCEPT
*/
static int
-cpqary3_poll(cpqary3_t *ctlr, uint32_t tag)
+cpqary3_poll(cpqary3_t *cpq, uint32_t tag)
{
- uint32_t ii = 0;
+ boolean_t found = B_FALSE;
+ unsigned tries = 0;
- RETURN_FAILURE_IF_NULL(ctlr);
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+ VERIFY(MUTEX_HELD(&cpq->sw_mutex));
/*
+ * XXX
* POLL for the completion of the said command
* Since, we had ensured that controller is empty, we need not
* check for the complete Retrieved Q.
@@ -1100,18 +1037,28 @@ cpqary3_poll(cpqary3_t *ctlr, uint32_t tag)
* if the polled command is completed, send back a success.
*/
- for (;;) { /* this function is called with both the locks held */
- if (CPQARY3_SUCCESS != cpqary3_poll_retrieve(ctlr, tag)) {
- ii++;
- if (ii > 120000)
- return (CPQARY3_FAILURE);
- drv_usecwait(500);
- continue;
- }
+retry:
+ switch (cpq->cpq_ctlr_mode) {
+ case CPQARY3_CTLR_MODE_SIMPLE:
+ cpqary3_retrieve_simple(cpq, tag, &found);
+ break;
+ case CPQARY3_CTLR_MODE_PERFORMANT:
+ cpqary3_retrieve_performant(cpq, tag, &found);
break;
+ default:
+ panic("unknown controller mode");
}
- return (CPQARY3_SUCCESS);
+ if (found) {
+ return (CPQARY3_SUCCESS);
+ }
+
+ if (tries++ < 120000) {
+ drv_usecwait(500);
+ goto retry;
+ }
+
+ return (CPQARY3_FAILURE);
}
static int
@@ -1186,50 +1133,46 @@ cpqary3_additional_cmd(struct scsi_pkt *scsi_pktp, cpqary3_t *ctlr)
* Return Values: None
*/
void
-cpqary3_oscmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
+cpqary3_oscmd_complete(cpqary3_command_t *cpcm)
{
- cpqary3_t *cpqary3p;
- ErrorInfo_t *errorinfop;
- CommandList_t *cmdlistp;
- struct scsi_pkt *scsi_pktp;
+ cpqary3_t *cpqary3p = cpcm->cpcm_ctlr;
+ ErrorInfo_t *errorinfop = cpcm->cpcm_va_err;
+ CommandList_t *cmdlistp = cpcm->cpcm_va_cmd;
+ struct scsi_pkt *scsi_pktp = cpcm->cpcm_private->scsi_cmd_pkt;
- ASSERT(cpqary3_cmdpvtp != NULL);
+ VERIFY(MUTEX_HELD(&cpqary3p->sw_mutex));
+ VERIFY(cpcm->cpcm_type == CPQARY3_CMDTYPE_OS);
- if (CPQARY3_TIMEOUT == cpqary3_cmdpvtp->cmdpvt_flag) {
- cpqary3_cmdlist_release(cpqary3_cmdpvtp,
- CPQARY3_NO_MUTEX);
+ /*
+ * XXX oops?
+ */
+ if (cpcm->cpcm_free_on_complete) {
+ cpqary3_command_free(cpcm);
return;
}
- cpqary3p = cpqary3_cmdpvtp->ctlr;
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
- errorinfop = cpqary3_cmdpvtp->errorinfop;
+ if (cmdlistp->Header.Tag.error != 0) {
+ mutex_exit(&cpqary3p->sw_mutex);
+
+ cpqary3_command_free(cpcm);
- if (cmdlistp->Header.Tag.drvinfo_n_err == CPQARY3_OSCMD_SUCCESS) {
- scsi_pktp = cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt;
scsi_pktp->pkt_reason = CMD_CMPLT;
scsi_pktp->pkt_statistics = 0;
scsi_pktp->pkt_state = STATE_GOT_BUS |
STATE_GOT_TARGET | STATE_SENT_CMD |
STATE_XFERRED_DATA | STATE_GOT_STATUS;
- if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags &
- FLAG_NOINTR) {
- cpqary3_cmdlist_release(cpqary3_cmdpvtp,
- CPQARY3_NO_MUTEX);
- } else {
- cpqary3_cmdlist_release(cpqary3_cmdpvtp,
- CPQARY3_NO_MUTEX);
-
- if (scsi_pktp->pkt_comp) {
- mutex_exit(&cpqary3p->sw_mutex);
+ /*
+ * XXX this is suspect...
+ */
+ if ((scsi_pktp->pkt_flags & FLAG_NOINTR) == 0) {
+ if (scsi_pktp->pkt_comp != NULL) {
(*scsi_pktp->pkt_comp)(scsi_pktp);
- mutex_enter(&cpqary3p->sw_mutex);
}
}
+
+ mutex_enter(&cpqary3p->sw_mutex);
return;
- } else {
- scsi_pktp = cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt;
}
switch (errorinfop->CommandStatus) {
@@ -1330,22 +1273,25 @@ cpqary3_oscmd_complete(cpqary3_cmdpvt_t *cpqary3_cmdpvtp)
bcopy((caddr_t)&errorinfop->SenseInfo[0],
(caddr_t)(&arq_statusp->sts_sensedata),
CPQARY3_MIN(errorinfop->SenseLen,
- cpqary3_cmdpvtp->pvt_pkt->scb_len));
+ cpcm->cpcm_private->scb_len));
scsi_pktp->pkt_state |= STATE_ARQ_DONE;
}
}
- if (cpqary3_cmdpvtp->pvt_pkt->scsi_cmd_pkt->pkt_flags & FLAG_NOINTR) {
- cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
- } else {
- cpqary3_cmdlist_release(cpqary3_cmdpvtp, CPQARY3_NO_MUTEX);
+ mutex_exit(&cpqary3p->sw_mutex);
- if (scsi_pktp->pkt_comp) {
- mutex_exit(&cpqary3p->sw_mutex);
+ cpqary3_command_free(cpcm);
+
+ /*
+ * XXX this is also suspicious.
+ */
+ if ((scsi_pktp->pkt_flags & FLAG_NOINTR) == 0) {
+ if (scsi_pktp->pkt_comp != NULL) {
(*scsi_pktp->pkt_comp)(scsi_pktp);
- mutex_enter(&cpqary3p->sw_mutex);
}
}
+
+ mutex_enter(&cpqary3p->sw_mutex);
}
static uint8_t
diff --git a/usr/src/uts/common/io/cpqary3/cpqary3_util.c b/usr/src/uts/common/io/cpqary3/cpqary3_util.c
index 91b44285af..7cba93ba6c 100644
--- a/usr/src/uts/common/io/cpqary3/cpqary3_util.c
+++ b/usr/src/uts/common/io/cpqary3/cpqary3_util.c
@@ -53,25 +53,8 @@ cpqary3_read_conf_file(dev_info_t *dip, cpqary3_t *cpqary3p)
/*
* We are calling ddi_prop_lookup_string
* which gets the property value, which is passed at
- * the grub menu. If the user wants to use the older
- * target mapping algorithm,(prior to 1.80)at the grub menu
- * "cpqary3_tgtmap=off" should be entered. if this
- * string is entered, then we will set the
- * value of the variable legacy_mapping to one, which
- * will be used in
- * cpqary3_detect_target_geometry()
- * and cpqary3_probe4LVs(), to decide on the
- * mapping algorithm
+ * the grub menu.
*/
-
- if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
- "cpqary3_tgtmap", &ptr) == DDI_PROP_SUCCESS) {
- if (strcmp("off", ptr) == 0) {
- cpqary3p->legacy_mapping = 1;
- }
- ddi_prop_free(ptr);
- }
-
if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
"cpqary3_noesupport", &ptr) == DDI_PROP_SUCCESS) {
if (strcmp("on", ptr) == 0) {
@@ -144,8 +127,16 @@ cpqary3_periodic(void *arg)
cpqary3_t *cpq = arg;
uint32_t no_cmds;
+ dev_err(cpq->dip, CE_WARN, "PERIODIC START");
+
cpqary3_lockup_check(cpq);
+ dev_err(cpq->dip, CE_WARN, "PERIODIC END");
+
+ /*
+ * XXX This should be re-tooled to use "cpq_inflight".
+ */
+#if 0
mutex_enter(&cpq->sw_mutex);
no_cmds = (uint32_t)((cpq->ctlr_maxcmds / 3) * NO_OF_CMDLIST_IN_A_BLK);
for (uint32_t i = 0; i < no_cmds; i++) {
@@ -193,6 +184,34 @@ cpqary3_periodic(void *arg)
}
}
mutex_exit(&cpq->sw_mutex);
+#endif
+}
+
+cpqary3_command_t *
+cpqary3_lookup_inflight(cpqary3_t *cpq, uint32_t tag)
+{
+ VERIFY(MUTEX_HELD(&cpq->hw_mutex));
+
+ cpqary3_command_t srch;
+
+ srch.cpcm_tag = tag;
+
+ return (avl_find(&cpq->cpq_inflight, &srch, NULL));
+}
+
+static int
+cpqary3_comparator(const void *lp, const void *rp)
+{
+ const cpqary3_command_t *l = lp;
+ const cpqary3_command_t *r = rp;
+
+ if (l->cpcm_tag > r->cpcm_tag) {
+ return (1);
+ } else if (l->cpcm_tag < r->cpcm_tag) {
+ return (-1);
+ } else {
+ return (0);
+ }
}
/*
@@ -210,9 +229,10 @@ cpqary3_periodic(void *arg)
uint16_t
cpqary3_init_ctlr_resource(cpqary3_t *ctlr)
{
-#ifdef CPQARY3_DEBUG_MEM
- int8_t i = 0;
-#endif
+ list_create(&ctlr->cpq_commands, sizeof (cpqary3_command_t),
+ offsetof(cpqary3_command_t, cpcm_link));
+ avl_create(&ctlr->cpq_inflight, cpqary3_comparator,
+ sizeof (cpqary3_command_t), offsetof(cpqary3_command_t, cpcm_node));
/*
* Initialize the Controller
@@ -223,46 +243,28 @@ cpqary3_init_ctlr_resource(cpqary3_t *ctlr)
* Determine geometry for all existing targets
* Initialize the condition variables
*/
+ if (cpqary3_ctlr_init(ctlr) != 0) {
+ dev_err(ctlr->dip, CE_WARN, "cpqary3_ctlr_init failed");
+ return (CPQARY3_FAILURE);
+ }
- RETURN_FAILURE_IF_NULL(ctlr);
-
- if (CPQARY3_FAILURE == cpqary3_init_ctlr(ctlr))
- return ((CPQARY3_FAILURE));
-
- if (CPQARY3_FAILURE == cpqary3_meminit(ctlr))
- return ((CPQARY3_FAILURE));
-
-
-#ifdef CPQARY3_DEBUG_MEM
/*
- * This code is in place to test the memory management of this driver.
- * This block of code allocates and de-allocates memory as many number
- * of times as given in the for loop.
- * After the for loop is executed, it returns a failure, which in turn
- * would result in attach being failed.
+ * XXX
*/
- cmn_err(CE_CONT, "CPQary3 : _init_ctlr_resource : Testing memory \n");
- for (i = 0; i < 15; i++) {
- if (CPQARY3_SUCCESS != cpqary3_meminit(ctlr)) {
- cmn_err(CE_CONT, "CPQary3 : meminit failed : "
- "attempt %d \n", i);
- return (CPQARY3_FAILURE);
- }
- cmn_err(CE_CONT,
- "CPQary3 : INIT successful : attempt %d \n", i);
- cpqary3_memfini(ctlr, CPQARY3_MEMLIST_DONE |
- CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE);
- cmn_err(CE_CONT,
- "CPQary3 : FINI successful : attempt %d \n", i);
+#if 0
+ if (cpqary3_meminit(ctlr) != CPQARY3_SUCCESS) {
+ return (CPQARY3_FAILURE);
}
- return (CPQARY3_FAILURE);
#endif
- ctlr->cpqary3_tgtp[CTLR_SCSI_ID] = MEM_ZALLOC(sizeof (cpqary3_tgt_t));
+ ctlr->cpqary3_tgtp[CTLR_SCSI_ID] = kmem_zalloc(sizeof (cpqary3_tgt_t),
+ KM_NOSLEEP);
if (!(ctlr->cpqary3_tgtp[CTLR_SCSI_ID])) {
cmn_err(CE_WARN, "CPQary3: Target Initialization Failed");
+#if 0
cpqary3_memfini(ctlr, CPQARY3_MEMLIST_DONE |
CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE);
+#endif
return (CPQARY3_FAILURE);
}
ctlr->cpqary3_tgtp[CTLR_SCSI_ID]->type = CPQARY3_TARGET_CTLR;
@@ -320,103 +322,33 @@ cpqary3_target_geometry(struct scsi_address *sa)
* Calls : cpqary3_alloc_phyctgs_mem(), cpqary3_cmdlist_occupy()
* Return Values: memp
*/
-cpqary3_cmdpvt_t *
-cpqary3_synccmd_alloc(cpqary3_t *cpqary3p, size_t bufsz)
+cpqary3_command_t *
+cpqary3_synccmd_alloc(cpqary3_t *cpq, size_t bufsz)
{
- cpqary3_private_t *cmddmah = NULL;
- uint32_t dmabufpa = 0; /* XXX 32-bit pa? */
- cpqary3_cmdpvt_t *memp = NULL;
-
- /* first, allocate any necessary dma buffers */
- if (bufsz > 0) {
- cpqary3_phyctg_t *dmah = NULL;
- caddr_t dmabufva = NULL;
-
- /* first, allocate the command's dma handle */
- cmddmah = (cpqary3_private_t *)MEM_ZALLOC(sizeof (*cmddmah));
- if (cmddmah == NULL) {
- cmn_err(CE_WARN, "cpqary3_synccmd_alloc: "
- "no memory for cmddmah");
- return (NULL);
- }
+ cpqary3_command_t *cpcm;
- /* next, allocate dma handle */
- dmah = (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (*dmah));
- if (dmah == NULL) {
- MEM_SFREE(cmddmah, sizeof (*cmddmah));
- cmn_err(CE_WARN, "cpqary3_synccmd_alloc: "
- "no memory for dmah");
- return (NULL);
- }
- /* now, allocate dma buffer */
- dmabufva = cpqary3_alloc_phyctgs_mem(cpqary3p, bufsz,
- &dmabufpa, dmah);
- if (dmabufva == NULL) {
- MEM_SFREE(cmddmah, sizeof (*cmddmah));
- cmn_err(CE_WARN, "cpqary3_synccmd_alloc: "
- "no memory for dma buf");
- return (NULL);
- }
- bzero(dmabufva, bufsz);
+ if ((cpcm = cpqary3_command_alloc(cpq)) == NULL) {
+ return (NULL);
+ }
+
+ cpcm->cpcm_type = CPQARY3_CMDTYPE_SYNCCMD;
- /* attach dma buffer to command dma handle */
- cmddmah->sg = dmabufva;
- cmddmah->phyctgp = dmah;
+ if (bufsz == 0) {
+ return (cpcm);
}
- /* next, allocate a command packet */
- memp = cpqary3_cmdlist_occupy(cpqary3p);
- if (memp == NULL) {
- if (cmddmah != NULL) {
- cpqary3_free_phyctgs_mem(cmddmah->phyctgp,
- CPQARY3_FREE_PHYCTG_MEM);
- MEM_SFREE(cmddmah, sizeof (*cmddmah));
- }
- cmn_err(CE_WARN, "cpqary3_synccmd_alloc: "
- "cannot get free command");
+ if ((cpcm->cpcm_internal = cpqary3_command_internal_alloc(cpq,
+ bufsz)) == NULL) {
+ cpqary3_command_free(cpcm);
return (NULL);
}
- memp->cmdpvt_flag = 0;
- memp->cmdlist_memaddr->Header.Tag.drvinfo_n_err =
- CPQARY3_SYNCCMD_SUCCESS;
- /* attach dma resources to command */
- memp->driverdata = cmddmah;
- memp->cmdlist_memaddr->SG[0].Addr = dmabufpa;
- memp->cmdlist_memaddr->SG[0].Len = (uint32_t)bufsz;
+ cpcm->cpcm_va_cmd->SG[0].Addr = cpcm->cpcm_internal->cpcmi_pa;
+ cpcm->cpcm_va_cmd->SG[0].Len = bufsz;
+ cpcm->cpcm_va_cmd->Header.SGList = 1;
+ cpcm->cpcm_va_cmd->Header.SGTotal = 1;
- /* done */
- return (memp);
-}
-
-/*
- * Function : cpqary3_synccmd_cleanup
- * Description : This routine cleans up the command
- * Called By : cpqary3_process_pkt(), cpqary3_synccmd_free()
- * Parameters : per_command_memory
- * Calls : cpqary3_free_phyctgs_mem(), cpqary3_cmdlist_release()
- * Return Values: none
- */
-void
-cpqary3_synccmd_cleanup(cpqary3_cmdpvt_t *memp)
-{
- /*
- * ordinary users should not call this routine
- * (use cpqary3_synccmd_free() instead). this is
- * for use ONLY by cpqary3_synccmd_free() and
- * cpqary3_process_pkt().
- */
-
- if (memp->driverdata != NULL) {
- /* free dma resources */
- cpqary3_free_phyctgs_mem(memp->driverdata->phyctgp,
- CPQARY3_FREE_PHYCTG_MEM);
- MEM_SFREE(memp->driverdata, sizeof (cpqary3_private_t));
- memp->driverdata = NULL;
- }
- /* release command */
- memp->cmdpvt_flag = 0;
- cpqary3_cmdlist_release(memp, CPQARY3_HOLD_SW_MUTEX);
+ return (cpcm);
}
/*
@@ -433,7 +365,7 @@ cpqary3_synccmd_cleanup(cpqary3_cmdpvt_t *memp)
* Return Values: NONE
*/
void
-cpqary3_synccmd_free(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp)
+cpqary3_synccmd_free(cpqary3_t *cpq, cpqary3_command_t *cpcm)
{
/*
* so, the user is done with this command packet.
@@ -460,30 +392,26 @@ cpqary3_synccmd_free(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp)
* cpqary3_process_pkt() clean it up instead.
*/
- mutex_enter(&(cpqary3p->sw_mutex));
- if (memp->cmdpvt_flag == CPQARY3_SYNC_SUBMITTED) {
+ mutex_enter(&cpq->sw_mutex);
+ if (cpcm->cpcm_synccmd_status == CPQARY3_SYNCCMD_STATUS_SUBMITTED) {
/*
* command is still pending (case #3 above).
* mark the command as abandoned and let
* cpqary3_process_pkt() clean it up.
*/
- memp->cmdpvt_flag = CPQARY3_SYNC_TIMEOUT;
- mutex_exit(&(cpqary3p->sw_mutex));
+ cpcm->cpcm_synccmd_status = CPQARY3_SYNCCMD_STATUS_TIMEOUT;
+ mutex_exit(&cpq->sw_mutex);
return;
}
- memp->cmdpvt_flag = 0;
- mutex_exit(&(cpqary3p->sw_mutex));
+ cpcm->cpcm_synccmd_status = CPQARY3_SYNCCMD_STATUS_NONE;
+ mutex_exit(&cpq->sw_mutex);
/*
* command was either never submitted or has completed
* (cases #1 and #2 above). so, clean it up.
*/
- cpqary3_synccmd_cleanup(memp);
-
- /* done */
- return;
-
-} /* cpqary3_synccmd_free() */
+ cpqary3_command_free(cpcm);
+}
/*
* Function : cpqary3_synccmd_send
@@ -499,70 +427,69 @@ cpqary3_synccmd_free(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp)
* Return Values: SUCCESS / FAILURE
*/
int
-cpqary3_synccmd_send(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp,
+cpqary3_synccmd_send(cpqary3_t *cpqary3p, cpqary3_command_t *cpcm,
clock_t timeoutms, int flags)
{
clock_t absto = 0; /* absolute timeout */
- int waitsig = 0;
+ boolean_t waitsig = B_FALSE;
int rc = 0;
- kcondvar_t *cv = 0;
/* compute absolute timeout, if necessary */
- if (timeoutms > 0)
+ if (timeoutms > 0) {
absto = ddi_get_lbolt() + drv_usectohz(timeoutms * 1000);
+ }
/* heed signals during wait? */
- if (flags & CPQARY3_SYNCCMD_SEND_WAITSIG)
- waitsig = 1;
+ if (flags & CPQARY3_SYNCCMD_SEND_WAITSIG) {
+ waitsig = B_TRUE;
+ }
/* acquire the sw mutex for our wait */
- mutex_enter(&(cpqary3p->sw_mutex));
-
- /* submit command to controller */
- mutex_enter(&(cpqary3p->hw_mutex));
-
- memp->cmdpvt_flag = CPQARY3_SYNC_SUBMITTED;
- memp->cmdlist_memaddr->Header.Tag.drvinfo_n_err =
- CPQARY3_SYNCCMD_SUCCESS;
- if (EIO == cpqary3_submit(cpqary3p, memp->cmdlist_phyaddr)) {
- mutex_exit(&(cpqary3p->hw_mutex));
- mutex_exit(&(cpqary3p->sw_mutex));
- rc = -1;
- return (rc);
+ mutex_enter(&cpqary3p->sw_mutex);
+ mutex_enter(&cpqary3p->hw_mutex);
+
+ VERIFY(cpcm->cpcm_synccmd_status == CPQARY3_SYNCCMD_STATUS_NONE);
+ cpcm->cpcm_synccmd_status = CPQARY3_SYNCCMD_STATUS_SUBMITTED;
+
+ if (cpqary3_submit(cpqary3p, cpcm) != 0) {
+ mutex_exit(&cpqary3p->hw_mutex);
+ mutex_exit(&cpqary3p->sw_mutex);
+ return (-1);
}
- mutex_exit(&(cpqary3p->hw_mutex));
+ mutex_exit(&cpqary3p->hw_mutex);
/* wait for command completion, timeout, or signal */
- while (memp->cmdpvt_flag == CPQARY3_SYNC_SUBMITTED) {
- kmutex_t *mt = &(cpqary3p->sw_mutex);
+ while (cpcm->cpcm_synccmd_status == CPQARY3_SYNCCMD_STATUS_SUBMITTED) {
+ kmutex_t *mt = &cpqary3p->sw_mutex;
+ kcondvar_t *cv = &cpqary3p->cv_ioctl_wait;
- cv = &(cpqary3p->cv_ioctl_wait);
/* wait with the request behavior */
if (absto) {
- clock_t crc;
+ clock_t crc;
if (waitsig) {
crc = cv_timedwait_sig(cv, mt, absto);
} else {
crc = cv_timedwait(cv, mt, absto);
}
- if (crc > 0)
+ if (crc > 0) {
rc = 0;
- else
- rc = (-1);
+ } else {
+ rc = -1;
+ }
} else {
if (waitsig) {
rc = cv_wait_sig(cv, mt);
- if (rc > 0)
+ if (rc > 0) {
rc = 0;
- else
- rc = (-1);
+ } else {
+ rc = -1;
+ }
} else {
cv_wait(cv, mt);
rc = 0;
}
}
-
/*
* if our wait was interrupted (timeout),
* then break here
@@ -572,10 +499,7 @@ cpqary3_synccmd_send(cpqary3_t *cpqary3p, cpqary3_cmdpvt_t *memp,
}
}
- /* our wait is done, so release the sw mutex */
- mutex_exit(&(cpqary3p->sw_mutex));
-
- /* return the results */
+ mutex_exit(&cpqary3p->sw_mutex);
return (rc);
}
@@ -599,9 +523,7 @@ cpqary3_detect_target_geometry(cpqary3_t *ctlr)
int8_t loop_cnt = 0;
IdLogDrive *idlogdrive;
CommandList_t *cmdlistp;
- cpqary3_cmdpvt_t *cpqary3_cmdpvtp;
-
- RETURN_FAILURE_IF_NULL(ctlr);
+ cpqary3_command_t *cpcm;
/*
* Occupy a Command List
@@ -613,20 +535,13 @@ cpqary3_detect_target_geometry(cpqary3_t *ctlr)
* If success, continue else RETURN 0
*/
- /* Sync Changes */
- cpqary3_cmdpvtp = cpqary3_synccmd_alloc(ctlr, sizeof (IdLogDrive));
- if (cpqary3_cmdpvtp == NULL)
+ if ((cpcm = cpqary3_synccmd_alloc(ctlr, sizeof (IdLogDrive))) ==
+ NULL) {
return (CPQARY3_FAILURE);
+ }
- cmdlistp = cpqary3_cmdpvtp->cmdlist_memaddr;
- idlogdrive = (IdLogDrive *)cpqary3_cmdpvtp->driverdata->sg;
- /* Sync Changes */
-
-
- /* Update Cmd Header */
- cmdlistp->Header.SGList = 1;
- cmdlistp->Header.SGTotal = 1;
- cmdlistp->Header.Tag.drvinfo_n_err = CPQARY3_SYNCCMD_SUCCESS;
+ cmdlistp = cpcm->cpcm_va_cmd;
+ idlogdrive = cpcm->cpcm_internal->cpcmi_va;
/* Cmd Reques */
cmdlistp->Request.CDBLen = CPQARY3_CDBLEN_16;
@@ -648,160 +563,77 @@ cpqary3_detect_target_geometry(cpqary3_t *ctlr)
*/
/*
- * Depending upon the value of the variable legacy_mapping
- * set in cpqary3_attach(),
- * the target mapping algorithm to be used by the driver is decided.
+ * Fix for QXCR1000446657: Logical drives are re numbered
+ * after deleting a Logical drive.
+ * introduced, new variable ld_count, which gets
+ * incremented when the Target ID is found.
+ * And for i=controller's SCSI ID and LDs with holes are found,
+ * we continue talking to
+ * the next logical drive in the per-target structure
*/
- if (ctlr->legacy_mapping == 1) {
- loop_cnt = ((ctlr->num_of_targets > CTLR_SCSI_ID) ?
- (ctlr->num_of_targets + 1) : (ctlr->num_of_targets));
-
- for (i = 0; i < loop_cnt; i++) {
- if (i == CTLR_SCSI_ID) /* Go to Next logical target */
- i++;
-
- bzero(idlogdrive, sizeof (IdLogDrive));
- cmdlistp->Request.CDB[1] =
- ctlr->cpqary3_tgtp[i]->logical_id;
-
- /* Always zero */
- cmdlistp->Header.LUN.PhysDev.TargetId = 0;
-
- /*
- * Logical volume Id numbering scheme is as follows
- * 0x00000, 0x00001, ... - for Direct Attached
- * 0x10000, 0x10001, ... - If 1st Port of HBA is
- * connected to MSA20 / MSA500
- * 0x20000, 0x20001, ... - If 2nd Port of HBA is
- * connected to MSA20 / MSA500
- */
- cmdlistp->Header.LUN.PhysDev.Bus =
- (ctlr->cpqary3_tgtp[i]->logical_id) >> 16;
- cmdlistp->Header.LUN.PhysDev.Mode =
- (cmdlistp->Header.LUN.PhysDev.Bus > 0) ?
- MASK_PERIPHERIAL_DEV_ADDR : PERIPHERIAL_DEV_ADDR;
-
- /*
- * Submit the command
- * Poll for its completion
- * If polling is not successful, something is wrong
- * with the controler
- * Return FAILURE (No point in continuing if h/w is
- * faulty !!!)
- */
-
- /* PERF */
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
- /* PERF */
-
- /* Sync Changes */
- if (cpqary3_synccmd_send(ctlr, cpqary3_cmdpvtp, 90000,
- CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- /* Timed out */
- cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp);
- return (CPQARY3_FAILURE);
- }
- if ((cpqary3_cmdpvtp->
- cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
- CPQARY3_SYNCCMD_FAILURE) &&
- (cpqary3_cmdpvtp->errorinfop->CommandStatus != 2)) {
- DTRACE_PROBE1(id_logdrv_fail,
- ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
- cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp);
- return (CPQARY3_FAILURE);
- }
- /* Sync Changes */
-
- ctlr->cpqary3_tgtp[i]->properties.drive.heads =
- idlogdrive->heads;
- ctlr->cpqary3_tgtp[i]->properties.drive.sectors =
- idlogdrive->sectors;
-
- DTRACE_PROBE2(tgt_geometry_detect,
- int, i, IdLogDrive *, idlogdrive);
+ for (i = 0; ld_count < ctlr->num_of_targets; i++) {
+ if (i == CTLR_SCSI_ID || ctlr->cpqary3_tgtp[i] == NULL) {
+ /* Go to the Next logical target */
+ continue;
}
- } else {
+ bzero(idlogdrive, sizeof (IdLogDrive));
+ cmdlistp->Request.CDB[1] = ctlr->cpqary3_tgtp[i]->logical_id;
+ /* Always zero */
+ cmdlistp->Header.LUN.PhysDev.TargetId = 0;
/*
- * Fix for QXCR1000446657: Logical drives are re numbered
- * after deleting a Logical drive.
- * introduced, new variable ld_count, which gets
- * incremented when the Target ID is found.
- * And for i=controller's SCSI ID and LDs with holes are found,
- * we continue talking to
- * the next logical drive in the per-target structure
+ * Logical volume Id numbering scheme is as follows
+ * 0x00000, 0x00001, ... - for Direct Attached
+ * 0x10000, 0x10001, ... - If 1st Port of HBA is
+ * connected to MSA20 / MSA500
+ * 0x20000, 0x20001, ... - If 2nd Port of HBA is
+ * connected to MSA20 / MSA500
*/
+ cmdlistp->Header.LUN.PhysDev.Bus =
+ (ctlr->cpqary3_tgtp[i]->logical_id) >> 16;
+ cmdlistp->Header.LUN.PhysDev.Mode =
+ (cmdlistp->Header.LUN.PhysDev.Bus > 0) ?
+ MASK_PERIPHERIAL_DEV_ADDR : PERIPHERIAL_DEV_ADDR;
- for (i = 0; ld_count < ctlr->num_of_targets; i++) {
- if (i == CTLR_SCSI_ID ||
- ctlr->cpqary3_tgtp[i] == NULL)
- /* Go to the Next logical target */
- continue;
- bzero(idlogdrive, sizeof (IdLogDrive));
- cmdlistp->Request.CDB[1] =
- ctlr->cpqary3_tgtp[i]->logical_id;
- /* Always zero */
- cmdlistp->Header.LUN.PhysDev.TargetId = 0;
- /*
- * Logical volume Id numbering scheme is as follows
- * 0x00000, 0x00001, ... - for Direct Attached
- * 0x10000, 0x10001, ... - If 1st Port of HBA is
- * connected to MSA20 / MSA500
- * 0x20000, 0x20001, ... - If 2nd Port of HBA is
- * connected to MSA20 / MSA500
- */
- cmdlistp->Header.LUN.PhysDev.Bus =
- (ctlr->cpqary3_tgtp[i]->logical_id) >> 16;
- cmdlistp->Header.LUN.PhysDev.Mode =
- (cmdlistp->Header.LUN.PhysDev.Bus > 0) ?
- MASK_PERIPHERIAL_DEV_ADDR : PERIPHERIAL_DEV_ADDR;
- /* PERF */
- cpqary3_cmdpvtp->complete = cpqary3_synccmd_complete;
- /* PERF */
-
- /*
- * Submit the command
- * Poll for its completion
- * If polling is not successful, something is wrong
- * with the controler
- * Return FAILURE (No point in continuing if h/w is
- * faulty !!!)
- */
-
- /* Sync Changes */
- if (cpqary3_synccmd_send(ctlr, cpqary3_cmdpvtp, 90000,
- CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
- /* Timed out */
- cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp);
- return (CPQARY3_FAILURE);
- }
- if ((cpqary3_cmdpvtp->
- cmdlist_memaddr->Header.Tag.drvinfo_n_err ==
- CPQARY3_SYNCCMD_FAILURE) &&
- (cpqary3_cmdpvtp->errorinfop->CommandStatus != 2)) {
- DTRACE_PROBE1(id_logdrv_fail,
- ErrorInfo_t *, cpqary3_cmdpvtp->errorinfop);
- cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp);
- return (CPQARY3_FAILURE);
- }
- /* Sync Changes */
+ cpcm->cpcm_complete = cpqary3_synccmd_complete;
- ctlr->cpqary3_tgtp[i]->properties.drive.heads =
- idlogdrive->heads;
- ctlr->cpqary3_tgtp[i]->properties.drive.sectors =
- idlogdrive->sectors;
+ /*
+ * Submit the command
+ * Poll for its completion
+ * If polling is not successful, something is wrong
+ * with the controler
+ * Return FAILURE (No point in continuing if h/w is
+ * faulty !!!)
+ */
- DTRACE_PROBE2(tgt_geometry_detect,
- int, i, IdLogDrive *, idlogdrive);
+ if (cpqary3_synccmd_send(ctlr, cpcm, 90000,
+ CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
+ /* Timed out */
+ cpqary3_synccmd_free(ctlr, cpcm);
+ return (CPQARY3_FAILURE);
+ }
- ld_count++;
+ if (cmdlistp->Header.Tag.error != 0 &&
+ cpcm->cpcm_va_err->CommandStatus != 2) {
+ DTRACE_PROBE1(id_logdrv_fail,
+ ErrorInfo_t *, cpcm->cpcm_va_err);
+ cpqary3_synccmd_free(ctlr, cpcm);
+ return (CPQARY3_FAILURE);
}
+
+ ctlr->cpqary3_tgtp[i]->properties.drive.heads =
+ idlogdrive->heads;
+ ctlr->cpqary3_tgtp[i]->properties.drive.sectors =
+ idlogdrive->sectors;
+
+ DTRACE_PROBE2(tgt_geometry_detect,
+ int, i, IdLogDrive *, idlogdrive);
+
+ ld_count++;
}
- /* Sync Changes */
- cpqary3_synccmd_free(ctlr, cpqary3_cmdpvtp);
- /* Sync Changes */
+ cpqary3_synccmd_free(ctlr, cpcm);
return (CPQARY3_SUCCESS);
}