14c06356bSdh /* 24c06356bSdh * CDDL HEADER START 34c06356bSdh * 44c06356bSdh * The contents of this file are subject to the terms of the 54c06356bSdh * Common Development and Distribution License (the "License"). 64c06356bSdh * You may not use this file except in compliance with the License. 74c06356bSdh * 84c06356bSdh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94c06356bSdh * or http://www.opensolaris.org/os/licensing. 104c06356bSdh * See the License for the specific language governing permissions 114c06356bSdh * and limitations under the License. 124c06356bSdh * 134c06356bSdh * When distributing Covered Code, include this CDDL HEADER in each 144c06356bSdh * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154c06356bSdh * If applicable, add the following below this CDDL HEADER, with the 164c06356bSdh * fields enclosed by brackets "[]" replaced with your own identifying 174c06356bSdh * information: Portions Copyright [yyyy] [name of copyright owner] 184c06356bSdh * 194c06356bSdh * CDDL HEADER END 204c06356bSdh * 214c06356bSdh * 2273a3eccdSDavid Hollister * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 234c06356bSdh * Use is subject to license terms. 244c06356bSdh */ 254c06356bSdh /* 264c06356bSdh * This file is the principle header file for the PMCS driver 274c06356bSdh */ 284c06356bSdh #ifndef _PMCS_H 294c06356bSdh #define _PMCS_H 304c06356bSdh #ifdef __cplusplus 314c06356bSdh extern "C" { 324c06356bSdh #endif 334c06356bSdh 344c06356bSdh 354c06356bSdh #include <sys/cpuvar.h> 364c06356bSdh #include <sys/ddi.h> 374c06356bSdh #include <sys/sunddi.h> 384c06356bSdh #include <sys/modctl.h> 394c06356bSdh #include <sys/pci.h> 404c06356bSdh #include <sys/pcie.h> 419719310aSDavid Hollister #include <sys/file.h> 424c06356bSdh #include <sys/isa_defs.h> 434c06356bSdh #include <sys/sunmdi.h> 444c06356bSdh #include <sys/mdi_impldefs.h> 454c06356bSdh #include <sys/scsi/scsi.h> 464c06356bSdh #include <sys/scsi/impl/scsi_reset_notify.h> 4796c4a178SChris Horne #include <sys/scsi/impl/scsi_sas.h> 4896c4a178SChris Horne #include <sys/scsi/impl/smp_transport.h> 494c06356bSdh #include <sys/scsi/generic/sas.h> 5096c4a178SChris Horne #include <sys/scsi/generic/smp_frames.h> 514c06356bSdh #include <sys/atomic.h> 524c06356bSdh #include <sys/byteorder.h> 534b456463SDavid Hollister #include <sys/sysmacros.h> 544c06356bSdh #include <sys/bitmap.h> 554c06356bSdh #include <sys/queue.h> 564c06356bSdh #include <sys/sdt.h> 574c06356bSdh #include <sys/ddifm.h> 584c06356bSdh #include <sys/fm/protocol.h> 594c06356bSdh #include <sys/fm/util.h> 604c06356bSdh #include <sys/fm/io/ddi.h> 614c06356bSdh #include <sys/scsi/impl/spc3_types.h> 624c06356bSdh 634c06356bSdh typedef struct pmcs_hw pmcs_hw_t; 644c06356bSdh typedef struct pmcs_iport pmcs_iport_t; 654c06356bSdh typedef struct pmcs_phy pmcs_phy_t; 664c06356bSdh typedef struct lsas_cmd lsas_cmd_t; 674c06356bSdh typedef struct lsas_result lsas_result_t; 684c06356bSdh typedef struct lsata_cmd lsata_cmd_t; 694c06356bSdh typedef struct lsata_result lsata_result_t; 704c06356bSdh typedef struct pmcwork pmcwork_t; 714c06356bSdh typedef struct pmcs_cmd pmcs_cmd_t; 724c06356bSdh typedef struct pmcs_xscsi pmcs_xscsi_t; 734c06356bSdh typedef struct pmcs_lun pmcs_lun_t; 744c06356bSdh typedef struct pmcs_chunk pmcs_chunk_t; 754c06356bSdh 764c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_param.h> 774c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_reg.h> 784c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_mpi.h> 794c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_iomb.h> 804c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_sgl.h> 814c06356bSdh 824c06356bSdh #include <sys/scsi/adapters/pmcs/ata.h> 834c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_def.h> 844c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_proto.h> 854c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_scsa.h> 864c06356bSdh #include <sys/scsi/adapters/pmcs/pmcs_smhba.h> 874c06356bSdh 884c06356bSdh #define PMCS_MAX_UA_SIZE 32 894c06356bSdh 904c06356bSdh struct pmcs_xscsi { 914c06356bSdh uint32_t 924c06356bSdh ca : 1, /* SATA specific */ 934c06356bSdh ncq : 1, /* SATA specific */ 944c06356bSdh pio : 1, /* SATA specific */ 954c06356bSdh special_needed : 1, /* SATA specific */ 964c06356bSdh special_running : 1, /* SATA specific */ 974c06356bSdh reset_success : 1, /* last reset ok */ 984c06356bSdh reset_wait : 1, /* wait for reset */ 994c06356bSdh resetting : 1, /* now resetting */ 1004c06356bSdh recover_wait : 1, /* wait for recovery */ 1014c06356bSdh recovering : 1, /* now recovering */ 1024c06356bSdh event_recovery : 1, /* event recovery */ 1034c06356bSdh draining : 1, 1044c06356bSdh new : 1, 1054c06356bSdh assigned : 1, 1064c06356bSdh dev_gone : 1, 1074c06356bSdh phy_addressable : 1, /* Direct attach SATA */ 1084c06356bSdh dev_state : 4; 1094c06356bSdh uint16_t maxdepth; 1104c06356bSdh uint16_t qdepth; 111601c90f1SSrikanth, Ramana uint16_t actv_cnt; /* Pkts ON CHIP */ 112601c90f1SSrikanth, Ramana uint16_t actv_pkts; /* Pkts in driver */ 1134c06356bSdh uint16_t target_num; 1144c06356bSdh /* statlock protects both target stats and the special queue (sq) */ 1154c06356bSdh kmutex_t statlock; 1164c06356bSdh int32_t ref_count; 1174c06356bSdh dev_info_t *dip; /* Solaris device dip */ 1184c06356bSdh pmcs_phy_t *phy; 1194c06356bSdh STAILQ_HEAD(wqh, pmcs_cmd) wq; 1204c06356bSdh pmcs_cmd_t *wq_recovery_tail; /* See below */ 1214c06356bSdh kmutex_t wqlock; 1224c06356bSdh STAILQ_HEAD(aqh, pmcs_cmd) aq; 1234c06356bSdh kmutex_t aqlock; 1244c06356bSdh STAILQ_HEAD(sqh, pmcs_cmd) sq; /* SATA specific */ 1254c06356bSdh uint32_t tagmap; /* SATA specific */ 1264c06356bSdh pmcs_hw_t *pwp; 1274c06356bSdh ddi_soft_state_bystr *lun_sstate; 1284c06356bSdh uint64_t capacity; /* SATA specific */ 1294c06356bSdh char unit_address[PMCS_MAX_UA_SIZE]; 1304c06356bSdh kcondvar_t reset_cv; 1314c06356bSdh kcondvar_t abort_cv; 1324c06356bSdh char *ua; 1334c06356bSdh pmcs_dtype_t dtype; 13473a3eccdSDavid Hollister list_t lun_list; /* list of LUNs */ 135499cfd15SDavid Hollister struct smp_device *smpd; /* Ptr to smp_device */ 1364c06356bSdh }; 1374c06356bSdh 1384c06356bSdh /* 1394c06356bSdh * wq_recovery_tail in the pmcs_xscsi structure is a pointer to a command in 1404c06356bSdh * the wait queue (wq). That pointer is the last command in the wait queue 1414c06356bSdh * that needs to be reissued after device state recovery is complete. Commands 1424c06356bSdh * that need to be retried are reinserted into the wq after wq_recovery_tail 1434c06356bSdh * to maintain the order in which the commands were originally submitted. 1444c06356bSdh */ 1454c06356bSdh 1464c06356bSdh #define PMCS_INVALID_TARGET_NUM (uint16_t)-1 1474c06356bSdh 1484c06356bSdh #define PMCS_TGT_WAIT_QUEUE 0x01 1494c06356bSdh #define PMCS_TGT_ACTIVE_QUEUE 0x02 1504c06356bSdh #define PMCS_TGT_SPECIAL_QUEUE 0x04 1514c06356bSdh #define PMCS_TGT_ALL_QUEUES 0xff 1524c06356bSdh 1534c06356bSdh /* 1544c06356bSdh * LUN representation. Just a LUN (number) and pointer to the target 1554c06356bSdh * structure (pmcs_xscsi). 1564c06356bSdh */ 1574c06356bSdh 1584c06356bSdh struct pmcs_lun { 15973a3eccdSDavid Hollister list_node_t lun_list_next; 16073a3eccdSDavid Hollister pmcs_xscsi_t *target; 16173a3eccdSDavid Hollister struct scsi_device *sd; 16273a3eccdSDavid Hollister uint64_t lun_num; /* lun64 */ 16373a3eccdSDavid Hollister scsi_lun_t scsi_lun; /* Wire format */ 16473a3eccdSDavid Hollister char unit_address[PMCS_MAX_UA_SIZE]; 1654c06356bSdh }; 1664c06356bSdh 1674c06356bSdh /* 1684c06356bSdh * Interrupt coalescing values 1694c06356bSdh */ 1704c06356bSdh #define PMCS_MAX_IO_COMPS_PER_INTR 12 1714c06356bSdh #define PMCS_MAX_IO_COMPS_HIWAT_SHIFT 6 1724c06356bSdh #define PMCS_MAX_IO_COMPS_LOWAT_SHIFT 10 1734c06356bSdh #define PMCS_QUANTUM_TIME_USECS (1000000 / 10) /* 1/10th sec. */ 1744c06356bSdh #define PMCS_MAX_COAL_TIMER 0x200 /* Don't set > than this */ 1754c06356bSdh #define PMCS_MAX_CQ_THREADS 4 1764c06356bSdh #define PMCS_COAL_TIMER_GRAN 2 /* Go up/down by 2 usecs */ 1774c06356bSdh #define PMCS_INTR_THRESHOLD(x) ((x) * 6 / 10) 1784c06356bSdh 1794c06356bSdh /* 1804c06356bSdh * This structure is used to maintain state with regard to I/O interrupt 1814c06356bSdh * coalescing. 1824c06356bSdh */ 1834c06356bSdh 1844c06356bSdh typedef struct pmcs_io_intr_coal_s { 1854c06356bSdh hrtime_t nsecs_between_intrs; 1864c06356bSdh hrtime_t last_io_comp; 1874c06356bSdh clock_t quantum; 1884c06356bSdh uint32_t num_io_completions; 1894c06356bSdh uint32_t num_intrs; 1904c06356bSdh uint32_t max_io_completions; 1914c06356bSdh uint32_t intr_latency; 1924c06356bSdh uint32_t intr_threshold; 1934c06356bSdh uint16_t intr_coal_timer; 1944c06356bSdh boolean_t timer_on; 1954c06356bSdh boolean_t stop_thread; 1964c06356bSdh boolean_t int_cleared; 1974c06356bSdh } pmcs_io_intr_coal_t; 1984c06356bSdh 1994c06356bSdh typedef struct pmcs_cq_thr_info_s { 2004c06356bSdh kthread_t *cq_thread; 2014c06356bSdh kmutex_t cq_thr_lock; 2024c06356bSdh kcondvar_t cq_cv; 2034c06356bSdh pmcs_hw_t *cq_pwp; 2044c06356bSdh } pmcs_cq_thr_info_t; 2054c06356bSdh 2064c06356bSdh typedef struct pmcs_cq_info_s { 2074c06356bSdh uint32_t cq_threads; 2084c06356bSdh uint32_t cq_next_disp_thr; 2094c06356bSdh boolean_t cq_stop; 2104c06356bSdh pmcs_cq_thr_info_t *cq_thr_info; 2114c06356bSdh } pmcs_cq_info_t; 2124c06356bSdh 2134c06356bSdh typedef struct pmcs_iocomp_cb_s { 2144c06356bSdh pmcwork_t *pwrk; 2154c06356bSdh char iomb[PMCS_QENTRY_SIZE << 1]; 2164c06356bSdh struct pmcs_iocomp_cb_s *next; 2174c06356bSdh } pmcs_iocomp_cb_t; 2184c06356bSdh 2194c06356bSdh typedef struct pmcs_iqp_trace_s { 2204c06356bSdh char *head; 2214c06356bSdh char *curpos; 2224c06356bSdh uint32_t size_left; 2234c06356bSdh } pmcs_iqp_trace_t; 2244c06356bSdh 2254c06356bSdh /* 2264c06356bSdh * Used by string-based softstate as hint to possible size. 2274c06356bSdh */ 2284c06356bSdh 2294c06356bSdh #define PMCS_TGT_SSTATE_SZ 64 2304c06356bSdh #define PMCS_LUN_SSTATE_SZ 4 2314c06356bSdh 2324c06356bSdh /* 2334c06356bSdh * HBA iport node softstate 2344c06356bSdh */ 235601c90f1SSrikanth, Ramana #define PMCS_IPORT_INVALID_PORT_ID 0xf 2364c06356bSdh 2374c06356bSdh struct pmcs_iport { 2384c06356bSdh kmutex_t lock; /* iport lock */ 2394c06356bSdh list_node_t list_node; /* list node for pwp->iports list_t */ 2404c06356bSdh kmutex_t refcnt_lock; /* refcnt lock */ 2414c06356bSdh kcondvar_t refcnt_cv; /* refcnt cv */ 2424c06356bSdh int refcnt; /* refcnt for this iport */ 2434c06356bSdh dev_info_t *dip; /* iport dip */ 2444c06356bSdh pmcs_hw_t *pwp; /* back pointer to HBA state */ 2454c06356bSdh pmcs_phy_t *pptr; /* pointer to this port's primary phy */ 2464c06356bSdh enum { /* unit address state in the phymap */ 2474c06356bSdh UA_INACTIVE, 2484c06356bSdh UA_PEND_ACTIVATE, 2494c06356bSdh UA_ACTIVE, 2504c06356bSdh UA_PEND_DEACTIVATE 2514c06356bSdh } ua_state; 2524c06356bSdh char *ua; /* unit address (phy mask) */ 2534c06356bSdh int portid; /* portid */ 2544c06356bSdh int report_skip; /* skip or report during discovery */ 2554c06356bSdh list_t phys; /* list of phys on this port */ 2564c06356bSdh int nphy; /* number of phys in this port */ 2574c06356bSdh scsi_hba_tgtmap_t *iss_tgtmap; /* tgtmap */ 2584c06356bSdh ddi_soft_state_bystr *tgt_sstate; /* tgt softstate */ 2596745c559SJesse Butler /* SMP serialization */ 2606745c559SJesse Butler kmutex_t smp_lock; 2616745c559SJesse Butler kcondvar_t smp_cv; 2626745c559SJesse Butler boolean_t smp_active; 2636745c559SJesse Butler kthread_t *smp_active_thread; 2644c06356bSdh }; 2654c06356bSdh 2664c06356bSdh struct pmcs_chunk { 2674c06356bSdh pmcs_chunk_t *next; 2684c06356bSdh ddi_acc_handle_t acc_handle; 2694c06356bSdh ddi_dma_handle_t dma_handle; 2704c06356bSdh uint8_t *addrp; 2714c06356bSdh uint64_t dma_addr; 2724c06356bSdh }; 2734c06356bSdh 2744c06356bSdh /* 2754c06356bSdh * HBA node (i.e. non-iport) softstate 2764c06356bSdh */ 2774c06356bSdh struct pmcs_hw { 2784c06356bSdh /* 2794c06356bSdh * Identity 2804c06356bSdh */ 2814c06356bSdh dev_info_t *dip; 2824c06356bSdh 2834c06356bSdh /* 2844c06356bSdh * 16 possible initiator PHY WWNs 2854c06356bSdh */ 2864c06356bSdh uint64_t sas_wwns[PMCS_MAX_PORTS]; 2874c06356bSdh 2884c06356bSdh /* 2894c06356bSdh * Card State 2904c06356bSdh */ 2914c06356bSdh enum pwpstate { 2924c06356bSdh STATE_NIL, 2934c06356bSdh STATE_PROBING, 2944c06356bSdh STATE_RUNNING, 2954c06356bSdh STATE_UNPROBING, 2965c45adf0SJesse Butler STATE_IN_RESET, 2974c06356bSdh STATE_DEAD 2984c06356bSdh } state; 2994c06356bSdh 3005c45adf0SJesse Butler /* 3015c45adf0SJesse Butler * Last reason for a soft reset 3025c45adf0SJesse Butler */ 3035c45adf0SJesse Butler enum pwp_last_reset_reason { 3045c45adf0SJesse Butler PMCS_LAST_RST_UNINIT, 3055c45adf0SJesse Butler PMCS_LAST_RST_ATTACH, 3065c45adf0SJesse Butler PMCS_LAST_RST_FW_UPGRADE, 3075c45adf0SJesse Butler PMCS_LAST_RST_FATAL_ERROR, 3085c45adf0SJesse Butler PMCS_LAST_RST_STALL, 3095c45adf0SJesse Butler PMCS_LAST_RST_QUIESCE, 3105c45adf0SJesse Butler PMCS_LAST_RST_DETACH 3115c45adf0SJesse Butler } last_reset_reason; 3125c45adf0SJesse Butler 3134c06356bSdh uint32_t 3144c06356bSdh fw_disable_update : 1, 3154c06356bSdh fw_force_update : 1, 3164c06356bSdh blocked : 1, 3174c06356bSdh stuck : 1, 3184c06356bSdh locks_initted : 1, 3194c06356bSdh mpi_table_setup : 1, 3204c06356bSdh hba_attached : 1, 3214c06356bSdh iports_attached : 1, 3224c06356bSdh suspended : 1, 3234c06356bSdh separate_ports : 1, 3244c06356bSdh fwlog : 4, 3254c06356bSdh phymode : 3, 3264c06356bSdh physpeed : 3, 3274c06356bSdh resource_limited : 1, 3284c06356bSdh configuring : 1, 3295c45adf0SJesse Butler ds_err_recovering : 1, 3309719310aSDavid Hollister quiesced : 1, 3319719310aSDavid Hollister fwlog_file : 1; 3324c06356bSdh 3334c06356bSdh /* 3344c06356bSdh * This HBA instance's iportmap and list of iport states. 3354c06356bSdh * Note: iports_lock protects iports, iports_attached, and 3364c06356bSdh * num_iports on the HBA softstate. 3374c06356bSdh */ 3384c06356bSdh krwlock_t iports_lock; 3394c06356bSdh scsi_hba_iportmap_t *hss_iportmap; 3404c06356bSdh list_t iports; 3414c06356bSdh int num_iports; 3424c06356bSdh 3434c06356bSdh sas_phymap_t *hss_phymap; 3444c06356bSdh int phymap_active; 3454c06356bSdh 3464c06356bSdh /* 3474c06356bSdh * Locks 3484c06356bSdh */ 3494c06356bSdh kmutex_t lock; 3504c06356bSdh kmutex_t dma_lock; 3514c06356bSdh kmutex_t axil_lock; 3524c06356bSdh kcondvar_t drain_cv; 3534c06356bSdh 3544c06356bSdh /* 3554c06356bSdh * FMA Capabilities 3564c06356bSdh */ 3574c06356bSdh int fm_capabilities; 3584c06356bSdh 3594c06356bSdh /* 3604c06356bSdh * Register Access Handles 3614c06356bSdh */ 3624c06356bSdh ddi_device_acc_attr_t dev_acc_attr; 3634c06356bSdh ddi_device_acc_attr_t reg_acc_attr; 3644c06356bSdh ddi_acc_handle_t pci_acc_handle; 3654c06356bSdh ddi_acc_handle_t msg_acc_handle; 3664c06356bSdh ddi_acc_handle_t top_acc_handle; 3674c06356bSdh ddi_acc_handle_t mpi_acc_handle; 3684c06356bSdh ddi_acc_handle_t gsm_acc_handle; 3694c06356bSdh ddi_acc_handle_t iqp_acchdls[PMCS_MAX_IQ]; 3704c06356bSdh ddi_acc_handle_t oqp_acchdls[PMCS_MAX_IQ]; 3714c06356bSdh ddi_acc_handle_t cip_acchdls; 3724c06356bSdh ddi_acc_handle_t fwlog_acchdl; 3734c06356bSdh ddi_acc_handle_t regdump_acchdl; 3744c06356bSdh 3754c06356bSdh /* 3764c06356bSdh * DMA Handles 3774c06356bSdh */ 3784c06356bSdh ddi_dma_attr_t iqp_dma_attr; 3794c06356bSdh ddi_dma_attr_t oqp_dma_attr; 3804c06356bSdh ddi_dma_attr_t cip_dma_attr; 3814c06356bSdh ddi_dma_attr_t fwlog_dma_attr; 3824c06356bSdh ddi_dma_attr_t regdump_dma_attr; 3834c06356bSdh ddi_dma_handle_t iqp_handles[PMCS_MAX_IQ]; 3844c06356bSdh ddi_dma_handle_t oqp_handles[PMCS_MAX_OQ]; 3854c06356bSdh ddi_dma_handle_t cip_handles; 3864c06356bSdh ddi_dma_handle_t fwlog_hndl; 3874c06356bSdh ddi_dma_handle_t regdump_hndl; 3884c06356bSdh 3894c06356bSdh /* 3904c06356bSdh * Register Pointers 3914c06356bSdh */ 3924c06356bSdh uint32_t *msg_regs; /* message unit registers */ 3934c06356bSdh uint32_t *top_regs; /* top unit registers */ 3944c06356bSdh uint32_t *mpi_regs; /* message passing unit registers */ 3954c06356bSdh uint32_t *gsm_regs; /* GSM registers */ 3964c06356bSdh 3974c06356bSdh /* 3984c06356bSdh * Message Passing and other offsets. 3994c06356bSdh * 4004c06356bSdh * mpi_offset is the offset within the fourth register set (mpi_regs) 4014c06356bSdh * that contains the base of the MPI structures. Since this is actually 4024c06356bSdh * set by the card firmware, it can change from startup to startup. 4034c06356bSdh * 4044c06356bSdh * The other offsets (gst, iqc, oqc) are for similar tables in 4054c06356bSdh * MPI space, typically only accessed during setup. 4064c06356bSdh */ 4074c06356bSdh uint32_t mpi_offset; 4084c06356bSdh uint32_t mpi_gst_offset; 4094c06356bSdh uint32_t mpi_iqc_offset; 4104c06356bSdh uint32_t mpi_oqc_offset; 4114c06356bSdh 4124c06356bSdh /* 4134c06356bSdh * Inbound and outbound queue depth 4144c06356bSdh */ 4154c06356bSdh uint32_t ioq_depth; 4164c06356bSdh 4174c06356bSdh /* 4184c06356bSdh * Kernel addresses and offsets for Inbound Queue Producer Indices 4194c06356bSdh * 4204c06356bSdh * See comments in pmcs_iomb.h about Inbound Queues. Since it 4214c06356bSdh * is relatively expensive to go across the PCIe bus to read or 4224c06356bSdh * write inside the card, we maintain shadow copies in kernel 4234c06356bSdh * memory and update the card as needed. 4244c06356bSdh */ 4254c06356bSdh uint32_t shadow_iqpi[PMCS_MAX_IQ]; 4264c06356bSdh uint32_t iqpi_offset[PMCS_MAX_IQ]; 427*d78a6b7eSJesse Butler uint32_t last_iqci[PMCS_MAX_IQ]; 428*d78a6b7eSJesse Butler uint32_t last_htag[PMCS_MAX_IQ]; 4294c06356bSdh uint32_t *iqp[PMCS_MAX_IQ]; 4304c06356bSdh kmutex_t iqp_lock[PMCS_NIQ]; 4314c06356bSdh 4324c06356bSdh pmcs_iqp_trace_t *iqpt; 4334c06356bSdh 4344c06356bSdh /* 4354c06356bSdh * Kernel addresses and offsets for Outbound Queue Consumer Indices 4364c06356bSdh */ 4374c06356bSdh uint32_t *oqp[PMCS_MAX_OQ]; 4384c06356bSdh uint32_t oqci_offset[PMCS_MAX_OQ]; 4394c06356bSdh 4404c06356bSdh /* 4414c06356bSdh * Driver's copy of the outbound queue indices 4424c06356bSdh */ 4434c06356bSdh 4444c06356bSdh uint32_t oqci[PMCS_NOQ]; 4454c06356bSdh uint32_t oqpi[PMCS_NOQ]; 4464c06356bSdh 4474c06356bSdh /* 4484c06356bSdh * DMA addresses for both Inbound and Outbound queues. 4494c06356bSdh */ 4504c06356bSdh uint64_t oqaddr[PMCS_MAX_OQ]; 4514c06356bSdh uint64_t iqaddr[PMCS_MAX_IQ]; 4524c06356bSdh 4534c06356bSdh /* 4544c06356bSdh * Producer/Queue Host Memory Pointers and scratch areas, 4554c06356bSdh * as well as DMA scatter/gather chunk areas. 4564c06356bSdh * 4574c06356bSdh * See discussion in pmcs_def.h about how this is laid out. 4584c06356bSdh */ 4594c06356bSdh uint8_t *cip; 4604c06356bSdh uint64_t ciaddr; 4614c06356bSdh 4624c06356bSdh /* 4634c06356bSdh * Scratch area pointer and DMA addrress for SATA and SMP operations. 4644c06356bSdh */ 4654c06356bSdh void *scratch; 4664c06356bSdh uint64_t scratch_dma; 4674c06356bSdh volatile uint8_t scratch_locked; /* Scratch area ownership */ 4684c06356bSdh 4694c06356bSdh /* 4709719310aSDavid Hollister * Firmware info 4719719310aSDavid Hollister * 4729719310aSDavid Hollister * fwlogp: Pointer to block of memory mapped for the event logs 4739719310aSDavid Hollister * fwlogp_aap1: Pointer to the beginning of the AAP1 event log 4749719310aSDavid Hollister * fwlogp_iop: Pointer to the beginning of the IOP event log 4759719310aSDavid Hollister * fwaddr: The physical address of fwlogp 4769719310aSDavid Hollister * 4779719310aSDavid Hollister * fwlogfile_aap1/iop: Path to the saved AAP1/IOP event logs 4789719310aSDavid Hollister * fwlog_max_entries_aap1/iop: Max # of entries in each log 4799719310aSDavid Hollister * fwlog_oldest_idx_aap1/iop: Index of oldest entry in each log 4809719310aSDavid Hollister * fwlog_latest_idx_aap1/iop: Index of newest entry in each log 4819719310aSDavid Hollister * fwlog_threshold_aap1/iop: % full at which we save the event log 4829719310aSDavid Hollister * fwlog_findex_aap1/iop: Suffix to each event log's next filename 4839719310aSDavid Hollister * 4849719310aSDavid Hollister * Firmware event logs are written out to the filenames specified in 4859719310aSDavid Hollister * fwlogp_aap1/iop when the number of entries in the in-memory copy 4869719310aSDavid Hollister * reaches or exceeds the threshold value. The filenames are suffixed 4879719310aSDavid Hollister * with .X where X is an integer ranging from 0 to 4. This allows us 4889719310aSDavid Hollister * to save up to 5MB of event log data for each log. 4894c06356bSdh */ 4904c06356bSdh uint32_t *fwlogp; 4919719310aSDavid Hollister pmcs_fw_event_hdr_t *fwlogp_aap1; 4929719310aSDavid Hollister pmcs_fw_event_hdr_t *fwlogp_iop; 4934c06356bSdh uint64_t fwaddr; 4949719310aSDavid Hollister char fwlogfile_aap1[MAXPATHLEN + 1]; 4959719310aSDavid Hollister uint32_t fwlog_max_entries_aap1; 4969719310aSDavid Hollister uint32_t fwlog_oldest_idx_aap1; 4979719310aSDavid Hollister uint32_t fwlog_latest_idx_aap1; 4989719310aSDavid Hollister uint32_t fwlog_threshold_aap1; 4999719310aSDavid Hollister uint32_t fwlog_findex_aap1; 5009719310aSDavid Hollister char fwlogfile_iop[MAXPATHLEN + 1]; 5019719310aSDavid Hollister uint32_t fwlog_max_entries_iop; 5029719310aSDavid Hollister uint32_t fwlog_oldest_idx_iop; 5039719310aSDavid Hollister uint32_t fwlog_latest_idx_iop; 5049719310aSDavid Hollister uint32_t fwlog_threshold_iop; 5059719310aSDavid Hollister uint32_t fwlog_findex_iop; 5064c06356bSdh 5074c06356bSdh /* 5084c06356bSdh * Internal register dump region and flash chunk DMA info 5094c06356bSdh */ 5104c06356bSdh 5114c06356bSdh caddr_t regdumpp; 5124c06356bSdh uint32_t *flash_chunkp; 5134c06356bSdh uint64_t flash_chunk_addr; 5144c06356bSdh 5155c45adf0SJesse Butler /* 5165c45adf0SJesse Butler * Copies of the last read MSGU and IOP heartbeats. 5175c45adf0SJesse Butler */ 5185c45adf0SJesse Butler uint32_t last_msgu_tick; 5195c45adf0SJesse Butler uint32_t last_iop_tick; 5205c45adf0SJesse Butler 5214c06356bSdh /* 5224c06356bSdh * Card information, some determined during MPI setup 5234c06356bSdh */ 5244c06356bSdh uint32_t fw; /* firmware version */ 5254c06356bSdh uint8_t max_iq; /* maximum inbound queues this card */ 5264c06356bSdh uint8_t max_oq; /* "" outbound "" */ 5274c06356bSdh uint8_t nphy; /* number of phys this card */ 5284c06356bSdh uint8_t chiprev; /* chip revision */ 5294c06356bSdh uint16_t max_cmd; /* max number of commands supported */ 5304c06356bSdh uint16_t max_dev; /* max number of devices supported */ 5314c06356bSdh uint16_t last_wq_dev; /* last dev whose wq was serviced */ 5324c06356bSdh 5335c45adf0SJesse Butler /* 5345c45adf0SJesse Butler * Counter for the number of times watchdog fires. We can use this 5355c45adf0SJesse Butler * to throttle events which fire off of the watchdog, such as the 5365c45adf0SJesse Butler * forward progress detection routine. 5375c45adf0SJesse Butler */ 5385c45adf0SJesse Butler uint8_t watchdog_count; 5394c06356bSdh 5404c06356bSdh /* 5414c06356bSdh * Interrupt Setup stuff. 5424c06356bSdh * 5434c06356bSdh * int_type defines the kind of interrupt we're using with this card. 5444c06356bSdh * oqvec defines the relationship between an Outbound Queue Number and 5454c06356bSdh * a MSI-X vector. 5464c06356bSdh */ 5474c06356bSdh enum { 5484c06356bSdh PMCS_INT_NONE, 5494c06356bSdh PMCS_INT_TIMER, 5504c06356bSdh PMCS_INT_MSI, 5514c06356bSdh PMCS_INT_MSIX, 5524c06356bSdh PMCS_INT_FIXED 5534c06356bSdh } int_type; 5544c06356bSdh uint8_t oqvec[PMCS_NOQ]; 5554c06356bSdh 5564c06356bSdh /* 5574c06356bSdh * Interrupt handle table and size 5584c06356bSdh */ 5594c06356bSdh ddi_intr_handle_t *ih_table; 5604c06356bSdh size_t ih_table_size; 5614c06356bSdh 5624c06356bSdh timeout_id_t wdhandle; 5634c06356bSdh uint32_t intr_mask; 5644c06356bSdh int intr_cnt; 5654c06356bSdh int intr_cap; 5664c06356bSdh uint32_t odb_auto_clear; 5674c06356bSdh 5684c06356bSdh /* 5694c06356bSdh * DMA S/G chunk list 5704c06356bSdh */ 5714c06356bSdh int nchunks; 5724c06356bSdh pmcs_chunk_t *dma_chunklist; 5734c06356bSdh 5744c06356bSdh /* 5754c06356bSdh * Front of the DMA S/G chunk freelist 5764c06356bSdh */ 5774c06356bSdh pmcs_dmachunk_t *dma_freelist; 5784c06356bSdh 5794c06356bSdh /* 5804c06356bSdh * PHY and Discovery Related Stuff 5814c06356bSdh * 5824c06356bSdh * The PMC chip can have up to 16 local phys. We build a level-first 5834c06356bSdh * traversal tree of phys starting with the physical phys on the 5844c06356bSdh * chip itself (i.e., treating the chip as if it were an expander). 5854c06356bSdh * 5864c06356bSdh * Our discovery process goes through a level and discovers what 5874c06356bSdh * each entity is (and it's phy number within that expander's 5884c06356bSdh * address space). It then configures each non-empty item (SAS, 5894c06356bSdh * SATA/STP, EXPANDER). For expanders, it then performs 5904c06356bSdh * discover on that expander itself via REPORT GENERAL and 5914c06356bSdh * DISCOVERY SMP commands, attaching the discovered entities 5924c06356bSdh * to the next level. Then we step down a level and continue 5934c06356bSdh * (and so on). 5944c06356bSdh * 5954c06356bSdh * The PMC chip maintains an I_T_NEXUS notion based upon our 5964c06356bSdh * registering each new device found (getting back a device handle). 5974c06356bSdh * 5984c06356bSdh * Like with the number of physical PHYS being a maximum of 16, 5994c06356bSdh * there are a maximum number of PORTS also being 16. Some 6004c06356bSdh * events apply to PORTS entirely, so we track PORTS as well. 6014c06356bSdh */ 6024c06356bSdh pmcs_phy_t *root_phys; /* HBA PHYs (level 0) */ 6034c06356bSdh pmcs_phy_t *ports[PMCS_MAX_PORTS]; 6044c06356bSdh kmutex_t dead_phylist_lock; /* Protects dead_phys */ 6054c06356bSdh pmcs_phy_t *dead_phys; /* PHYs waiting to be freed */ 6064c06356bSdh 6074c06356bSdh kmem_cache_t *phy_cache; 6084c06356bSdh 6094c06356bSdh /* 6104c06356bSdh * Discovery-related items. 6114c06356bSdh * config_lock: Protects config_changed and should never be held 6124c06356bSdh * outside of getting or setting the value of config_changed. 6134c06356bSdh * config_changed: Boolean indicating whether discovery needs to 6144c06356bSdh * be restarted. 6154c06356bSdh * configuring: 1 = discovery is running, 0 = discovery not running. 6164c06356bSdh * NOTE: configuring is now in the bitfield above. 6179aed1621SDavid Hollister * 6189aed1621SDavid Hollister * config_restart_time is set by the tgtmap_[de]activate callbacks each 6199aed1621SDavid Hollister * time we decide we want SCSA to retry enumeration on some device. 6209aed1621SDavid Hollister * The watchdog timer will not fire discovery unless it has reached 6219aed1621SDavid Hollister * config_restart_time and config_restart is TRUE. This ensures that 6229aed1621SDavid Hollister * we don't ask SCSA to retry enumerating devices while it is still 6239aed1621SDavid Hollister * running. 6244c06356bSdh */ 6254c06356bSdh kmutex_t config_lock; 6264c06356bSdh volatile boolean_t config_changed; 6279aed1621SDavid Hollister boolean_t config_restart; 6289aed1621SDavid Hollister clock_t config_restart_time; 6294c06356bSdh 6304c06356bSdh /* 6314c06356bSdh * Work Related Stuff 6324c06356bSdh * 6334c06356bSdh * Each command given to the PMC chip has an associated work structure. 6344c06356bSdh * See the discussion in pmcs_def.h about work structures. 6354c06356bSdh */ 6364c06356bSdh pmcwork_t *work; /* pool of work structures */ 6374c06356bSdh STAILQ_HEAD(wfh, pmcwork) wf; /* current freelist */ 6384c06356bSdh STAILQ_HEAD(pfh, pmcwork) pf; /* current pending freelist */ 6394c06356bSdh uint16_t wserno; /* rolling serial number */ 6404c06356bSdh kmutex_t wfree_lock; /* freelist/actvlist/wserno lock */ 6414c06356bSdh kmutex_t pfree_lock; /* freelist/actvlist/wserno lock */ 6424c06356bSdh 6434c06356bSdh /* 6444c06356bSdh * Solaris/SCSA items. 6454c06356bSdh */ 6464c06356bSdh scsi_hba_tran_t *tran; 64796c4a178SChris Horne smp_hba_tran_t *smp_tran; 6484c06356bSdh struct scsi_reset_notify_entry *reset_notify_listf; 6494c06356bSdh 6504c06356bSdh /* 6514c06356bSdh * Thread Level stuff. 6524c06356bSdh * 6534c06356bSdh * A number of tasks are done off worker thread taskq. 6544c06356bSdh */ 6554c06356bSdh ddi_taskq_t *tq; /* For the worker thread */ 6564c06356bSdh volatile ulong_t work_flags; 6574c06356bSdh 6584c06356bSdh /* 6594c06356bSdh * Solaris target representation. 6604c06356bSdh * targets = array of pointers to xscsi structures 6614c06356bSdh * allocated by ssoftstate. 6624c06356bSdh */ 6634c06356bSdh pmcs_xscsi_t **targets; 6644c06356bSdh 6654c06356bSdh STAILQ_HEAD(dqh, pmcs_cmd) dq; /* dead commands */ 6664c06356bSdh STAILQ_HEAD(cqh, pmcs_cmd) cq; /* completed commands */ 6674c06356bSdh kmutex_t cq_lock; 6684c06356bSdh kmem_cache_t *iocomp_cb_cache; 6694c06356bSdh pmcs_iocomp_cb_t *iocomp_cb_head; 6704c06356bSdh pmcs_iocomp_cb_t *iocomp_cb_tail; 6714c06356bSdh 6724c06356bSdh uint16_t debug_mask; 6734c06356bSdh uint16_t phyid_block_mask; 6744c06356bSdh uint16_t phys_started; 6754c06356bSdh uint32_t hipri_queue; 6764c06356bSdh uint32_t mpibar; 6774c06356bSdh uint32_t intr_pri; 6784c06356bSdh 6794c06356bSdh pmcs_io_intr_coal_t io_intr_coal; 6804c06356bSdh pmcs_cq_info_t cq_info; 6814c06356bSdh kmutex_t ict_lock; 6824c06356bSdh kcondvar_t ict_cv; 6834c06356bSdh kthread_t *ict_thread; 6844c06356bSdh 6854c06356bSdh #ifdef DEBUG 6864c06356bSdh kmutex_t dbglock; 6874c06356bSdh uint32_t ltags[256]; 6884c06356bSdh uint32_t ftags[256]; 6894c06356bSdh hrtime_t ltime[256]; 6904c06356bSdh hrtime_t ftime[256]; 6914c06356bSdh uint16_t ftag_lines[256]; 6924c06356bSdh uint8_t lti; /* last tag index */ 6934c06356bSdh uint8_t fti; /* first tag index */ 6944c06356bSdh #endif 6954c06356bSdh }; 6964c06356bSdh 6974c06356bSdh extern void *pmcs_softc_state; 6984c06356bSdh extern void *pmcs_iport_softstate; 6994c06356bSdh 7004c06356bSdh /* 7014c06356bSdh * Some miscellaneous, oft used strings 7024c06356bSdh */ 7034c06356bSdh extern const char pmcs_nowrk[]; 7044c06356bSdh extern const char pmcs_nomsg[]; 7054c06356bSdh extern const char pmcs_timeo[]; 7064c06356bSdh 7074c06356bSdh #ifdef __cplusplus 7084c06356bSdh } 7094c06356bSdh #endif 7104c06356bSdh #endif /* _PMCS_H */ 711