diff options
| author | Joshua M. Clulow <jmc@joyent.com> | 2016-02-28 08:16:44 +0000 |
|---|---|---|
| committer | Joshua M. Clulow <jmc@joyent.com> | 2016-07-06 16:25:14 +0000 |
| commit | c77e6a5cd33b65f552adf2b60cacf437e43163d7 (patch) | |
| tree | b2a5271fe78a3f0cd9970932181bbf21a70d71b5 /usr/src | |
| parent | 93748a271b44434294fbc444dac0eb17fee6d2d7 (diff) | |
| download | illumos-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.files | 5 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3.c | 187 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3.h | 185 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_ciss.h | 61 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_isr.c | 196 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_mem.c | 595 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_noe.c | 31 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_scsi.c | 430 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_talk2ctlr.c | 921 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_transport.c | 338 | ||||
| -rw-r--r-- | usr/src/uts/common/io/cpqary3/cpqary3_util.c | 518 |
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); } |
