1265555Sambrisko/* 2284267Skadesai * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy 3275976Ssmh * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 4284267Skadesai * Support: freebsdraid@avagotech.com 5265555Sambrisko * 6265555Sambrisko * Redistribution and use in source and binary forms, with or without 7275976Ssmh * modification, are permitted provided that the following conditions are 8275976Ssmh * met: 9265555Sambrisko * 10275976Ssmh * 1. Redistributions of source code must retain the above copyright notice, 11275976Ssmh * this list of conditions and the following disclaimer. 2. Redistributions 12275976Ssmh * in binary form must reproduce the above copyright notice, this list of 13275976Ssmh * conditions and the following disclaimer in the documentation and/or other 14275976Ssmh * materials provided with the distribution. 3. Neither the name of the 15275976Ssmh * <ORGANIZATION> nor the names of its contributors may be used to endorse or 16275976Ssmh * promote products derived from this software without specific prior written 17275976Ssmh * permission. 18265555Sambrisko * 19275976Ssmh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20275976Ssmh * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21275976Ssmh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22275976Ssmh * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23275976Ssmh * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24275976Ssmh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25275976Ssmh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26275976Ssmh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27275976Ssmh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28275976Ssmh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29265555Sambrisko * POSSIBILITY OF SUCH DAMAGE. 30265555Sambrisko * 31275976Ssmh * The views and conclusions contained in the software and documentation are 32275976Ssmh * those of the authors and should not be interpreted as representing 33265555Sambrisko * official policies,either expressed or implied, of the FreeBSD Project. 34265555Sambrisko * 35284267Skadesai * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES 1621 36275976Ssmh * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 37265555Sambrisko * 38265555Sambrisko */ 39265555Sambrisko 40265555Sambrisko#include <sys/cdefs.h> 41265555Sambrisko__FBSDID("$FreeBSD: releng/10.3/sys/dev/mrsas/mrsas.c 284267 2015-06-11 14:11:41Z kadesai $"); 42265555Sambrisko 43265555Sambrisko#include <dev/mrsas/mrsas.h> 44265555Sambrisko#include <dev/mrsas/mrsas_ioctl.h> 45265555Sambrisko 46265555Sambrisko#include <cam/cam.h> 47265555Sambrisko#include <cam/cam_ccb.h> 48265555Sambrisko 49265555Sambrisko#include <sys/sysctl.h> 50265555Sambrisko#include <sys/types.h> 51265555Sambrisko#include <sys/kthread.h> 52265555Sambrisko#include <sys/taskqueue.h> 53275976Ssmh#include <sys/smp.h> 54265555Sambrisko 55265555Sambrisko 56275976Ssmh/* 57275976Ssmh * Function prototypes 58265555Sambrisko */ 59275976Ssmhstatic d_open_t mrsas_open; 60275976Ssmhstatic d_close_t mrsas_close; 61275976Ssmhstatic d_read_t mrsas_read; 62275976Ssmhstatic d_write_t mrsas_write; 63275976Ssmhstatic d_ioctl_t mrsas_ioctl; 64275976Ssmhstatic d_poll_t mrsas_poll; 65265555Sambrisko 66275976Ssmhstatic struct mrsas_mgmt_info mrsas_mgmt_info; 67265555Sambriskostatic struct mrsas_ident *mrsas_find_ident(device_t); 68275976Ssmhstatic int mrsas_setup_msix(struct mrsas_softc *sc); 69275976Ssmhstatic int mrsas_allocate_msix(struct mrsas_softc *sc); 70265555Sambriskostatic void mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode); 71265555Sambriskostatic void mrsas_flush_cache(struct mrsas_softc *sc); 72265555Sambriskostatic void mrsas_reset_reply_desc(struct mrsas_softc *sc); 73265555Sambriskostatic void mrsas_ocr_thread(void *arg); 74265555Sambriskostatic int mrsas_get_map_info(struct mrsas_softc *sc); 75265555Sambriskostatic int mrsas_get_ld_map_info(struct mrsas_softc *sc); 76265555Sambriskostatic int mrsas_sync_map_info(struct mrsas_softc *sc); 77265555Sambriskostatic int mrsas_get_pd_list(struct mrsas_softc *sc); 78265555Sambriskostatic int mrsas_get_ld_list(struct mrsas_softc *sc); 79265555Sambriskostatic int mrsas_setup_irq(struct mrsas_softc *sc); 80265555Sambriskostatic int mrsas_alloc_mem(struct mrsas_softc *sc); 81265555Sambriskostatic int mrsas_init_fw(struct mrsas_softc *sc); 82265555Sambriskostatic int mrsas_setup_raidmap(struct mrsas_softc *sc); 83275976Ssmhstatic int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); 84265555Sambriskostatic int mrsas_clear_intr(struct mrsas_softc *sc); 85284267Skadesaistatic int mrsas_get_ctrl_info(struct mrsas_softc *sc); 86284267Skadesaistatic void mrsas_update_ext_vd_details(struct mrsas_softc *sc); 87284267Skadesaistatic int 88275976Ssmhmrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc, 89275976Ssmh struct mrsas_mfi_cmd *cmd_to_abort); 90284267Skadesaistatic struct mrsas_softc * 91284267Skadesaimrsas_get_softc_instance(struct cdev *dev, 92284267Skadesai u_long cmd, caddr_t arg); 93265555Sambriskou_int32_t mrsas_read_reg(struct mrsas_softc *sc, int offset); 94284267Skadesaiu_int8_t 95275976Ssmhmrsas_build_mptmfi_passthru(struct mrsas_softc *sc, 96275976Ssmh struct mrsas_mfi_cmd *mfi_cmd); 97284267Skadesaivoid mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc); 98275976Ssmhint mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr); 99275976Ssmhint mrsas_init_adapter(struct mrsas_softc *sc); 100275976Ssmhint mrsas_alloc_mpt_cmds(struct mrsas_softc *sc); 101275976Ssmhint mrsas_alloc_ioc_cmd(struct mrsas_softc *sc); 102275976Ssmhint mrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc); 103275976Ssmhint mrsas_ioc_init(struct mrsas_softc *sc); 104275976Ssmhint mrsas_bus_scan(struct mrsas_softc *sc); 105275976Ssmhint mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 106275976Ssmhint mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 107275976Ssmhint mrsas_reset_ctrl(struct mrsas_softc *sc); 108275976Ssmhint mrsas_wait_for_outstanding(struct mrsas_softc *sc); 109284267Skadesaiint 110275976Ssmhmrsas_issue_blocked_cmd(struct mrsas_softc *sc, 111275976Ssmh struct mrsas_mfi_cmd *cmd); 112284267Skadesaiint 113275976Ssmhmrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd, 114275976Ssmh int size); 115275976Ssmhvoid mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); 116275976Ssmhvoid mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 117275976Ssmhvoid mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 118275976Ssmhvoid mrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 119275976Ssmhvoid mrsas_disable_intr(struct mrsas_softc *sc); 120275976Ssmhvoid mrsas_enable_intr(struct mrsas_softc *sc); 121275976Ssmhvoid mrsas_free_ioc_cmd(struct mrsas_softc *sc); 122275976Ssmhvoid mrsas_free_mem(struct mrsas_softc *sc); 123275976Ssmhvoid mrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp); 124275976Ssmhvoid mrsas_isr(void *arg); 125275976Ssmhvoid mrsas_teardown_intr(struct mrsas_softc *sc); 126275976Ssmhvoid mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error); 127275976Ssmhvoid mrsas_kill_hba(struct mrsas_softc *sc); 128275976Ssmhvoid mrsas_aen_handler(struct mrsas_softc *sc); 129284267Skadesaivoid 130275976Ssmhmrsas_write_reg(struct mrsas_softc *sc, int offset, 131275976Ssmh u_int32_t value); 132284267Skadesaivoid 133275976Ssmhmrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, 134275976Ssmh u_int32_t req_desc_hi); 135275976Ssmhvoid mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc); 136284267Skadesaivoid 137275976Ssmhmrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, 138275976Ssmh struct mrsas_mfi_cmd *cmd, u_int8_t status); 139284267Skadesaivoid 140275976Ssmhmrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, 141275976Ssmh u_int8_t extStatus); 142275976Ssmhstruct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc); 143265555Sambrisko 144275976SsmhMRSAS_REQUEST_DESCRIPTOR_UNION *mrsas_build_mpt_cmd 145275976Ssmh (struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 146275976Ssmh 147265555Sambriskoextern int mrsas_cam_attach(struct mrsas_softc *sc); 148265555Sambriskoextern void mrsas_cam_detach(struct mrsas_softc *sc); 149265555Sambriskoextern void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); 150265555Sambriskoextern void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 151265555Sambriskoextern int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc); 152275976Ssmhextern void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd); 153265555Sambriskoextern struct mrsas_mpt_cmd *mrsas_get_mpt_cmd(struct mrsas_softc *sc); 154275976Ssmhextern int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd); 155265555Sambriskoextern uint8_t MR_ValidateMapInfo(struct mrsas_softc *sc); 156275976Ssmhextern u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 157275976Ssmhextern MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); 158265555Sambriskoextern void mrsas_xpt_freeze(struct mrsas_softc *sc); 159265555Sambriskoextern void mrsas_xpt_release(struct mrsas_softc *sc); 160275976Ssmhextern MRSAS_REQUEST_DESCRIPTOR_UNION * 161275976Ssmhmrsas_get_request_desc(struct mrsas_softc *sc, 162275976Ssmh u_int16_t index); 163265555Sambriskoextern int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim); 164265555Sambriskostatic int mrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc); 165265555Sambriskostatic void mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc); 166275976Ssmh 167265555SambriskoSYSCTL_NODE(_hw, OID_AUTO, mrsas, CTLFLAG_RD, 0, "MRSAS Driver Parameters"); 168265555Sambrisko 169275976Ssmh/* 170265555Sambrisko * PCI device struct and table 171265555Sambrisko * 172265555Sambrisko */ 173265555Sambriskotypedef struct mrsas_ident { 174275976Ssmh uint16_t vendor; 175275976Ssmh uint16_t device; 176275976Ssmh uint16_t subvendor; 177275976Ssmh uint16_t subdevice; 178275976Ssmh const char *desc; 179275976Ssmh} MRSAS_CTLR_ID; 180265555Sambrisko 181265555SambriskoMRSAS_CTLR_ID device_table[] = { 182284267Skadesai {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "AVAGO Thunderbolt SAS Controller"}, 183284267Skadesai {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "AVAGO Invader SAS Controller"}, 184284267Skadesai {0x1000, MRSAS_FURY, 0xffff, 0xffff, "AVAGO Fury SAS Controller"}, 185275976Ssmh {0, 0, 0, 0, NULL} 186265555Sambrisko}; 187265555Sambrisko 188275976Ssmh/* 189275976Ssmh * Character device entry points 190265555Sambrisko * 191265555Sambrisko */ 192265555Sambriskostatic struct cdevsw mrsas_cdevsw = { 193275976Ssmh .d_version = D_VERSION, 194275976Ssmh .d_open = mrsas_open, 195275976Ssmh .d_close = mrsas_close, 196275976Ssmh .d_read = mrsas_read, 197275976Ssmh .d_write = mrsas_write, 198275976Ssmh .d_ioctl = mrsas_ioctl, 199275976Ssmh .d_poll = mrsas_poll, 200275976Ssmh .d_name = "mrsas", 201265555Sambrisko}; 202265555Sambrisko 203265555SambriskoMALLOC_DEFINE(M_MRSAS, "mrsasbuf", "Buffers for the MRSAS driver"); 204265555Sambrisko 205275976Ssmh/* 206275976Ssmh * In the cdevsw routines, we find our softc by using the si_drv1 member of 207275976Ssmh * struct cdev. We set this variable to point to our softc in our attach 208275976Ssmh * routine when we create the /dev entry. 209265555Sambrisko */ 210265555Sambriskoint 211265555Sambriskomrsas_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td) 212265555Sambrisko{ 213275976Ssmh struct mrsas_softc *sc; 214265555Sambrisko 215275976Ssmh sc = dev->si_drv1; 216275976Ssmh return (0); 217265555Sambrisko} 218265555Sambrisko 219265555Sambriskoint 220265555Sambriskomrsas_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td) 221265555Sambrisko{ 222275976Ssmh struct mrsas_softc *sc; 223265555Sambrisko 224275976Ssmh sc = dev->si_drv1; 225275976Ssmh return (0); 226265555Sambrisko} 227265555Sambrisko 228265555Sambriskoint 229265555Sambriskomrsas_read(struct cdev *dev, struct uio *uio, int ioflag) 230265555Sambrisko{ 231275976Ssmh struct mrsas_softc *sc; 232265555Sambrisko 233275976Ssmh sc = dev->si_drv1; 234275976Ssmh return (0); 235265555Sambrisko} 236265555Sambriskoint 237265555Sambriskomrsas_write(struct cdev *dev, struct uio *uio, int ioflag) 238265555Sambrisko{ 239275976Ssmh struct mrsas_softc *sc; 240265555Sambrisko 241275976Ssmh sc = dev->si_drv1; 242275976Ssmh return (0); 243265555Sambrisko} 244265555Sambrisko 245275976Ssmh/* 246275976Ssmh * Register Read/Write Functions 247265555Sambrisko * 248265555Sambrisko */ 249265555Sambriskovoid 250265555Sambriskomrsas_write_reg(struct mrsas_softc *sc, int offset, 251275976Ssmh u_int32_t value) 252265555Sambrisko{ 253275976Ssmh bus_space_tag_t bus_tag = sc->bus_tag; 254275976Ssmh bus_space_handle_t bus_handle = sc->bus_handle; 255265555Sambrisko 256275976Ssmh bus_space_write_4(bus_tag, bus_handle, offset, value); 257265555Sambrisko} 258265555Sambrisko 259265555Sambriskou_int32_t 260265555Sambriskomrsas_read_reg(struct mrsas_softc *sc, int offset) 261265555Sambrisko{ 262275976Ssmh bus_space_tag_t bus_tag = sc->bus_tag; 263275976Ssmh bus_space_handle_t bus_handle = sc->bus_handle; 264265555Sambrisko 265275976Ssmh return ((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset)); 266265555Sambrisko} 267265555Sambrisko 268265555Sambrisko 269275976Ssmh/* 270275976Ssmh * Interrupt Disable/Enable/Clear Functions 271265555Sambrisko * 272265555Sambrisko */ 273275976Ssmhvoid 274275976Ssmhmrsas_disable_intr(struct mrsas_softc *sc) 275265555Sambrisko{ 276275976Ssmh u_int32_t mask = 0xFFFFFFFF; 277275976Ssmh u_int32_t status; 278265555Sambrisko 279284267Skadesai sc->mask_interrupts = 1; 280275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), mask); 281275976Ssmh /* Dummy read to force pci flush */ 282275976Ssmh status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask)); 283265555Sambrisko} 284265555Sambrisko 285275976Ssmhvoid 286275976Ssmhmrsas_enable_intr(struct mrsas_softc *sc) 287265555Sambrisko{ 288275976Ssmh u_int32_t mask = MFI_FUSION_ENABLE_INTERRUPT_MASK; 289275976Ssmh u_int32_t status; 290265555Sambrisko 291284267Skadesai sc->mask_interrupts = 0; 292275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), ~0); 293275976Ssmh status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status)); 294265555Sambrisko 295275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), ~mask); 296275976Ssmh status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask)); 297265555Sambrisko} 298265555Sambrisko 299275976Ssmhstatic int 300275976Ssmhmrsas_clear_intr(struct mrsas_softc *sc) 301265555Sambrisko{ 302275976Ssmh u_int32_t status, fw_status, fw_state; 303265555Sambrisko 304275976Ssmh /* Read received interrupt */ 305275976Ssmh status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status)); 306265555Sambrisko 307275976Ssmh /* 308275976Ssmh * If FW state change interrupt is received, write to it again to 309275976Ssmh * clear 310275976Ssmh */ 311275976Ssmh if (status & MRSAS_FW_STATE_CHNG_INTERRUPT) { 312275976Ssmh fw_status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 313275976Ssmh outbound_scratch_pad)); 314275976Ssmh fw_state = fw_status & MFI_STATE_MASK; 315275976Ssmh if (fw_state == MFI_STATE_FAULT) { 316275976Ssmh device_printf(sc->mrsas_dev, "FW is in FAULT state!\n"); 317275976Ssmh if (sc->ocr_thread_active) 318275976Ssmh wakeup(&sc->ocr_chan); 319275976Ssmh } 320275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), status); 321275976Ssmh mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status)); 322275976Ssmh return (1); 323275976Ssmh } 324275976Ssmh /* Not our interrupt, so just return */ 325275976Ssmh if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) 326275976Ssmh return (0); 327265555Sambrisko 328275976Ssmh /* We got a reply interrupt */ 329275976Ssmh return (1); 330265555Sambrisko} 331265555Sambrisko 332275976Ssmh/* 333275976Ssmh * PCI Support Functions 334265555Sambrisko * 335265555Sambrisko */ 336275976Ssmhstatic struct mrsas_ident * 337275976Ssmhmrsas_find_ident(device_t dev) 338265555Sambrisko{ 339275976Ssmh struct mrsas_ident *pci_device; 340265555Sambrisko 341275976Ssmh for (pci_device = device_table; pci_device->vendor != 0; pci_device++) { 342275976Ssmh if ((pci_device->vendor == pci_get_vendor(dev)) && 343275976Ssmh (pci_device->device == pci_get_device(dev)) && 344275976Ssmh ((pci_device->subvendor == pci_get_subvendor(dev)) || 345275976Ssmh (pci_device->subvendor == 0xffff)) && 346275976Ssmh ((pci_device->subdevice == pci_get_subdevice(dev)) || 347275976Ssmh (pci_device->subdevice == 0xffff))) 348275976Ssmh return (pci_device); 349275976Ssmh } 350275976Ssmh return (NULL); 351265555Sambrisko} 352265555Sambrisko 353275976Ssmhstatic int 354275976Ssmhmrsas_probe(device_t dev) 355265555Sambrisko{ 356275976Ssmh static u_int8_t first_ctrl = 1; 357275976Ssmh struct mrsas_ident *id; 358265555Sambrisko 359275976Ssmh if ((id = mrsas_find_ident(dev)) != NULL) { 360275976Ssmh if (first_ctrl) { 361284267Skadesai printf("AVAGO MegaRAID SAS FreeBSD mrsas driver version: %s\n", 362275976Ssmh MRSAS_VERSION); 363275976Ssmh first_ctrl = 0; 364275976Ssmh } 365275976Ssmh device_set_desc(dev, id->desc); 366275976Ssmh /* between BUS_PROBE_DEFAULT and BUS_PROBE_LOW_PRIORITY */ 367275976Ssmh return (-30); 368275976Ssmh } 369275976Ssmh return (ENXIO); 370265555Sambrisko} 371265555Sambrisko 372275976Ssmh/* 373275976Ssmh * mrsas_setup_sysctl: setup sysctl values for mrsas 374275976Ssmh * input: Adapter instance soft state 375265555Sambrisko * 376265555Sambrisko * Setup sysctl entries for mrsas driver. 377265555Sambrisko */ 378265555Sambriskostatic void 379265555Sambriskomrsas_setup_sysctl(struct mrsas_softc *sc) 380265555Sambrisko{ 381275976Ssmh struct sysctl_ctx_list *sysctl_ctx = NULL; 382275976Ssmh struct sysctl_oid *sysctl_tree = NULL; 383275976Ssmh char tmpstr[80], tmpstr2[80]; 384265555Sambrisko 385275976Ssmh /* 386275976Ssmh * Setup the sysctl variable so the user can change the debug level 387275976Ssmh * on the fly. 388275976Ssmh */ 389275976Ssmh snprintf(tmpstr, sizeof(tmpstr), "MRSAS controller %d", 390275976Ssmh device_get_unit(sc->mrsas_dev)); 391275976Ssmh snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mrsas_dev)); 392265555Sambrisko 393275976Ssmh sysctl_ctx = device_get_sysctl_ctx(sc->mrsas_dev); 394275976Ssmh if (sysctl_ctx != NULL) 395275976Ssmh sysctl_tree = device_get_sysctl_tree(sc->mrsas_dev); 396265555Sambrisko 397275976Ssmh if (sysctl_tree == NULL) { 398275976Ssmh sysctl_ctx_init(&sc->sysctl_ctx); 399275976Ssmh sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 400275976Ssmh SYSCTL_STATIC_CHILDREN(_hw_mrsas), OID_AUTO, tmpstr2, 401275976Ssmh CTLFLAG_RD, 0, tmpstr); 402275976Ssmh if (sc->sysctl_tree == NULL) 403275976Ssmh return; 404275976Ssmh sysctl_ctx = &sc->sysctl_ctx; 405275976Ssmh sysctl_tree = sc->sysctl_tree; 406275976Ssmh } 407275976Ssmh SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 408275976Ssmh OID_AUTO, "disable_ocr", CTLFLAG_RW, &sc->disableOnlineCtrlReset, 0, 409275976Ssmh "Disable the use of OCR"); 410265555Sambrisko 411275976Ssmh SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 412275976Ssmh OID_AUTO, "driver_version", CTLFLAG_RD, MRSAS_VERSION, 413275976Ssmh strlen(MRSAS_VERSION), "driver version"); 414265555Sambrisko 415275976Ssmh SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 416275976Ssmh OID_AUTO, "reset_count", CTLFLAG_RD, 417275976Ssmh &sc->reset_count, 0, "number of ocr from start of the day"); 418265555Sambrisko 419275976Ssmh SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 420275976Ssmh OID_AUTO, "fw_outstanding", CTLFLAG_RD, 421275976Ssmh &sc->fw_outstanding.val_rdonly, 0, "FW outstanding commands"); 422265555Sambrisko 423265555Sambrisko SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 424275976Ssmh OID_AUTO, "io_cmds_highwater", CTLFLAG_RD, 425275976Ssmh &sc->io_cmds_highwater, 0, "Max FW outstanding commands"); 426265555Sambrisko 427275976Ssmh SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 428275976Ssmh OID_AUTO, "mrsas_debug", CTLFLAG_RW, &sc->mrsas_debug, 0, 429275976Ssmh "Driver debug level"); 430265555Sambrisko 431275976Ssmh SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 432275976Ssmh OID_AUTO, "mrsas_io_timeout", CTLFLAG_RW, &sc->mrsas_io_timeout, 433275976Ssmh 0, "Driver IO timeout value in mili-second."); 434265555Sambrisko 435275976Ssmh SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 436275976Ssmh OID_AUTO, "mrsas_fw_fault_check_delay", CTLFLAG_RW, 437275976Ssmh &sc->mrsas_fw_fault_check_delay, 438275976Ssmh 0, "FW fault check thread delay in seconds. <default is 1 sec>"); 439265555Sambrisko 440275976Ssmh SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 441275976Ssmh OID_AUTO, "reset_in_progress", CTLFLAG_RD, 442275976Ssmh &sc->reset_in_progress, 0, "ocr in progress status"); 443265555Sambrisko 444265555Sambrisko} 445265555Sambrisko 446275976Ssmh/* 447275976Ssmh * mrsas_get_tunables: get tunable parameters. 448275976Ssmh * input: Adapter instance soft state 449265555Sambrisko * 450265555Sambrisko * Get tunable parameters. This will help to debug driver at boot time. 451265555Sambrisko */ 452265555Sambriskostatic void 453265555Sambriskomrsas_get_tunables(struct mrsas_softc *sc) 454265555Sambrisko{ 455275976Ssmh char tmpstr[80]; 456265555Sambrisko 457275976Ssmh /* XXX default to some debugging for now */ 458275976Ssmh sc->mrsas_debug = MRSAS_FAULT; 459275976Ssmh sc->mrsas_io_timeout = MRSAS_IO_TIMEOUT; 460275976Ssmh sc->mrsas_fw_fault_check_delay = 1; 461275976Ssmh sc->reset_count = 0; 462275976Ssmh sc->reset_in_progress = 0; 463265555Sambrisko 464275976Ssmh /* 465275976Ssmh * Grab the global variables. 466275976Ssmh */ 467275976Ssmh TUNABLE_INT_FETCH("hw.mrsas.debug_level", &sc->mrsas_debug); 468265555Sambrisko 469284267Skadesai /* 470284267Skadesai * Grab the global variables. 471284267Skadesai */ 472284267Skadesai TUNABLE_INT_FETCH("hw.mrsas.lb_pending_cmds", &sc->lb_pending_cmds); 473284267Skadesai 474275976Ssmh /* Grab the unit-instance variables */ 475275976Ssmh snprintf(tmpstr, sizeof(tmpstr), "dev.mrsas.%d.debug_level", 476275976Ssmh device_get_unit(sc->mrsas_dev)); 477275976Ssmh TUNABLE_INT_FETCH(tmpstr, &sc->mrsas_debug); 478265555Sambrisko} 479265555Sambrisko 480275976Ssmh/* 481275976Ssmh * mrsas_alloc_evt_log_info cmd: Allocates memory to get event log information. 482275976Ssmh * Used to get sequence number at driver load time. 483275976Ssmh * input: Adapter soft state 484265555Sambrisko * 485265555Sambrisko * Allocates DMAable memory for the event log info internal command. 486265555Sambrisko */ 487275976Ssmhint 488275976Ssmhmrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc) 489265555Sambrisko{ 490275976Ssmh int el_info_size; 491265555Sambrisko 492275976Ssmh /* Allocate get event log info command */ 493275976Ssmh el_info_size = sizeof(struct mrsas_evt_log_info); 494275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 495275976Ssmh 1, 0, 496275976Ssmh BUS_SPACE_MAXADDR_32BIT, 497275976Ssmh BUS_SPACE_MAXADDR, 498275976Ssmh NULL, NULL, 499275976Ssmh el_info_size, 500275976Ssmh 1, 501275976Ssmh el_info_size, 502275976Ssmh BUS_DMA_ALLOCNOW, 503275976Ssmh NULL, NULL, 504275976Ssmh &sc->el_info_tag)) { 505275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate event log info tag\n"); 506275976Ssmh return (ENOMEM); 507275976Ssmh } 508275976Ssmh if (bus_dmamem_alloc(sc->el_info_tag, (void **)&sc->el_info_mem, 509275976Ssmh BUS_DMA_NOWAIT, &sc->el_info_dmamap)) { 510275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate event log info cmd mem\n"); 511275976Ssmh return (ENOMEM); 512275976Ssmh } 513275976Ssmh if (bus_dmamap_load(sc->el_info_tag, sc->el_info_dmamap, 514275976Ssmh sc->el_info_mem, el_info_size, mrsas_addr_cb, 515275976Ssmh &sc->el_info_phys_addr, BUS_DMA_NOWAIT)) { 516275976Ssmh device_printf(sc->mrsas_dev, "Cannot load event log info cmd mem\n"); 517275976Ssmh return (ENOMEM); 518275976Ssmh } 519275976Ssmh memset(sc->el_info_mem, 0, el_info_size); 520275976Ssmh return (0); 521265555Sambrisko} 522265555Sambrisko 523275976Ssmh/* 524275976Ssmh * mrsas_free_evt_info_cmd: Free memory for Event log info command 525275976Ssmh * input: Adapter soft state 526265555Sambrisko * 527265555Sambrisko * Deallocates memory for the event log info internal command. 528265555Sambrisko */ 529275976Ssmhvoid 530275976Ssmhmrsas_free_evt_log_info_cmd(struct mrsas_softc *sc) 531265555Sambrisko{ 532275976Ssmh if (sc->el_info_phys_addr) 533275976Ssmh bus_dmamap_unload(sc->el_info_tag, sc->el_info_dmamap); 534275976Ssmh if (sc->el_info_mem != NULL) 535275976Ssmh bus_dmamem_free(sc->el_info_tag, sc->el_info_mem, sc->el_info_dmamap); 536275976Ssmh if (sc->el_info_tag != NULL) 537275976Ssmh bus_dma_tag_destroy(sc->el_info_tag); 538265555Sambrisko} 539265555Sambrisko 540275976Ssmh/* 541265555Sambrisko * mrsas_get_seq_num: Get latest event sequence number 542265555Sambrisko * @sc: Adapter soft state 543265555Sambrisko * @eli: Firmware event log sequence number information. 544275976Ssmh * 545275976Ssmh * Firmware maintains a log of all events in a non-volatile area. 546275976Ssmh * Driver get the sequence number using DCMD 547275976Ssmh * "MR_DCMD_CTRL_EVENT_GET_INFO" at driver load time. 548265555Sambrisko */ 549265555Sambrisko 550265555Sambriskostatic int 551265555Sambriskomrsas_get_seq_num(struct mrsas_softc *sc, 552275976Ssmh struct mrsas_evt_log_info *eli) 553265555Sambrisko{ 554265555Sambrisko struct mrsas_mfi_cmd *cmd; 555265555Sambrisko struct mrsas_dcmd_frame *dcmd; 556265555Sambrisko 557275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 558265555Sambrisko 559265555Sambrisko if (!cmd) { 560265555Sambrisko device_printf(sc->mrsas_dev, "Failed to get a free cmd\n"); 561265555Sambrisko return -ENOMEM; 562265555Sambrisko } 563265555Sambrisko dcmd = &cmd->frame->dcmd; 564265555Sambrisko 565265555Sambrisko if (mrsas_alloc_evt_log_info_cmd(sc) != SUCCESS) { 566265555Sambrisko device_printf(sc->mrsas_dev, "Cannot allocate evt log info cmd\n"); 567265555Sambrisko mrsas_release_mfi_cmd(cmd); 568265555Sambrisko return -ENOMEM; 569265555Sambrisko } 570265555Sambrisko memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 571265555Sambrisko 572265555Sambrisko dcmd->cmd = MFI_CMD_DCMD; 573265555Sambrisko dcmd->cmd_status = 0x0; 574265555Sambrisko dcmd->sge_count = 1; 575265555Sambrisko dcmd->flags = MFI_FRAME_DIR_READ; 576265555Sambrisko dcmd->timeout = 0; 577265555Sambrisko dcmd->pad_0 = 0; 578265555Sambrisko dcmd->data_xfer_len = sizeof(struct mrsas_evt_log_info); 579265555Sambrisko dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; 580265555Sambrisko dcmd->sgl.sge32[0].phys_addr = sc->el_info_phys_addr; 581265555Sambrisko dcmd->sgl.sge32[0].length = sizeof(struct mrsas_evt_log_info); 582265555Sambrisko 583265555Sambrisko mrsas_issue_blocked_cmd(sc, cmd); 584265555Sambrisko 585265555Sambrisko /* 586275976Ssmh * Copy the data back into callers buffer 587275976Ssmh */ 588265555Sambrisko memcpy(eli, sc->el_info_mem, sizeof(struct mrsas_evt_log_info)); 589265555Sambrisko mrsas_free_evt_log_info_cmd(sc); 590265555Sambrisko mrsas_release_mfi_cmd(cmd); 591265555Sambrisko 592265555Sambrisko return 0; 593265555Sambrisko} 594265555Sambrisko 595265555Sambrisko 596275976Ssmh/* 597265555Sambrisko * mrsas_register_aen: Register for asynchronous event notification 598275976Ssmh * @sc: Adapter soft state 599275976Ssmh * @seq_num: Starting sequence number 600275976Ssmh * @class_locale: Class of the event 601275976Ssmh * 602275976Ssmh * This function subscribes for events beyond the @seq_num 603275976Ssmh * and type @class_locale. 604275976Ssmh * 605275976Ssmh */ 606265555Sambriskostatic int 607265555Sambriskomrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num, 608275976Ssmh u_int32_t class_locale_word) 609265555Sambrisko{ 610265555Sambrisko int ret_val; 611265555Sambrisko struct mrsas_mfi_cmd *cmd; 612265555Sambrisko struct mrsas_dcmd_frame *dcmd; 613265555Sambrisko union mrsas_evt_class_locale curr_aen; 614265555Sambrisko union mrsas_evt_class_locale prev_aen; 615265555Sambrisko 616275976Ssmh /* 617275976Ssmh * If there an AEN pending already (aen_cmd), check if the 618275976Ssmh * class_locale of that pending AEN is inclusive of the new AEN 619275976Ssmh * request we currently have. If it is, then we don't have to do 620275976Ssmh * anything. In other words, whichever events the current AEN request 621275976Ssmh * is subscribing to, have already been subscribed to. If the old_cmd 622275976Ssmh * is _not_ inclusive, then we have to abort that command, form a 623275976Ssmh * class_locale that is superset of both old and current and re-issue 624275976Ssmh * to the FW 625275976Ssmh */ 626265555Sambrisko 627265555Sambrisko curr_aen.word = class_locale_word; 628265555Sambrisko 629265555Sambrisko if (sc->aen_cmd) { 630265555Sambrisko 631265555Sambrisko prev_aen.word = sc->aen_cmd->frame->dcmd.mbox.w[1]; 632265555Sambrisko 633275976Ssmh /* 634275976Ssmh * A class whose enum value is smaller is inclusive of all 635275976Ssmh * higher values. If a PROGRESS (= -1) was previously 636275976Ssmh * registered, then a new registration requests for higher 637275976Ssmh * classes need not be sent to FW. They are automatically 638275976Ssmh * included. Locale numbers don't have such hierarchy. They 639275976Ssmh * are bitmap values 640275976Ssmh */ 641265555Sambrisko if ((prev_aen.members.class <= curr_aen.members.class) && 642275976Ssmh !((prev_aen.members.locale & curr_aen.members.locale) ^ 643275976Ssmh curr_aen.members.locale)) { 644265555Sambrisko /* 645275976Ssmh * Previously issued event registration includes 646275976Ssmh * current request. Nothing to do. 647275976Ssmh */ 648265555Sambrisko return 0; 649265555Sambrisko } else { 650265555Sambrisko curr_aen.members.locale |= prev_aen.members.locale; 651265555Sambrisko 652265555Sambrisko if (prev_aen.members.class < curr_aen.members.class) 653265555Sambrisko curr_aen.members.class = prev_aen.members.class; 654265555Sambrisko 655265555Sambrisko sc->aen_cmd->abort_aen = 1; 656265555Sambrisko ret_val = mrsas_issue_blocked_abort_cmd(sc, 657275976Ssmh sc->aen_cmd); 658265555Sambrisko 659265555Sambrisko if (ret_val) { 660265555Sambrisko printf("mrsas: Failed to abort " 661275976Ssmh "previous AEN command\n"); 662265555Sambrisko return ret_val; 663265555Sambrisko } 664265555Sambrisko } 665265555Sambrisko } 666275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 667265555Sambrisko 668265555Sambrisko if (!cmd) 669265555Sambrisko return -ENOMEM; 670265555Sambrisko 671265555Sambrisko dcmd = &cmd->frame->dcmd; 672265555Sambrisko 673265555Sambrisko memset(sc->evt_detail_mem, 0, sizeof(struct mrsas_evt_detail)); 674265555Sambrisko 675275976Ssmh /* 676275976Ssmh * Prepare DCMD for aen registration 677275976Ssmh */ 678265555Sambrisko memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 679265555Sambrisko 680265555Sambrisko dcmd->cmd = MFI_CMD_DCMD; 681265555Sambrisko dcmd->cmd_status = 0x0; 682265555Sambrisko dcmd->sge_count = 1; 683265555Sambrisko dcmd->flags = MFI_FRAME_DIR_READ; 684265555Sambrisko dcmd->timeout = 0; 685265555Sambrisko dcmd->pad_0 = 0; 686265555Sambrisko dcmd->data_xfer_len = sizeof(struct mrsas_evt_detail); 687265555Sambrisko dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; 688265555Sambrisko dcmd->mbox.w[0] = seq_num; 689275976Ssmh sc->last_seq_num = seq_num; 690265555Sambrisko dcmd->mbox.w[1] = curr_aen.word; 691275976Ssmh dcmd->sgl.sge32[0].phys_addr = (u_int32_t)sc->evt_detail_phys_addr; 692265555Sambrisko dcmd->sgl.sge32[0].length = sizeof(struct mrsas_evt_detail); 693265555Sambrisko 694265555Sambrisko if (sc->aen_cmd != NULL) { 695265555Sambrisko mrsas_release_mfi_cmd(cmd); 696265555Sambrisko return 0; 697265555Sambrisko } 698265555Sambrisko /* 699275976Ssmh * Store reference to the cmd used to register for AEN. When an 700275976Ssmh * application wants us to register for AEN, we have to abort this 701275976Ssmh * cmd and re-register with a new EVENT LOCALE supplied by that app 702275976Ssmh */ 703265555Sambrisko sc->aen_cmd = cmd; 704265555Sambrisko 705265555Sambrisko /* 706275976Ssmh * Issue the aen registration frame 707275976Ssmh */ 708275976Ssmh if (mrsas_issue_dcmd(sc, cmd)) { 709275976Ssmh device_printf(sc->mrsas_dev, "Cannot issue AEN DCMD command.\n"); 710275976Ssmh return (1); 711275976Ssmh } 712265555Sambrisko return 0; 713265555Sambrisko} 714275976Ssmh 715275976Ssmh/* 716275976Ssmh * mrsas_start_aen: Subscribes to AEN during driver load time 717275976Ssmh * @instance: Adapter soft state 718265555Sambrisko */ 719275976Ssmhstatic int 720275976Ssmhmrsas_start_aen(struct mrsas_softc *sc) 721265555Sambrisko{ 722265555Sambrisko struct mrsas_evt_log_info eli; 723265555Sambrisko union mrsas_evt_class_locale class_locale; 724265555Sambrisko 725265555Sambrisko 726275976Ssmh /* Get the latest sequence number from FW */ 727275976Ssmh 728265555Sambrisko memset(&eli, 0, sizeof(eli)); 729265555Sambrisko 730265555Sambrisko if (mrsas_get_seq_num(sc, &eli)) 731265555Sambrisko return -1; 732265555Sambrisko 733275976Ssmh /* Register AEN with FW for latest sequence number plus 1 */ 734265555Sambrisko class_locale.members.reserved = 0; 735265555Sambrisko class_locale.members.locale = MR_EVT_LOCALE_ALL; 736265555Sambrisko class_locale.members.class = MR_EVT_CLASS_DEBUG; 737265555Sambrisko 738265555Sambrisko return mrsas_register_aen(sc, eli.newest_seq_num + 1, 739275976Ssmh class_locale.word); 740275976Ssmh 741265555Sambrisko} 742265555Sambrisko 743275976Ssmh/* 744275976Ssmh * mrsas_setup_msix: Allocate MSI-x vectors 745275976Ssmh * @sc: adapter soft state 746265555Sambrisko */ 747275976Ssmhstatic int 748275976Ssmhmrsas_setup_msix(struct mrsas_softc *sc) 749265555Sambrisko{ 750275976Ssmh int i; 751265555Sambrisko 752275976Ssmh for (i = 0; i < sc->msix_vectors; i++) { 753275976Ssmh sc->irq_context[i].sc = sc; 754275976Ssmh sc->irq_context[i].MSIxIndex = i; 755275976Ssmh sc->irq_id[i] = i + 1; 756275976Ssmh sc->mrsas_irq[i] = bus_alloc_resource_any 757275976Ssmh (sc->mrsas_dev, SYS_RES_IRQ, &sc->irq_id[i] 758275976Ssmh ,RF_ACTIVE); 759275976Ssmh if (sc->mrsas_irq[i] == NULL) { 760275976Ssmh device_printf(sc->mrsas_dev, "Can't allocate MSI-x\n"); 761275976Ssmh goto irq_alloc_failed; 762275976Ssmh } 763275976Ssmh if (bus_setup_intr(sc->mrsas_dev, 764275976Ssmh sc->mrsas_irq[i], 765275976Ssmh INTR_MPSAFE | INTR_TYPE_CAM, 766275976Ssmh NULL, mrsas_isr, &sc->irq_context[i], 767275976Ssmh &sc->intr_handle[i])) { 768275976Ssmh device_printf(sc->mrsas_dev, 769275976Ssmh "Cannot set up MSI-x interrupt handler\n"); 770275976Ssmh goto irq_alloc_failed; 771275976Ssmh } 772275976Ssmh } 773275976Ssmh return SUCCESS; 774265555Sambrisko 775275976Ssmhirq_alloc_failed: 776275976Ssmh mrsas_teardown_intr(sc); 777275976Ssmh return (FAIL); 778275976Ssmh} 779265555Sambrisko 780275976Ssmh/* 781275976Ssmh * mrsas_allocate_msix: Setup MSI-x vectors 782275976Ssmh * @sc: adapter soft state 783275976Ssmh */ 784275976Ssmhstatic int 785275976Ssmhmrsas_allocate_msix(struct mrsas_softc *sc) 786275976Ssmh{ 787275976Ssmh if (pci_alloc_msix(sc->mrsas_dev, &sc->msix_vectors) == 0) { 788275976Ssmh device_printf(sc->mrsas_dev, "Using MSI-X with %d number" 789275976Ssmh " of vectors\n", sc->msix_vectors); 790275976Ssmh } else { 791275976Ssmh device_printf(sc->mrsas_dev, "MSI-x setup failed\n"); 792275976Ssmh goto irq_alloc_failed; 793275976Ssmh } 794275976Ssmh return SUCCESS; 795265555Sambrisko 796275976Ssmhirq_alloc_failed: 797275976Ssmh mrsas_teardown_intr(sc); 798275976Ssmh return (FAIL); 799275976Ssmh} 800265555Sambrisko 801275976Ssmh/* 802275976Ssmh * mrsas_attach: PCI entry point 803275976Ssmh * input: pointer to device struct 804275976Ssmh * 805275976Ssmh * Performs setup of PCI and registers, initializes mutexes and linked lists, 806275976Ssmh * registers interrupts and CAM, and initializes the adapter/controller to 807275976Ssmh * its proper state. 808275976Ssmh */ 809275976Ssmhstatic int 810275976Ssmhmrsas_attach(device_t dev) 811275976Ssmh{ 812275976Ssmh struct mrsas_softc *sc = device_get_softc(dev); 813275976Ssmh uint32_t cmd, bar, error; 814265555Sambrisko 815275976Ssmh /* Look up our softc and initialize its fields. */ 816275976Ssmh sc->mrsas_dev = dev; 817275976Ssmh sc->device_id = pci_get_device(dev); 818265555Sambrisko 819275976Ssmh mrsas_get_tunables(sc); 820265555Sambrisko 821275976Ssmh /* 822275976Ssmh * Set up PCI and registers 823275976Ssmh */ 824275976Ssmh cmd = pci_read_config(dev, PCIR_COMMAND, 2); 825275976Ssmh if ((cmd & PCIM_CMD_PORTEN) == 0) { 826275976Ssmh return (ENXIO); 827275976Ssmh } 828275976Ssmh /* Force the busmaster enable bit on. */ 829275976Ssmh cmd |= PCIM_CMD_BUSMASTEREN; 830275976Ssmh pci_write_config(dev, PCIR_COMMAND, cmd, 2); 831265555Sambrisko 832275976Ssmh bar = pci_read_config(dev, MRSAS_PCI_BAR1, 4); 833275976Ssmh 834275976Ssmh sc->reg_res_id = MRSAS_PCI_BAR1;/* BAR1 offset */ 835275976Ssmh if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 836275976Ssmh &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE)) 837275976Ssmh == NULL) { 838275976Ssmh device_printf(dev, "Cannot allocate PCI registers\n"); 839275976Ssmh goto attach_fail; 840275976Ssmh } 841275976Ssmh sc->bus_tag = rman_get_bustag(sc->reg_res); 842275976Ssmh sc->bus_handle = rman_get_bushandle(sc->reg_res); 843275976Ssmh 844275976Ssmh /* Intialize mutexes */ 845275976Ssmh mtx_init(&sc->sim_lock, "mrsas_sim_lock", NULL, MTX_DEF); 846275976Ssmh mtx_init(&sc->pci_lock, "mrsas_pci_lock", NULL, MTX_DEF); 847275976Ssmh mtx_init(&sc->io_lock, "mrsas_io_lock", NULL, MTX_DEF); 848275976Ssmh mtx_init(&sc->aen_lock, "mrsas_aen_lock", NULL, MTX_DEF); 849275976Ssmh mtx_init(&sc->ioctl_lock, "mrsas_ioctl_lock", NULL, MTX_SPIN); 850275976Ssmh mtx_init(&sc->mpt_cmd_pool_lock, "mrsas_mpt_cmd_pool_lock", NULL, MTX_DEF); 851275976Ssmh mtx_init(&sc->mfi_cmd_pool_lock, "mrsas_mfi_cmd_pool_lock", NULL, MTX_DEF); 852275976Ssmh mtx_init(&sc->raidmap_lock, "mrsas_raidmap_lock", NULL, MTX_DEF); 853275976Ssmh 854275976Ssmh /* 855275976Ssmh * Intialize a counting Semaphore to take care no. of concurrent 856275976Ssmh * IOCTLs 857275976Ssmh */ 858275976Ssmh sema_init(&sc->ioctl_count_sema, MRSAS_MAX_MFI_CMDS - 5, IOCTL_SEMA_DESCRIPTION); 859275976Ssmh 860275976Ssmh /* Intialize linked list */ 861275976Ssmh TAILQ_INIT(&sc->mrsas_mpt_cmd_list_head); 862275976Ssmh TAILQ_INIT(&sc->mrsas_mfi_cmd_list_head); 863275976Ssmh 864275976Ssmh mrsas_atomic_set(&sc->fw_outstanding, 0); 865275976Ssmh 866265555Sambrisko sc->io_cmds_highwater = 0; 867265555Sambrisko 868275976Ssmh /* Create a /dev entry for this device. */ 869275976Ssmh sc->mrsas_cdev = make_dev(&mrsas_cdevsw, device_get_unit(dev), UID_ROOT, 870275976Ssmh GID_OPERATOR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), "mrsas%u", 871275976Ssmh device_get_unit(dev)); 872275976Ssmh if (device_get_unit(dev) == 0) 873275976Ssmh make_dev_alias(sc->mrsas_cdev, "megaraid_sas_ioctl_node"); 874275976Ssmh if (sc->mrsas_cdev) 875275976Ssmh sc->mrsas_cdev->si_drv1 = sc; 876265555Sambrisko 877275976Ssmh sc->adprecovery = MRSAS_HBA_OPERATIONAL; 878265555Sambrisko sc->UnevenSpanSupport = 0; 879265555Sambrisko 880275976Ssmh sc->msix_enable = 0; 881265555Sambrisko 882275976Ssmh /* Initialize Firmware */ 883275976Ssmh if (mrsas_init_fw(sc) != SUCCESS) { 884275976Ssmh goto attach_fail_fw; 885275976Ssmh } 886275976Ssmh /* Register SCSI mid-layer */ 887275976Ssmh if ((mrsas_cam_attach(sc) != SUCCESS)) { 888275976Ssmh goto attach_fail_cam; 889275976Ssmh } 890275976Ssmh /* Register IRQs */ 891275976Ssmh if (mrsas_setup_irq(sc) != SUCCESS) { 892275976Ssmh goto attach_fail_irq; 893275976Ssmh } 894275976Ssmh /* Enable Interrupts */ 895275976Ssmh mrsas_enable_intr(sc); 896265555Sambrisko 897275976Ssmh error = mrsas_kproc_create(mrsas_ocr_thread, sc, 898275976Ssmh &sc->ocr_thread, 0, 0, "mrsas_ocr%d", 899275976Ssmh device_get_unit(sc->mrsas_dev)); 900275976Ssmh if (error) { 901275976Ssmh printf("Error %d starting rescan thread\n", error); 902275976Ssmh goto attach_fail_irq; 903275976Ssmh } 904275976Ssmh mrsas_setup_sysctl(sc); 905265555Sambrisko 906275976Ssmh /* Initiate AEN (Asynchronous Event Notification) */ 907265555Sambrisko 908265555Sambrisko if (mrsas_start_aen(sc)) { 909265555Sambrisko printf("Error: start aen failed\n"); 910265555Sambrisko goto fail_start_aen; 911265555Sambrisko } 912275976Ssmh /* 913275976Ssmh * Add this controller to mrsas_mgmt_info structure so that it can be 914275976Ssmh * exported to management applications 915275976Ssmh */ 916275976Ssmh if (device_get_unit(dev) == 0) 917275976Ssmh memset(&mrsas_mgmt_info, 0, sizeof(mrsas_mgmt_info)); 918265555Sambrisko 919275976Ssmh mrsas_mgmt_info.count++; 920275976Ssmh mrsas_mgmt_info.sc_ptr[mrsas_mgmt_info.max_index] = sc; 921275976Ssmh mrsas_mgmt_info.max_index++; 922265555Sambrisko 923275976Ssmh return (0); 924275976Ssmh 925265555Sambriskofail_start_aen: 926265555Sambriskoattach_fail_irq: 927275976Ssmh mrsas_teardown_intr(sc); 928265555Sambriskoattach_fail_cam: 929275976Ssmh mrsas_cam_detach(sc); 930265555Sambriskoattach_fail_fw: 931275976Ssmh /* if MSIX vector is allocated and FW Init FAILED then release MSIX */ 932275976Ssmh if (sc->msix_enable == 1) 933275976Ssmh pci_release_msi(sc->mrsas_dev); 934275976Ssmh mrsas_free_mem(sc); 935275976Ssmh mtx_destroy(&sc->sim_lock); 936275976Ssmh mtx_destroy(&sc->aen_lock); 937275976Ssmh mtx_destroy(&sc->pci_lock); 938275976Ssmh mtx_destroy(&sc->io_lock); 939275976Ssmh mtx_destroy(&sc->ioctl_lock); 940275976Ssmh mtx_destroy(&sc->mpt_cmd_pool_lock); 941275976Ssmh mtx_destroy(&sc->mfi_cmd_pool_lock); 942275976Ssmh mtx_destroy(&sc->raidmap_lock); 943275976Ssmh /* Destroy the counting semaphore created for Ioctl */ 944275976Ssmh sema_destroy(&sc->ioctl_count_sema); 945265555Sambriskoattach_fail: 946275976Ssmh destroy_dev(sc->mrsas_cdev); 947275976Ssmh if (sc->reg_res) { 948275976Ssmh bus_release_resource(sc->mrsas_dev, SYS_RES_MEMORY, 949275976Ssmh sc->reg_res_id, sc->reg_res); 950275976Ssmh } 951275976Ssmh return (ENXIO); 952265555Sambrisko} 953265555Sambrisko 954275976Ssmh/* 955275976Ssmh * mrsas_detach: De-allocates and teardown resources 956275976Ssmh * input: pointer to device struct 957275976Ssmh * 958275976Ssmh * This function is the entry point for device disconnect and detach. 959275976Ssmh * It performs memory de-allocations, shutdown of the controller and various 960265555Sambrisko * teardown and destroy resource functions. 961265555Sambrisko */ 962275976Ssmhstatic int 963275976Ssmhmrsas_detach(device_t dev) 964265555Sambrisko{ 965275976Ssmh struct mrsas_softc *sc; 966275976Ssmh int i = 0; 967265555Sambrisko 968275976Ssmh sc = device_get_softc(dev); 969275976Ssmh sc->remove_in_progress = 1; 970275976Ssmh 971275976Ssmh /* Destroy the character device so no other IOCTL will be handled */ 972275976Ssmh destroy_dev(sc->mrsas_cdev); 973275976Ssmh 974275976Ssmh /* 975275976Ssmh * Take the instance off the instance array. Note that we will not 976275976Ssmh * decrement the max_index. We let this array be sparse array 977275976Ssmh */ 978275976Ssmh for (i = 0; i < mrsas_mgmt_info.max_index; i++) { 979275976Ssmh if (mrsas_mgmt_info.sc_ptr[i] == sc) { 980275976Ssmh mrsas_mgmt_info.count--; 981275976Ssmh mrsas_mgmt_info.sc_ptr[i] = NULL; 982275976Ssmh break; 983275976Ssmh } 984275976Ssmh } 985275976Ssmh 986275976Ssmh if (sc->ocr_thread_active) 987275976Ssmh wakeup(&sc->ocr_chan); 988275976Ssmh while (sc->reset_in_progress) { 989275976Ssmh i++; 990275976Ssmh if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { 991275976Ssmh mrsas_dprint(sc, MRSAS_INFO, 992275976Ssmh "[%2d]waiting for ocr to be finished\n", i); 993275976Ssmh } 994275976Ssmh pause("mr_shutdown", hz); 995275976Ssmh } 996275976Ssmh i = 0; 997275976Ssmh while (sc->ocr_thread_active) { 998275976Ssmh i++; 999275976Ssmh if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { 1000275976Ssmh mrsas_dprint(sc, MRSAS_INFO, 1001275976Ssmh "[%2d]waiting for " 1002275976Ssmh "mrsas_ocr thread to quit ocr %d\n", i, 1003275976Ssmh sc->ocr_thread_active); 1004275976Ssmh } 1005275976Ssmh pause("mr_shutdown", hz); 1006275976Ssmh } 1007275976Ssmh mrsas_flush_cache(sc); 1008275976Ssmh mrsas_shutdown_ctlr(sc, MR_DCMD_CTRL_SHUTDOWN); 1009275976Ssmh mrsas_disable_intr(sc); 1010275976Ssmh mrsas_cam_detach(sc); 1011275976Ssmh mrsas_teardown_intr(sc); 1012275976Ssmh mrsas_free_mem(sc); 1013275976Ssmh mtx_destroy(&sc->sim_lock); 1014275976Ssmh mtx_destroy(&sc->aen_lock); 1015275976Ssmh mtx_destroy(&sc->pci_lock); 1016275976Ssmh mtx_destroy(&sc->io_lock); 1017275976Ssmh mtx_destroy(&sc->ioctl_lock); 1018275976Ssmh mtx_destroy(&sc->mpt_cmd_pool_lock); 1019275976Ssmh mtx_destroy(&sc->mfi_cmd_pool_lock); 1020275976Ssmh mtx_destroy(&sc->raidmap_lock); 1021275976Ssmh 1022275976Ssmh /* Wait for all the semaphores to be released */ 1023275976Ssmh while (sema_value(&sc->ioctl_count_sema) != (MRSAS_MAX_MFI_CMDS - 5)) 1024275976Ssmh pause("mr_shutdown", hz); 1025275976Ssmh 1026275976Ssmh /* Destroy the counting semaphore created for Ioctl */ 1027275976Ssmh sema_destroy(&sc->ioctl_count_sema); 1028275976Ssmh 1029275976Ssmh if (sc->reg_res) { 1030275976Ssmh bus_release_resource(sc->mrsas_dev, 1031275976Ssmh SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res); 1032275976Ssmh } 1033275976Ssmh if (sc->sysctl_tree != NULL) 1034275976Ssmh sysctl_ctx_free(&sc->sysctl_ctx); 1035275976Ssmh 1036275976Ssmh return (0); 1037265555Sambrisko} 1038265555Sambrisko 1039275976Ssmh/* 1040275976Ssmh * mrsas_free_mem: Frees allocated memory 1041275976Ssmh * input: Adapter instance soft state 1042275976Ssmh * 1043265555Sambrisko * This function is called from mrsas_detach() to free previously allocated 1044275976Ssmh * memory. 1045265555Sambrisko */ 1046275976Ssmhvoid 1047275976Ssmhmrsas_free_mem(struct mrsas_softc *sc) 1048265555Sambrisko{ 1049275976Ssmh int i; 1050275976Ssmh u_int32_t max_cmd; 1051275976Ssmh struct mrsas_mfi_cmd *mfi_cmd; 1052275976Ssmh struct mrsas_mpt_cmd *mpt_cmd; 1053275976Ssmh 1054265555Sambrisko /* 1055275976Ssmh * Free RAID map memory 1056275976Ssmh */ 1057275976Ssmh for (i = 0; i < 2; i++) { 1058275976Ssmh if (sc->raidmap_phys_addr[i]) 1059275976Ssmh bus_dmamap_unload(sc->raidmap_tag[i], sc->raidmap_dmamap[i]); 1060275976Ssmh if (sc->raidmap_mem[i] != NULL) 1061275976Ssmh bus_dmamem_free(sc->raidmap_tag[i], sc->raidmap_mem[i], sc->raidmap_dmamap[i]); 1062275976Ssmh if (sc->raidmap_tag[i] != NULL) 1063275976Ssmh bus_dma_tag_destroy(sc->raidmap_tag[i]); 1064265555Sambrisko 1065275976Ssmh if (sc->ld_drv_map[i] != NULL) 1066275976Ssmh free(sc->ld_drv_map[i], M_MRSAS); 1067275976Ssmh } 1068265555Sambrisko 1069275976Ssmh /* 1070275976Ssmh * Free version buffer memroy 1071275976Ssmh */ 1072275976Ssmh if (sc->verbuf_phys_addr) 1073275976Ssmh bus_dmamap_unload(sc->verbuf_tag, sc->verbuf_dmamap); 1074275976Ssmh if (sc->verbuf_mem != NULL) 1075275976Ssmh bus_dmamem_free(sc->verbuf_tag, sc->verbuf_mem, sc->verbuf_dmamap); 1076275976Ssmh if (sc->verbuf_tag != NULL) 1077275976Ssmh bus_dma_tag_destroy(sc->verbuf_tag); 1078265555Sambrisko 1079265555Sambrisko 1080275976Ssmh /* 1081275976Ssmh * Free sense buffer memory 1082275976Ssmh */ 1083275976Ssmh if (sc->sense_phys_addr) 1084275976Ssmh bus_dmamap_unload(sc->sense_tag, sc->sense_dmamap); 1085275976Ssmh if (sc->sense_mem != NULL) 1086275976Ssmh bus_dmamem_free(sc->sense_tag, sc->sense_mem, sc->sense_dmamap); 1087275976Ssmh if (sc->sense_tag != NULL) 1088275976Ssmh bus_dma_tag_destroy(sc->sense_tag); 1089265555Sambrisko 1090275976Ssmh /* 1091275976Ssmh * Free chain frame memory 1092275976Ssmh */ 1093275976Ssmh if (sc->chain_frame_phys_addr) 1094275976Ssmh bus_dmamap_unload(sc->chain_frame_tag, sc->chain_frame_dmamap); 1095275976Ssmh if (sc->chain_frame_mem != NULL) 1096275976Ssmh bus_dmamem_free(sc->chain_frame_tag, sc->chain_frame_mem, sc->chain_frame_dmamap); 1097275976Ssmh if (sc->chain_frame_tag != NULL) 1098275976Ssmh bus_dma_tag_destroy(sc->chain_frame_tag); 1099265555Sambrisko 1100275976Ssmh /* 1101275976Ssmh * Free IO Request memory 1102275976Ssmh */ 1103275976Ssmh if (sc->io_request_phys_addr) 1104275976Ssmh bus_dmamap_unload(sc->io_request_tag, sc->io_request_dmamap); 1105275976Ssmh if (sc->io_request_mem != NULL) 1106275976Ssmh bus_dmamem_free(sc->io_request_tag, sc->io_request_mem, sc->io_request_dmamap); 1107275976Ssmh if (sc->io_request_tag != NULL) 1108275976Ssmh bus_dma_tag_destroy(sc->io_request_tag); 1109265555Sambrisko 1110275976Ssmh /* 1111275976Ssmh * Free Reply Descriptor memory 1112275976Ssmh */ 1113275976Ssmh if (sc->reply_desc_phys_addr) 1114275976Ssmh bus_dmamap_unload(sc->reply_desc_tag, sc->reply_desc_dmamap); 1115275976Ssmh if (sc->reply_desc_mem != NULL) 1116275976Ssmh bus_dmamem_free(sc->reply_desc_tag, sc->reply_desc_mem, sc->reply_desc_dmamap); 1117275976Ssmh if (sc->reply_desc_tag != NULL) 1118275976Ssmh bus_dma_tag_destroy(sc->reply_desc_tag); 1119275976Ssmh 1120275976Ssmh /* 1121275976Ssmh * Free event detail memory 1122275976Ssmh */ 1123275976Ssmh if (sc->evt_detail_phys_addr) 1124275976Ssmh bus_dmamap_unload(sc->evt_detail_tag, sc->evt_detail_dmamap); 1125275976Ssmh if (sc->evt_detail_mem != NULL) 1126275976Ssmh bus_dmamem_free(sc->evt_detail_tag, sc->evt_detail_mem, sc->evt_detail_dmamap); 1127275976Ssmh if (sc->evt_detail_tag != NULL) 1128275976Ssmh bus_dma_tag_destroy(sc->evt_detail_tag); 1129275976Ssmh 1130275976Ssmh /* 1131275976Ssmh * Free MFI frames 1132275976Ssmh */ 1133265555Sambrisko if (sc->mfi_cmd_list) { 1134275976Ssmh for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 1135275976Ssmh mfi_cmd = sc->mfi_cmd_list[i]; 1136275976Ssmh mrsas_free_frame(sc, mfi_cmd); 1137265555Sambrisko } 1138275976Ssmh } 1139275976Ssmh if (sc->mficmd_frame_tag != NULL) 1140275976Ssmh bus_dma_tag_destroy(sc->mficmd_frame_tag); 1141265555Sambrisko 1142275976Ssmh /* 1143275976Ssmh * Free MPT internal command list 1144275976Ssmh */ 1145275976Ssmh max_cmd = sc->max_fw_cmds; 1146265555Sambrisko if (sc->mpt_cmd_list) { 1147275976Ssmh for (i = 0; i < max_cmd; i++) { 1148275976Ssmh mpt_cmd = sc->mpt_cmd_list[i]; 1149275976Ssmh bus_dmamap_destroy(sc->data_tag, mpt_cmd->data_dmamap); 1150275976Ssmh free(sc->mpt_cmd_list[i], M_MRSAS); 1151275976Ssmh } 1152275976Ssmh free(sc->mpt_cmd_list, M_MRSAS); 1153275976Ssmh sc->mpt_cmd_list = NULL; 1154265555Sambrisko } 1155275976Ssmh /* 1156275976Ssmh * Free MFI internal command list 1157275976Ssmh */ 1158265555Sambrisko 1159265555Sambrisko if (sc->mfi_cmd_list) { 1160275976Ssmh for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 1161275976Ssmh free(sc->mfi_cmd_list[i], M_MRSAS); 1162275976Ssmh } 1163275976Ssmh free(sc->mfi_cmd_list, M_MRSAS); 1164275976Ssmh sc->mfi_cmd_list = NULL; 1165265555Sambrisko } 1166275976Ssmh /* 1167275976Ssmh * Free request descriptor memory 1168275976Ssmh */ 1169275976Ssmh free(sc->req_desc, M_MRSAS); 1170275976Ssmh sc->req_desc = NULL; 1171265555Sambrisko 1172275976Ssmh /* 1173275976Ssmh * Destroy parent tag 1174275976Ssmh */ 1175275976Ssmh if (sc->mrsas_parent_tag != NULL) 1176275976Ssmh bus_dma_tag_destroy(sc->mrsas_parent_tag); 1177284267Skadesai 1178284267Skadesai /* 1179284267Skadesai * Free ctrl_info memory 1180284267Skadesai */ 1181284267Skadesai if (sc->ctrl_info != NULL) 1182284267Skadesai free(sc->ctrl_info, M_MRSAS); 1183265555Sambrisko} 1184265555Sambrisko 1185275976Ssmh/* 1186275976Ssmh * mrsas_teardown_intr: Teardown interrupt 1187275976Ssmh * input: Adapter instance soft state 1188265555Sambrisko * 1189275976Ssmh * This function is called from mrsas_detach() to teardown and release bus 1190275976Ssmh * interrupt resourse. 1191265555Sambrisko */ 1192275976Ssmhvoid 1193275976Ssmhmrsas_teardown_intr(struct mrsas_softc *sc) 1194265555Sambrisko{ 1195275976Ssmh int i; 1196275976Ssmh 1197275976Ssmh if (!sc->msix_enable) { 1198275976Ssmh if (sc->intr_handle[0]) 1199275976Ssmh bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[0], sc->intr_handle[0]); 1200275976Ssmh if (sc->mrsas_irq[0] != NULL) 1201275976Ssmh bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, 1202275976Ssmh sc->irq_id[0], sc->mrsas_irq[0]); 1203275976Ssmh sc->intr_handle[0] = NULL; 1204275976Ssmh } else { 1205275976Ssmh for (i = 0; i < sc->msix_vectors; i++) { 1206275976Ssmh if (sc->intr_handle[i]) 1207275976Ssmh bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[i], 1208275976Ssmh sc->intr_handle[i]); 1209275976Ssmh 1210275976Ssmh if (sc->mrsas_irq[i] != NULL) 1211275976Ssmh bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, 1212275976Ssmh sc->irq_id[i], sc->mrsas_irq[i]); 1213275976Ssmh 1214275976Ssmh sc->intr_handle[i] = NULL; 1215275976Ssmh } 1216275976Ssmh pci_release_msi(sc->mrsas_dev); 1217275976Ssmh } 1218275976Ssmh 1219265555Sambrisko} 1220265555Sambrisko 1221275976Ssmh/* 1222275976Ssmh * mrsas_suspend: Suspend entry point 1223275976Ssmh * input: Device struct pointer 1224275976Ssmh * 1225275976Ssmh * This function is the entry point for system suspend from the OS. 1226265555Sambrisko */ 1227275976Ssmhstatic int 1228275976Ssmhmrsas_suspend(device_t dev) 1229265555Sambrisko{ 1230275976Ssmh struct mrsas_softc *sc; 1231265555Sambrisko 1232275976Ssmh sc = device_get_softc(dev); 1233275976Ssmh return (0); 1234265555Sambrisko} 1235265555Sambrisko 1236275976Ssmh/* 1237275976Ssmh * mrsas_resume: Resume entry point 1238275976Ssmh * input: Device struct pointer 1239275976Ssmh * 1240275976Ssmh * This function is the entry point for system resume from the OS. 1241265555Sambrisko */ 1242275976Ssmhstatic int 1243275976Ssmhmrsas_resume(device_t dev) 1244265555Sambrisko{ 1245275976Ssmh struct mrsas_softc *sc; 1246265555Sambrisko 1247275976Ssmh sc = device_get_softc(dev); 1248275976Ssmh return (0); 1249265555Sambrisko} 1250265555Sambrisko 1251284267Skadesai/** 1252284267Skadesai * mrsas_get_softc_instance: Find softc instance based on cmd type 1253284267Skadesai * 1254284267Skadesai * This function will return softc instance based on cmd type. 1255284267Skadesai * In some case, application fire ioctl on required management instance and 1256284267Skadesai * do not provide host_no. Use cdev->si_drv1 to get softc instance for those 1257284267Skadesai * case, else get the softc instance from host_no provided by application in 1258284267Skadesai * user data. 1259284267Skadesai */ 1260284267Skadesai 1261284267Skadesaistatic struct mrsas_softc * 1262284267Skadesaimrsas_get_softc_instance(struct cdev *dev, u_long cmd, caddr_t arg) 1263284267Skadesai{ 1264284267Skadesai struct mrsas_softc *sc = NULL; 1265284267Skadesai struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; 1266284267Skadesai 1267284267Skadesai if (cmd == MRSAS_IOC_GET_PCI_INFO) { 1268284267Skadesai sc = dev->si_drv1; 1269284267Skadesai } else { 1270284267Skadesai /* 1271284267Skadesai * get the Host number & the softc from data sent by the 1272284267Skadesai * Application 1273284267Skadesai */ 1274284267Skadesai sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no]; 1275284267Skadesai if ((user_ioc->host_no >= mrsas_mgmt_info.max_index) || (sc == NULL)) { 1276284267Skadesai if (sc == NULL) 1277284267Skadesai mrsas_dprint(sc, MRSAS_FAULT, 1278284267Skadesai "There is no Controller number %d .\n", user_ioc->host_no); 1279284267Skadesai else 1280284267Skadesai mrsas_dprint(sc, MRSAS_FAULT, 1281284267Skadesai "Invalid Controller number %d .\n", user_ioc->host_no); 1282284267Skadesai } 1283284267Skadesai } 1284284267Skadesai 1285284267Skadesai return sc; 1286284267Skadesai} 1287284267Skadesai 1288275976Ssmh/* 1289275976Ssmh * mrsas_ioctl: IOCtl commands entry point. 1290275976Ssmh * 1291275976Ssmh * This function is the entry point for IOCtls from the OS. It calls the 1292265555Sambrisko * appropriate function for processing depending on the command received. 1293265555Sambrisko */ 1294265555Sambriskostatic int 1295265555Sambriskomrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) 1296265555Sambrisko{ 1297275976Ssmh struct mrsas_softc *sc; 1298275976Ssmh int ret = 0, i = 0; 1299284267Skadesai MRSAS_DRV_PCI_INFORMATION *pciDrvInfo; 1300265555Sambrisko 1301284267Skadesai sc = mrsas_get_softc_instance(dev, cmd, arg); 1302284267Skadesai if (!sc) 1303284267Skadesai return ENOENT; 1304265555Sambrisko 1305275976Ssmh if (sc->remove_in_progress) { 1306275976Ssmh mrsas_dprint(sc, MRSAS_INFO, 1307275976Ssmh "Driver remove or shutdown called.\n"); 1308275976Ssmh return ENOENT; 1309275976Ssmh } 1310275976Ssmh mtx_lock_spin(&sc->ioctl_lock); 1311275976Ssmh if (!sc->reset_in_progress) { 1312275976Ssmh mtx_unlock_spin(&sc->ioctl_lock); 1313275976Ssmh goto do_ioctl; 1314275976Ssmh } 1315275976Ssmh mtx_unlock_spin(&sc->ioctl_lock); 1316275976Ssmh while (sc->reset_in_progress) { 1317275976Ssmh i++; 1318275976Ssmh if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { 1319275976Ssmh mrsas_dprint(sc, MRSAS_INFO, 1320275976Ssmh "[%2d]waiting for " 1321275976Ssmh "OCR to be finished %d\n", i, 1322275976Ssmh sc->ocr_thread_active); 1323275976Ssmh } 1324275976Ssmh pause("mr_ioctl", hz); 1325275976Ssmh } 1326275976Ssmh 1327265555Sambriskodo_ioctl: 1328275976Ssmh switch (cmd) { 1329275976Ssmh case MRSAS_IOC_FIRMWARE_PASS_THROUGH64: 1330275976Ssmh#ifdef COMPAT_FREEBSD32 1331275976Ssmh case MRSAS_IOC_FIRMWARE_PASS_THROUGH32: 1332275976Ssmh#endif 1333275976Ssmh /* 1334275976Ssmh * Decrement the Ioctl counting Semaphore before getting an 1335275976Ssmh * mfi command 1336275976Ssmh */ 1337275976Ssmh sema_wait(&sc->ioctl_count_sema); 1338275976Ssmh 1339275976Ssmh ret = mrsas_passthru(sc, (void *)arg, cmd); 1340275976Ssmh 1341275976Ssmh /* Increment the Ioctl counting semaphore value */ 1342275976Ssmh sema_post(&sc->ioctl_count_sema); 1343275976Ssmh 1344275976Ssmh break; 1345275976Ssmh case MRSAS_IOC_SCAN_BUS: 1346275976Ssmh ret = mrsas_bus_scan(sc); 1347275976Ssmh break; 1348284267Skadesai 1349284267Skadesai case MRSAS_IOC_GET_PCI_INFO: 1350284267Skadesai pciDrvInfo = (MRSAS_DRV_PCI_INFORMATION *) arg; 1351284267Skadesai memset(pciDrvInfo, 0, sizeof(MRSAS_DRV_PCI_INFORMATION)); 1352284267Skadesai pciDrvInfo->busNumber = pci_get_bus(sc->mrsas_dev); 1353284267Skadesai pciDrvInfo->deviceNumber = pci_get_slot(sc->mrsas_dev); 1354284267Skadesai pciDrvInfo->functionNumber = pci_get_function(sc->mrsas_dev); 1355284267Skadesai pciDrvInfo->domainID = pci_get_domain(sc->mrsas_dev); 1356284267Skadesai mrsas_dprint(sc, MRSAS_INFO, "pci bus no: %d," 1357284267Skadesai "pci device no: %d, pci function no: %d," 1358284267Skadesai "pci domain ID: %d\n", 1359284267Skadesai pciDrvInfo->busNumber, pciDrvInfo->deviceNumber, 1360284267Skadesai pciDrvInfo->functionNumber, pciDrvInfo->domainID); 1361284267Skadesai ret = 0; 1362284267Skadesai break; 1363284267Skadesai 1364275976Ssmh default: 1365275976Ssmh mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd); 1366275976Ssmh ret = ENOENT; 1367275976Ssmh } 1368275976Ssmh 1369275976Ssmh return (ret); 1370265555Sambrisko} 1371265555Sambrisko 1372275976Ssmh/* 1373275976Ssmh * mrsas_poll: poll entry point for mrsas driver fd 1374275976Ssmh * 1375275976Ssmh * This function is the entry point for poll from the OS. It waits for some AEN 1376275976Ssmh * events to be triggered from the controller and notifies back. 1377275976Ssmh */ 1378275976Ssmhstatic int 1379275976Ssmhmrsas_poll(struct cdev *dev, int poll_events, struct thread *td) 1380275976Ssmh{ 1381275976Ssmh struct mrsas_softc *sc; 1382275976Ssmh int revents = 0; 1383275976Ssmh 1384275976Ssmh sc = dev->si_drv1; 1385275976Ssmh 1386275976Ssmh if (poll_events & (POLLIN | POLLRDNORM)) { 1387275976Ssmh if (sc->mrsas_aen_triggered) { 1388275976Ssmh revents |= poll_events & (POLLIN | POLLRDNORM); 1389275976Ssmh } 1390275976Ssmh } 1391275976Ssmh if (revents == 0) { 1392275976Ssmh if (poll_events & (POLLIN | POLLRDNORM)) { 1393284267Skadesai mtx_lock(&sc->aen_lock); 1394275976Ssmh sc->mrsas_poll_waiting = 1; 1395275976Ssmh selrecord(td, &sc->mrsas_select); 1396284267Skadesai mtx_unlock(&sc->aen_lock); 1397275976Ssmh } 1398275976Ssmh } 1399275976Ssmh return revents; 1400275976Ssmh} 1401275976Ssmh 1402275976Ssmh/* 1403275976Ssmh * mrsas_setup_irq: Set up interrupt 1404275976Ssmh * input: Adapter instance soft state 1405275976Ssmh * 1406265555Sambrisko * This function sets up interrupts as a bus resource, with flags indicating 1407275976Ssmh * resource permitting contemporaneous sharing and for resource to activate 1408265555Sambrisko * atomically. 1409265555Sambrisko */ 1410275976Ssmhstatic int 1411275976Ssmhmrsas_setup_irq(struct mrsas_softc *sc) 1412265555Sambrisko{ 1413275976Ssmh if (sc->msix_enable && (mrsas_setup_msix(sc) == SUCCESS)) 1414275976Ssmh device_printf(sc->mrsas_dev, "MSI-x interrupts setup success\n"); 1415265555Sambrisko 1416275976Ssmh else { 1417275976Ssmh device_printf(sc->mrsas_dev, "Fall back to legacy interrupt\n"); 1418275976Ssmh sc->irq_context[0].sc = sc; 1419275976Ssmh sc->irq_context[0].MSIxIndex = 0; 1420275976Ssmh sc->irq_id[0] = 0; 1421275976Ssmh sc->mrsas_irq[0] = bus_alloc_resource_any(sc->mrsas_dev, 1422275976Ssmh SYS_RES_IRQ, &sc->irq_id[0], RF_SHAREABLE | RF_ACTIVE); 1423275976Ssmh if (sc->mrsas_irq[0] == NULL) { 1424275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate legcay" 1425275976Ssmh "interrupt\n"); 1426275976Ssmh return (FAIL); 1427275976Ssmh } 1428275976Ssmh if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq[0], 1429275976Ssmh INTR_MPSAFE | INTR_TYPE_CAM, NULL, mrsas_isr, 1430275976Ssmh &sc->irq_context[0], &sc->intr_handle[0])) { 1431275976Ssmh device_printf(sc->mrsas_dev, "Cannot set up legacy" 1432275976Ssmh "interrupt\n"); 1433275976Ssmh return (FAIL); 1434275976Ssmh } 1435275976Ssmh } 1436275976Ssmh return (0); 1437265555Sambrisko} 1438265555Sambrisko 1439265555Sambrisko/* 1440275976Ssmh * mrsas_isr: ISR entry point 1441275976Ssmh * input: argument pointer 1442265555Sambrisko * 1443275976Ssmh * This function is the interrupt service routine entry point. There are two 1444275976Ssmh * types of interrupts, state change interrupt and response interrupt. If an 1445275976Ssmh * interrupt is not ours, we just return. 1446265555Sambrisko */ 1447275976Ssmhvoid 1448275976Ssmhmrsas_isr(void *arg) 1449265555Sambrisko{ 1450275976Ssmh struct mrsas_irq_context *irq_context = (struct mrsas_irq_context *)arg; 1451275976Ssmh struct mrsas_softc *sc = irq_context->sc; 1452275976Ssmh int status = 0; 1453265555Sambrisko 1454284267Skadesai if (sc->mask_interrupts) 1455284267Skadesai return; 1456284267Skadesai 1457275976Ssmh if (!sc->msix_vectors) { 1458275976Ssmh status = mrsas_clear_intr(sc); 1459275976Ssmh if (!status) 1460275976Ssmh return; 1461275976Ssmh } 1462275976Ssmh /* If we are resetting, bail */ 1463275976Ssmh if (mrsas_test_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags)) { 1464275976Ssmh printf(" Entered into ISR when OCR is going active. \n"); 1465275976Ssmh mrsas_clear_intr(sc); 1466275976Ssmh return; 1467275976Ssmh } 1468275976Ssmh /* Process for reply request and clear response interrupt */ 1469275976Ssmh if (mrsas_complete_cmd(sc, irq_context->MSIxIndex) != SUCCESS) 1470275976Ssmh mrsas_clear_intr(sc); 1471265555Sambrisko 1472275976Ssmh return; 1473265555Sambrisko} 1474265555Sambrisko 1475265555Sambrisko/* 1476275976Ssmh * mrsas_complete_cmd: Process reply request 1477275976Ssmh * input: Adapter instance soft state 1478265555Sambrisko * 1479275976Ssmh * This function is called from mrsas_isr() to process reply request and clear 1480275976Ssmh * response interrupt. Processing of the reply request entails walking 1481275976Ssmh * through the reply descriptor array for the command request pended from 1482275976Ssmh * Firmware. We look at the Function field to determine the command type and 1483275976Ssmh * perform the appropriate action. Before we return, we clear the response 1484275976Ssmh * interrupt. 1485265555Sambrisko */ 1486275976Ssmhstatic int 1487275976Ssmhmrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) 1488265555Sambrisko{ 1489275976Ssmh Mpi2ReplyDescriptorsUnion_t *desc; 1490275976Ssmh MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; 1491275976Ssmh MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req; 1492275976Ssmh struct mrsas_mpt_cmd *cmd_mpt; 1493275976Ssmh struct mrsas_mfi_cmd *cmd_mfi; 1494284267Skadesai u_int8_t reply_descript_type; 1495275976Ssmh u_int16_t smid, num_completed; 1496275976Ssmh u_int8_t status, extStatus; 1497275976Ssmh union desc_value desc_val; 1498275976Ssmh PLD_LOAD_BALANCE_INFO lbinfo; 1499275976Ssmh u_int32_t device_id; 1500275976Ssmh int threshold_reply_count = 0; 1501265555Sambrisko 1502265555Sambrisko 1503275976Ssmh /* If we have a hardware error, not need to continue */ 1504275976Ssmh if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) 1505275976Ssmh return (DONE); 1506265555Sambrisko 1507275976Ssmh desc = sc->reply_desc_mem; 1508275976Ssmh desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION)) 1509275976Ssmh + sc->last_reply_idx[MSIxIndex]; 1510265555Sambrisko 1511275976Ssmh reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc; 1512265555Sambrisko 1513275976Ssmh desc_val.word = desc->Words; 1514275976Ssmh num_completed = 0; 1515265555Sambrisko 1516275976Ssmh reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; 1517265555Sambrisko 1518275976Ssmh /* Find our reply descriptor for the command and process */ 1519275976Ssmh while ((desc_val.u.low != 0xFFFFFFFF) && (desc_val.u.high != 0xFFFFFFFF)) { 1520275976Ssmh smid = reply_desc->SMID; 1521275976Ssmh cmd_mpt = sc->mpt_cmd_list[smid - 1]; 1522275976Ssmh scsi_io_req = (MRSAS_RAID_SCSI_IO_REQUEST *) cmd_mpt->io_request; 1523265555Sambrisko 1524275976Ssmh status = scsi_io_req->RaidContext.status; 1525275976Ssmh extStatus = scsi_io_req->RaidContext.exStatus; 1526265555Sambrisko 1527275976Ssmh switch (scsi_io_req->Function) { 1528275976Ssmh case MPI2_FUNCTION_SCSI_IO_REQUEST: /* Fast Path IO. */ 1529275976Ssmh device_id = cmd_mpt->ccb_ptr->ccb_h.target_id; 1530275976Ssmh lbinfo = &sc->load_balance_info[device_id]; 1531275976Ssmh if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) { 1532284267Skadesai mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[cmd_mpt->pd_r1_lb]); 1533275976Ssmh cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG; 1534275976Ssmh } 1535275976Ssmh /* Fall thru and complete IO */ 1536275976Ssmh case MRSAS_MPI2_FUNCTION_LD_IO_REQUEST: 1537275976Ssmh mrsas_map_mpt_cmd_status(cmd_mpt, status, extStatus); 1538275976Ssmh mrsas_cmd_done(sc, cmd_mpt); 1539275976Ssmh scsi_io_req->RaidContext.status = 0; 1540275976Ssmh scsi_io_req->RaidContext.exStatus = 0; 1541275976Ssmh mrsas_atomic_dec(&sc->fw_outstanding); 1542275976Ssmh break; 1543275976Ssmh case MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /* MFI command */ 1544275976Ssmh cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx]; 1545275976Ssmh mrsas_complete_mptmfi_passthru(sc, cmd_mfi, status); 1546275976Ssmh cmd_mpt->flags = 0; 1547275976Ssmh mrsas_release_mpt_cmd(cmd_mpt); 1548275976Ssmh break; 1549275976Ssmh } 1550265555Sambrisko 1551275976Ssmh sc->last_reply_idx[MSIxIndex]++; 1552275976Ssmh if (sc->last_reply_idx[MSIxIndex] >= sc->reply_q_depth) 1553275976Ssmh sc->last_reply_idx[MSIxIndex] = 0; 1554265555Sambrisko 1555275976Ssmh desc->Words = ~((uint64_t)0x00); /* set it back to all 1556275976Ssmh * 0xFFFFFFFFs */ 1557275976Ssmh num_completed++; 1558275976Ssmh threshold_reply_count++; 1559265555Sambrisko 1560275976Ssmh /* Get the next reply descriptor */ 1561275976Ssmh if (!sc->last_reply_idx[MSIxIndex]) { 1562275976Ssmh desc = sc->reply_desc_mem; 1563275976Ssmh desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION)); 1564275976Ssmh } else 1565275976Ssmh desc++; 1566265555Sambrisko 1567275976Ssmh reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc; 1568275976Ssmh desc_val.word = desc->Words; 1569265555Sambrisko 1570275976Ssmh reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; 1571265555Sambrisko 1572275976Ssmh if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) 1573275976Ssmh break; 1574265555Sambrisko 1575275976Ssmh /* 1576275976Ssmh * Write to reply post index after completing threshold reply 1577275976Ssmh * count and still there are more replies in reply queue 1578275976Ssmh * pending to be completed. 1579275976Ssmh */ 1580275976Ssmh if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) { 1581275976Ssmh if (sc->msix_enable) { 1582275976Ssmh if ((sc->device_id == MRSAS_INVADER) || 1583275976Ssmh (sc->device_id == MRSAS_FURY)) 1584275976Ssmh mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8], 1585275976Ssmh ((MSIxIndex & 0x7) << 24) | 1586275976Ssmh sc->last_reply_idx[MSIxIndex]); 1587275976Ssmh else 1588275976Ssmh mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) | 1589275976Ssmh sc->last_reply_idx[MSIxIndex]); 1590275976Ssmh } else 1591275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, 1592275976Ssmh reply_post_host_index), sc->last_reply_idx[0]); 1593265555Sambrisko 1594275976Ssmh threshold_reply_count = 0; 1595275976Ssmh } 1596275976Ssmh } 1597265555Sambrisko 1598275976Ssmh /* No match, just return */ 1599275976Ssmh if (num_completed == 0) 1600275976Ssmh return (DONE); 1601275976Ssmh 1602275976Ssmh /* Clear response interrupt */ 1603275976Ssmh if (sc->msix_enable) { 1604275976Ssmh if ((sc->device_id == MRSAS_INVADER) || 1605275976Ssmh (sc->device_id == MRSAS_FURY)) { 1606275976Ssmh mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8], 1607275976Ssmh ((MSIxIndex & 0x7) << 24) | 1608275976Ssmh sc->last_reply_idx[MSIxIndex]); 1609275976Ssmh } else 1610275976Ssmh mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) | 1611275976Ssmh sc->last_reply_idx[MSIxIndex]); 1612275976Ssmh } else 1613275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, 1614275976Ssmh reply_post_host_index), sc->last_reply_idx[0]); 1615275976Ssmh 1616275976Ssmh return (0); 1617265555Sambrisko} 1618265555Sambrisko 1619265555Sambrisko/* 1620275976Ssmh * mrsas_map_mpt_cmd_status: Allocate DMAable memory. 1621275976Ssmh * input: Adapter instance soft state 1622265555Sambrisko * 1623265555Sambrisko * This function is called from mrsas_complete_cmd(), for LD IO and FastPath IO. 1624275976Ssmh * It checks the command status and maps the appropriate CAM status for the 1625275976Ssmh * CCB. 1626265555Sambrisko */ 1627275976Ssmhvoid 1628275976Ssmhmrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t extStatus) 1629265555Sambrisko{ 1630275976Ssmh struct mrsas_softc *sc = cmd->sc; 1631275976Ssmh u_int8_t *sense_data; 1632265555Sambrisko 1633275976Ssmh switch (status) { 1634275976Ssmh case MFI_STAT_OK: 1635275976Ssmh cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP; 1636275976Ssmh break; 1637275976Ssmh case MFI_STAT_SCSI_IO_FAILED: 1638275976Ssmh case MFI_STAT_SCSI_DONE_WITH_ERROR: 1639275976Ssmh cmd->ccb_ptr->ccb_h.status = CAM_SCSI_STATUS_ERROR; 1640275976Ssmh sense_data = (u_int8_t *)&cmd->ccb_ptr->csio.sense_data; 1641275976Ssmh if (sense_data) { 1642275976Ssmh /* For now just copy 18 bytes back */ 1643275976Ssmh memcpy(sense_data, cmd->sense, 18); 1644275976Ssmh cmd->ccb_ptr->csio.sense_len = 18; 1645275976Ssmh cmd->ccb_ptr->ccb_h.status |= CAM_AUTOSNS_VALID; 1646275976Ssmh } 1647275976Ssmh break; 1648275976Ssmh case MFI_STAT_LD_OFFLINE: 1649275976Ssmh case MFI_STAT_DEVICE_NOT_FOUND: 1650275976Ssmh if (cmd->ccb_ptr->ccb_h.target_lun) 1651275976Ssmh cmd->ccb_ptr->ccb_h.status |= CAM_LUN_INVALID; 1652275976Ssmh else 1653275976Ssmh cmd->ccb_ptr->ccb_h.status |= CAM_DEV_NOT_THERE; 1654275976Ssmh break; 1655275976Ssmh case MFI_STAT_CONFIG_SEQ_MISMATCH: 1656275976Ssmh cmd->ccb_ptr->ccb_h.status |= CAM_REQUEUE_REQ; 1657275976Ssmh break; 1658275976Ssmh default: 1659275976Ssmh device_printf(sc->mrsas_dev, "FW cmd complete status %x\n", status); 1660275976Ssmh cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP_ERR; 1661275976Ssmh cmd->ccb_ptr->csio.scsi_status = status; 1662275976Ssmh } 1663275976Ssmh return; 1664265555Sambrisko} 1665265555Sambrisko 1666265555Sambrisko/* 1667275976Ssmh * mrsas_alloc_mem: Allocate DMAable memory 1668275976Ssmh * input: Adapter instance soft state 1669265555Sambrisko * 1670275976Ssmh * This function creates the parent DMA tag and allocates DMAable memory. DMA 1671275976Ssmh * tag describes constraints of DMA mapping. Memory allocated is mapped into 1672275976Ssmh * Kernel virtual address. Callback argument is physical memory address. 1673265555Sambrisko */ 1674275976Ssmhstatic int 1675275976Ssmhmrsas_alloc_mem(struct mrsas_softc *sc) 1676265555Sambrisko{ 1677284267Skadesai u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, 1678284267Skadesai chain_frame_size, evt_detail_size, count; 1679265555Sambrisko 1680275976Ssmh /* 1681275976Ssmh * Allocate parent DMA tag 1682275976Ssmh */ 1683275976Ssmh if (bus_dma_tag_create(NULL, /* parent */ 1684275976Ssmh 1, /* alignment */ 1685275976Ssmh 0, /* boundary */ 1686275976Ssmh BUS_SPACE_MAXADDR, /* lowaddr */ 1687275976Ssmh BUS_SPACE_MAXADDR, /* highaddr */ 1688275976Ssmh NULL, NULL, /* filter, filterarg */ 1689275976Ssmh MRSAS_MAX_IO_SIZE, /* maxsize */ 1690275976Ssmh MRSAS_MAX_SGL, /* nsegments */ 1691275976Ssmh MRSAS_MAX_IO_SIZE, /* maxsegsize */ 1692275976Ssmh 0, /* flags */ 1693275976Ssmh NULL, NULL, /* lockfunc, lockarg */ 1694275976Ssmh &sc->mrsas_parent_tag /* tag */ 1695275976Ssmh )) { 1696275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate parent DMA tag\n"); 1697275976Ssmh return (ENOMEM); 1698275976Ssmh } 1699275976Ssmh /* 1700275976Ssmh * Allocate for version buffer 1701275976Ssmh */ 1702275976Ssmh verbuf_size = MRSAS_MAX_NAME_LENGTH * (sizeof(bus_addr_t)); 1703275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1704275976Ssmh 1, 0, 1705275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1706275976Ssmh BUS_SPACE_MAXADDR, 1707275976Ssmh NULL, NULL, 1708275976Ssmh verbuf_size, 1709275976Ssmh 1, 1710275976Ssmh verbuf_size, 1711275976Ssmh BUS_DMA_ALLOCNOW, 1712275976Ssmh NULL, NULL, 1713275976Ssmh &sc->verbuf_tag)) { 1714275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate verbuf DMA tag\n"); 1715275976Ssmh return (ENOMEM); 1716275976Ssmh } 1717275976Ssmh if (bus_dmamem_alloc(sc->verbuf_tag, (void **)&sc->verbuf_mem, 1718275976Ssmh BUS_DMA_NOWAIT, &sc->verbuf_dmamap)) { 1719275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate verbuf memory\n"); 1720275976Ssmh return (ENOMEM); 1721275976Ssmh } 1722275976Ssmh bzero(sc->verbuf_mem, verbuf_size); 1723275976Ssmh if (bus_dmamap_load(sc->verbuf_tag, sc->verbuf_dmamap, sc->verbuf_mem, 1724275976Ssmh verbuf_size, mrsas_addr_cb, &sc->verbuf_phys_addr, 1725275976Ssmh BUS_DMA_NOWAIT)) { 1726275976Ssmh device_printf(sc->mrsas_dev, "Cannot load verbuf DMA map\n"); 1727275976Ssmh return (ENOMEM); 1728275976Ssmh } 1729275976Ssmh /* 1730275976Ssmh * Allocate IO Request Frames 1731275976Ssmh */ 1732275976Ssmh io_req_size = sc->io_frames_alloc_sz; 1733275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1734275976Ssmh 16, 0, 1735275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1736275976Ssmh BUS_SPACE_MAXADDR, 1737275976Ssmh NULL, NULL, 1738275976Ssmh io_req_size, 1739275976Ssmh 1, 1740275976Ssmh io_req_size, 1741275976Ssmh BUS_DMA_ALLOCNOW, 1742275976Ssmh NULL, NULL, 1743275976Ssmh &sc->io_request_tag)) { 1744275976Ssmh device_printf(sc->mrsas_dev, "Cannot create IO request tag\n"); 1745275976Ssmh return (ENOMEM); 1746275976Ssmh } 1747275976Ssmh if (bus_dmamem_alloc(sc->io_request_tag, (void **)&sc->io_request_mem, 1748275976Ssmh BUS_DMA_NOWAIT, &sc->io_request_dmamap)) { 1749275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc IO request memory\n"); 1750275976Ssmh return (ENOMEM); 1751275976Ssmh } 1752275976Ssmh bzero(sc->io_request_mem, io_req_size); 1753275976Ssmh if (bus_dmamap_load(sc->io_request_tag, sc->io_request_dmamap, 1754275976Ssmh sc->io_request_mem, io_req_size, mrsas_addr_cb, 1755275976Ssmh &sc->io_request_phys_addr, BUS_DMA_NOWAIT)) { 1756275976Ssmh device_printf(sc->mrsas_dev, "Cannot load IO request memory\n"); 1757275976Ssmh return (ENOMEM); 1758275976Ssmh } 1759275976Ssmh /* 1760275976Ssmh * Allocate Chain Frames 1761275976Ssmh */ 1762275976Ssmh chain_frame_size = sc->chain_frames_alloc_sz; 1763275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1764275976Ssmh 4, 0, 1765275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1766275976Ssmh BUS_SPACE_MAXADDR, 1767275976Ssmh NULL, NULL, 1768275976Ssmh chain_frame_size, 1769275976Ssmh 1, 1770275976Ssmh chain_frame_size, 1771275976Ssmh BUS_DMA_ALLOCNOW, 1772275976Ssmh NULL, NULL, 1773275976Ssmh &sc->chain_frame_tag)) { 1774275976Ssmh device_printf(sc->mrsas_dev, "Cannot create chain frame tag\n"); 1775275976Ssmh return (ENOMEM); 1776275976Ssmh } 1777275976Ssmh if (bus_dmamem_alloc(sc->chain_frame_tag, (void **)&sc->chain_frame_mem, 1778275976Ssmh BUS_DMA_NOWAIT, &sc->chain_frame_dmamap)) { 1779275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc chain frame memory\n"); 1780275976Ssmh return (ENOMEM); 1781275976Ssmh } 1782275976Ssmh bzero(sc->chain_frame_mem, chain_frame_size); 1783275976Ssmh if (bus_dmamap_load(sc->chain_frame_tag, sc->chain_frame_dmamap, 1784275976Ssmh sc->chain_frame_mem, chain_frame_size, mrsas_addr_cb, 1785275976Ssmh &sc->chain_frame_phys_addr, BUS_DMA_NOWAIT)) { 1786275976Ssmh device_printf(sc->mrsas_dev, "Cannot load chain frame memory\n"); 1787275976Ssmh return (ENOMEM); 1788275976Ssmh } 1789275976Ssmh count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 1790275976Ssmh /* 1791275976Ssmh * Allocate Reply Descriptor Array 1792275976Ssmh */ 1793275976Ssmh reply_desc_size = sc->reply_alloc_sz * count; 1794275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1795275976Ssmh 16, 0, 1796275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1797275976Ssmh BUS_SPACE_MAXADDR, 1798275976Ssmh NULL, NULL, 1799275976Ssmh reply_desc_size, 1800275976Ssmh 1, 1801275976Ssmh reply_desc_size, 1802275976Ssmh BUS_DMA_ALLOCNOW, 1803275976Ssmh NULL, NULL, 1804275976Ssmh &sc->reply_desc_tag)) { 1805275976Ssmh device_printf(sc->mrsas_dev, "Cannot create reply descriptor tag\n"); 1806275976Ssmh return (ENOMEM); 1807275976Ssmh } 1808275976Ssmh if (bus_dmamem_alloc(sc->reply_desc_tag, (void **)&sc->reply_desc_mem, 1809275976Ssmh BUS_DMA_NOWAIT, &sc->reply_desc_dmamap)) { 1810275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc reply descriptor memory\n"); 1811275976Ssmh return (ENOMEM); 1812275976Ssmh } 1813275976Ssmh if (bus_dmamap_load(sc->reply_desc_tag, sc->reply_desc_dmamap, 1814275976Ssmh sc->reply_desc_mem, reply_desc_size, mrsas_addr_cb, 1815275976Ssmh &sc->reply_desc_phys_addr, BUS_DMA_NOWAIT)) { 1816275976Ssmh device_printf(sc->mrsas_dev, "Cannot load reply descriptor memory\n"); 1817275976Ssmh return (ENOMEM); 1818275976Ssmh } 1819275976Ssmh /* 1820275976Ssmh * Allocate Sense Buffer Array. Keep in lower 4GB 1821275976Ssmh */ 1822275976Ssmh sense_size = sc->max_fw_cmds * MRSAS_SENSE_LEN; 1823275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1824275976Ssmh 64, 0, 1825275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1826275976Ssmh BUS_SPACE_MAXADDR, 1827275976Ssmh NULL, NULL, 1828275976Ssmh sense_size, 1829275976Ssmh 1, 1830275976Ssmh sense_size, 1831275976Ssmh BUS_DMA_ALLOCNOW, 1832275976Ssmh NULL, NULL, 1833275976Ssmh &sc->sense_tag)) { 1834275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate sense buf tag\n"); 1835275976Ssmh return (ENOMEM); 1836275976Ssmh } 1837275976Ssmh if (bus_dmamem_alloc(sc->sense_tag, (void **)&sc->sense_mem, 1838275976Ssmh BUS_DMA_NOWAIT, &sc->sense_dmamap)) { 1839275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate sense buf memory\n"); 1840275976Ssmh return (ENOMEM); 1841275976Ssmh } 1842275976Ssmh if (bus_dmamap_load(sc->sense_tag, sc->sense_dmamap, 1843275976Ssmh sc->sense_mem, sense_size, mrsas_addr_cb, &sc->sense_phys_addr, 1844275976Ssmh BUS_DMA_NOWAIT)) { 1845275976Ssmh device_printf(sc->mrsas_dev, "Cannot load sense buf memory\n"); 1846275976Ssmh return (ENOMEM); 1847275976Ssmh } 1848275976Ssmh /* 1849275976Ssmh * Allocate for Event detail structure 1850275976Ssmh */ 1851275976Ssmh evt_detail_size = sizeof(struct mrsas_evt_detail); 1852275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1853275976Ssmh 1, 0, 1854275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1855275976Ssmh BUS_SPACE_MAXADDR, 1856275976Ssmh NULL, NULL, 1857275976Ssmh evt_detail_size, 1858275976Ssmh 1, 1859275976Ssmh evt_detail_size, 1860275976Ssmh BUS_DMA_ALLOCNOW, 1861275976Ssmh NULL, NULL, 1862275976Ssmh &sc->evt_detail_tag)) { 1863275976Ssmh device_printf(sc->mrsas_dev, "Cannot create Event detail tag\n"); 1864275976Ssmh return (ENOMEM); 1865275976Ssmh } 1866275976Ssmh if (bus_dmamem_alloc(sc->evt_detail_tag, (void **)&sc->evt_detail_mem, 1867275976Ssmh BUS_DMA_NOWAIT, &sc->evt_detail_dmamap)) { 1868275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc Event detail buffer memory\n"); 1869275976Ssmh return (ENOMEM); 1870275976Ssmh } 1871275976Ssmh bzero(sc->evt_detail_mem, evt_detail_size); 1872275976Ssmh if (bus_dmamap_load(sc->evt_detail_tag, sc->evt_detail_dmamap, 1873275976Ssmh sc->evt_detail_mem, evt_detail_size, mrsas_addr_cb, 1874275976Ssmh &sc->evt_detail_phys_addr, BUS_DMA_NOWAIT)) { 1875275976Ssmh device_printf(sc->mrsas_dev, "Cannot load Event detail buffer memory\n"); 1876275976Ssmh return (ENOMEM); 1877275976Ssmh } 1878275976Ssmh /* 1879275976Ssmh * Create a dma tag for data buffers; size will be the maximum 1880275976Ssmh * possible I/O size (280kB). 1881275976Ssmh */ 1882275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1883275976Ssmh 1, 1884275976Ssmh 0, 1885275976Ssmh BUS_SPACE_MAXADDR, 1886275976Ssmh BUS_SPACE_MAXADDR, 1887275976Ssmh NULL, NULL, 1888275976Ssmh MRSAS_MAX_IO_SIZE, 1889275976Ssmh MRSAS_MAX_SGL, 1890275976Ssmh MRSAS_MAX_IO_SIZE, 1891275976Ssmh BUS_DMA_ALLOCNOW, 1892275976Ssmh busdma_lock_mutex, 1893275976Ssmh &sc->io_lock, 1894275976Ssmh &sc->data_tag)) { 1895275976Ssmh device_printf(sc->mrsas_dev, "Cannot create data dma tag\n"); 1896275976Ssmh return (ENOMEM); 1897275976Ssmh } 1898275976Ssmh return (0); 1899265555Sambrisko} 1900265555Sambrisko 1901265555Sambrisko/* 1902275976Ssmh * mrsas_addr_cb: Callback function of bus_dmamap_load() 1903275976Ssmh * input: callback argument, machine dependent type 1904275976Ssmh * that describes DMA segments, number of segments, error code 1905265555Sambrisko * 1906275976Ssmh * This function is for the driver to receive mapping information resultant of 1907275976Ssmh * the bus_dmamap_load(). The information is actually not being used, but the 1908275976Ssmh * address is saved anyway. 1909265555Sambrisko */ 1910265555Sambriskovoid 1911265555Sambriskomrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 1912265555Sambrisko{ 1913275976Ssmh bus_addr_t *addr; 1914275976Ssmh 1915275976Ssmh addr = arg; 1916275976Ssmh *addr = segs[0].ds_addr; 1917265555Sambrisko} 1918265555Sambrisko 1919265555Sambrisko/* 1920275976Ssmh * mrsas_setup_raidmap: Set up RAID map. 1921275976Ssmh * input: Adapter instance soft state 1922265555Sambrisko * 1923265555Sambrisko * Allocate DMA memory for the RAID maps and perform setup. 1924265555Sambrisko */ 1925275976Ssmhstatic int 1926275976Ssmhmrsas_setup_raidmap(struct mrsas_softc *sc) 1927275976Ssmh{ 1928275976Ssmh int i; 1929265555Sambrisko 1930275976Ssmh for (i = 0; i < 2; i++) { 1931275976Ssmh sc->ld_drv_map[i] = 1932275976Ssmh (void *)malloc(sc->drv_map_sz, M_MRSAS, M_NOWAIT); 1933275976Ssmh /* Do Error handling */ 1934275976Ssmh if (!sc->ld_drv_map[i]) { 1935275976Ssmh device_printf(sc->mrsas_dev, "Could not allocate memory for local map"); 1936275976Ssmh 1937275976Ssmh if (i == 1) 1938275976Ssmh free(sc->ld_drv_map[0], M_MRSAS); 1939275976Ssmh /* ABORT driver initialization */ 1940275976Ssmh goto ABORT; 1941275976Ssmh } 1942275976Ssmh } 1943275976Ssmh 1944275976Ssmh for (int i = 0; i < 2; i++) { 1945275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 1946275976Ssmh 4, 0, 1947275976Ssmh BUS_SPACE_MAXADDR_32BIT, 1948275976Ssmh BUS_SPACE_MAXADDR, 1949275976Ssmh NULL, NULL, 1950275976Ssmh sc->max_map_sz, 1951275976Ssmh 1, 1952275976Ssmh sc->max_map_sz, 1953275976Ssmh BUS_DMA_ALLOCNOW, 1954275976Ssmh NULL, NULL, 1955275976Ssmh &sc->raidmap_tag[i])) { 1956275976Ssmh device_printf(sc->mrsas_dev, 1957275976Ssmh "Cannot allocate raid map tag.\n"); 1958275976Ssmh return (ENOMEM); 1959275976Ssmh } 1960275976Ssmh if (bus_dmamem_alloc(sc->raidmap_tag[i], 1961275976Ssmh (void **)&sc->raidmap_mem[i], 1962275976Ssmh BUS_DMA_NOWAIT, &sc->raidmap_dmamap[i])) { 1963275976Ssmh device_printf(sc->mrsas_dev, 1964275976Ssmh "Cannot allocate raidmap memory.\n"); 1965275976Ssmh return (ENOMEM); 1966275976Ssmh } 1967275976Ssmh bzero(sc->raidmap_mem[i], sc->max_map_sz); 1968275976Ssmh 1969275976Ssmh if (bus_dmamap_load(sc->raidmap_tag[i], sc->raidmap_dmamap[i], 1970275976Ssmh sc->raidmap_mem[i], sc->max_map_sz, 1971275976Ssmh mrsas_addr_cb, &sc->raidmap_phys_addr[i], 1972275976Ssmh BUS_DMA_NOWAIT)) { 1973275976Ssmh device_printf(sc->mrsas_dev, "Cannot load raidmap memory.\n"); 1974275976Ssmh return (ENOMEM); 1975275976Ssmh } 1976275976Ssmh if (!sc->raidmap_mem[i]) { 1977275976Ssmh device_printf(sc->mrsas_dev, 1978275976Ssmh "Cannot allocate memory for raid map.\n"); 1979275976Ssmh return (ENOMEM); 1980275976Ssmh } 1981275976Ssmh } 1982275976Ssmh 1983275976Ssmh if (!mrsas_get_map_info(sc)) 1984275976Ssmh mrsas_sync_map_info(sc); 1985275976Ssmh 1986275976Ssmh return (0); 1987275976Ssmh 1988275976SsmhABORT: 1989275976Ssmh return (1); 1990265555Sambrisko} 1991265555Sambrisko 1992275976Ssmh/* 1993275976Ssmh * mrsas_init_fw: Initialize Firmware 1994275976Ssmh * input: Adapter soft state 1995265555Sambrisko * 1996275976Ssmh * Calls transition_to_ready() to make sure Firmware is in operational state and 1997275976Ssmh * calls mrsas_init_adapter() to send IOC_INIT command to Firmware. It 1998275976Ssmh * issues internal commands to get the controller info after the IOC_INIT 1999275976Ssmh * command response is received by Firmware. Note: code relating to 2000275976Ssmh * get_pdlist, get_ld_list and max_sectors are currently not being used, it 2001275976Ssmh * is left here as placeholder. 2002265555Sambrisko */ 2003284267Skadesaistatic int 2004275976Ssmhmrsas_init_fw(struct mrsas_softc *sc) 2005265555Sambrisko{ 2006265555Sambrisko 2007275976Ssmh int ret, loop, ocr = 0; 2008275976Ssmh u_int32_t max_sectors_1; 2009275976Ssmh u_int32_t max_sectors_2; 2010275976Ssmh u_int32_t tmp_sectors; 2011275976Ssmh u_int32_t scratch_pad_2; 2012275976Ssmh int msix_enable = 0; 2013275976Ssmh int fw_msix_count = 0; 2014265555Sambrisko 2015275976Ssmh /* Make sure Firmware is ready */ 2016275976Ssmh ret = mrsas_transition_to_ready(sc, ocr); 2017275976Ssmh if (ret != SUCCESS) { 2018275976Ssmh return (ret); 2019265555Sambrisko } 2020275976Ssmh /* MSI-x index 0- reply post host index register */ 2021275976Ssmh sc->msix_reg_offset[0] = MPI2_REPLY_POST_HOST_INDEX_OFFSET; 2022275976Ssmh /* Check if MSI-X is supported while in ready state */ 2023275976Ssmh msix_enable = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)) & 0x4000000) >> 0x1a; 2024265555Sambrisko 2025275976Ssmh if (msix_enable) { 2026275976Ssmh scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2027275976Ssmh outbound_scratch_pad_2)); 2028265555Sambrisko 2029275976Ssmh /* Check max MSI-X vectors */ 2030275976Ssmh if (sc->device_id == MRSAS_TBOLT) { 2031275976Ssmh sc->msix_vectors = (scratch_pad_2 2032275976Ssmh & MR_MAX_REPLY_QUEUES_OFFSET) + 1; 2033275976Ssmh fw_msix_count = sc->msix_vectors; 2034275976Ssmh } else { 2035275976Ssmh /* Invader/Fury supports 96 MSI-X vectors */ 2036275976Ssmh sc->msix_vectors = ((scratch_pad_2 2037275976Ssmh & MR_MAX_REPLY_QUEUES_EXT_OFFSET) 2038275976Ssmh >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; 2039275976Ssmh fw_msix_count = sc->msix_vectors; 2040275976Ssmh 2041275976Ssmh for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; 2042275976Ssmh loop++) { 2043275976Ssmh sc->msix_reg_offset[loop] = 2044275976Ssmh MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET + 2045275976Ssmh (loop * 0x10); 2046275976Ssmh } 2047275976Ssmh } 2048275976Ssmh 2049275976Ssmh /* Don't bother allocating more MSI-X vectors than cpus */ 2050275976Ssmh sc->msix_vectors = min(sc->msix_vectors, 2051275976Ssmh mp_ncpus); 2052275976Ssmh 2053275976Ssmh /* Allocate MSI-x vectors */ 2054275976Ssmh if (mrsas_allocate_msix(sc) == SUCCESS) 2055275976Ssmh sc->msix_enable = 1; 2056275976Ssmh else 2057275976Ssmh sc->msix_enable = 0; 2058275976Ssmh 2059275976Ssmh device_printf(sc->mrsas_dev, "FW supports <%d> MSIX vector," 2060275976Ssmh "Online CPU %d Current MSIX <%d>\n", 2061275976Ssmh fw_msix_count, mp_ncpus, sc->msix_vectors); 2062265555Sambrisko } 2063275976Ssmh if (mrsas_init_adapter(sc) != SUCCESS) { 2064275976Ssmh device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n"); 2065275976Ssmh return (1); 2066275976Ssmh } 2067275976Ssmh /* Allocate internal commands for pass-thru */ 2068275976Ssmh if (mrsas_alloc_mfi_cmds(sc) != SUCCESS) { 2069275976Ssmh device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n"); 2070275976Ssmh return (1); 2071275976Ssmh } 2072284267Skadesai sc->ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT); 2073284267Skadesai if (!sc->ctrl_info) { 2074284267Skadesai device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n"); 2075284267Skadesai return (1); 2076284267Skadesai } 2077275976Ssmh /* 2078275976Ssmh * Get the controller info from FW, so that the MAX VD support 2079275976Ssmh * availability can be decided. 2080275976Ssmh */ 2081284267Skadesai if (mrsas_get_ctrl_info(sc)) { 2082275976Ssmh device_printf(sc->mrsas_dev, "Unable to get FW ctrl_info.\n"); 2083284267Skadesai return (1); 2084275976Ssmh } 2085284267Skadesai sc->secure_jbod_support = 2086284267Skadesai (u_int8_t)sc->ctrl_info->adapterOperations3.supportSecurityonJBOD; 2087265555Sambrisko 2088284267Skadesai if (sc->secure_jbod_support) 2089284267Skadesai device_printf(sc->mrsas_dev, "FW supports SED \n"); 2090284267Skadesai 2091275976Ssmh if (mrsas_setup_raidmap(sc) != SUCCESS) { 2092275976Ssmh device_printf(sc->mrsas_dev, "Set up RAID map failed.\n"); 2093275976Ssmh return (1); 2094275976Ssmh } 2095275976Ssmh /* For pass-thru, get PD/LD list and controller info */ 2096275976Ssmh memset(sc->pd_list, 0, 2097275976Ssmh MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); 2098275976Ssmh mrsas_get_pd_list(sc); 2099265555Sambrisko 2100275976Ssmh memset(sc->ld_ids, 0xff, MRSAS_MAX_LD_IDS); 2101275976Ssmh mrsas_get_ld_list(sc); 2102265555Sambrisko 2103275976Ssmh /* 2104275976Ssmh * Compute the max allowed sectors per IO: The controller info has 2105275976Ssmh * two limits on max sectors. Driver should use the minimum of these 2106275976Ssmh * two. 2107275976Ssmh * 2108275976Ssmh * 1 << stripe_sz_ops.min = max sectors per strip 2109275976Ssmh * 2110275976Ssmh * Note that older firmwares ( < FW ver 30) didn't report information to 2111275976Ssmh * calculate max_sectors_1. So the number ended up as zero always. 2112275976Ssmh */ 2113275976Ssmh tmp_sectors = 0; 2114284267Skadesai max_sectors_1 = (1 << sc->ctrl_info->stripe_sz_ops.min) * 2115284267Skadesai sc->ctrl_info->max_strips_per_io; 2116284267Skadesai max_sectors_2 = sc->ctrl_info->max_request_size; 2117275976Ssmh tmp_sectors = min(max_sectors_1, max_sectors_2); 2118275976Ssmh sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512; 2119265555Sambrisko 2120275976Ssmh if (tmp_sectors && (sc->max_sectors_per_req > tmp_sectors)) 2121275976Ssmh sc->max_sectors_per_req = tmp_sectors; 2122265555Sambrisko 2123275976Ssmh sc->disableOnlineCtrlReset = 2124284267Skadesai sc->ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; 2125275976Ssmh sc->UnevenSpanSupport = 2126284267Skadesai sc->ctrl_info->adapterOperations2.supportUnevenSpans; 2127275976Ssmh if (sc->UnevenSpanSupport) { 2128275976Ssmh device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n\n", 2129275976Ssmh sc->UnevenSpanSupport); 2130265555Sambrisko 2131275976Ssmh if (MR_ValidateMapInfo(sc)) 2132275976Ssmh sc->fast_path_io = 1; 2133275976Ssmh else 2134275976Ssmh sc->fast_path_io = 0; 2135275976Ssmh } 2136275976Ssmh return (0); 2137265555Sambrisko} 2138265555Sambrisko 2139275976Ssmh/* 2140275976Ssmh * mrsas_init_adapter: Initializes the adapter/controller 2141275976Ssmh * input: Adapter soft state 2142265555Sambrisko * 2143275976Ssmh * Prepares for the issuing of the IOC Init cmd to FW for initializing the 2144275976Ssmh * ROC/controller. The FW register is read to determined the number of 2145265555Sambrisko * commands that is supported. All memory allocations for IO is based on 2146275976Ssmh * max_cmd. Appropriate calculations are performed in this function. 2147265555Sambrisko */ 2148275976Ssmhint 2149275976Ssmhmrsas_init_adapter(struct mrsas_softc *sc) 2150265555Sambrisko{ 2151275976Ssmh uint32_t status; 2152275976Ssmh u_int32_t max_cmd; 2153275976Ssmh int ret; 2154275976Ssmh int i = 0; 2155265555Sambrisko 2156275976Ssmh /* Read FW status register */ 2157275976Ssmh status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)); 2158265555Sambrisko 2159275976Ssmh /* Get operational params from status register */ 2160275976Ssmh sc->max_fw_cmds = status & MRSAS_FWSTATE_MAXCMD_MASK; 2161265555Sambrisko 2162275976Ssmh /* Decrement the max supported by 1, to correlate with FW */ 2163275976Ssmh sc->max_fw_cmds = sc->max_fw_cmds - 1; 2164275976Ssmh max_cmd = sc->max_fw_cmds; 2165265555Sambrisko 2166275976Ssmh /* Determine allocation size of command frames */ 2167284267Skadesai sc->reply_q_depth = ((max_cmd + 1 + 15) / 16 * 16) * 2; 2168275976Ssmh sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd; 2169275976Ssmh sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth); 2170275976Ssmh sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1)); 2171275976Ssmh sc->chain_frames_alloc_sz = 1024 * max_cmd; 2172275976Ssmh sc->max_sge_in_main_msg = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - 2173275976Ssmh offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL)) / 16; 2174265555Sambrisko 2175275976Ssmh sc->max_sge_in_chain = MRSAS_MAX_SZ_CHAIN_FRAME / sizeof(MPI2_SGE_IO_UNION); 2176275976Ssmh sc->max_num_sge = sc->max_sge_in_main_msg + sc->max_sge_in_chain - 2; 2177265555Sambrisko 2178275976Ssmh /* Used for pass thru MFI frame (DCMD) */ 2179275976Ssmh sc->chain_offset_mfi_pthru = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 16; 2180265555Sambrisko 2181275976Ssmh sc->chain_offset_io_request = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - 2182275976Ssmh sizeof(MPI2_SGE_IO_UNION)) / 16; 2183265555Sambrisko 2184275976Ssmh int count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 2185265555Sambrisko 2186275976Ssmh for (i = 0; i < count; i++) 2187275976Ssmh sc->last_reply_idx[i] = 0; 2188265555Sambrisko 2189275976Ssmh ret = mrsas_alloc_mem(sc); 2190275976Ssmh if (ret != SUCCESS) 2191275976Ssmh return (ret); 2192265555Sambrisko 2193275976Ssmh ret = mrsas_alloc_mpt_cmds(sc); 2194275976Ssmh if (ret != SUCCESS) 2195275976Ssmh return (ret); 2196275976Ssmh 2197275976Ssmh ret = mrsas_ioc_init(sc); 2198275976Ssmh if (ret != SUCCESS) 2199275976Ssmh return (ret); 2200275976Ssmh 2201275976Ssmh return (0); 2202265555Sambrisko} 2203265555Sambrisko 2204275976Ssmh/* 2205275976Ssmh * mrsas_alloc_ioc_cmd: Allocates memory for IOC Init command 2206275976Ssmh * input: Adapter soft state 2207265555Sambrisko * 2208265555Sambrisko * Allocates for the IOC Init cmd to FW to initialize the ROC/controller. 2209265555Sambrisko */ 2210275976Ssmhint 2211275976Ssmhmrsas_alloc_ioc_cmd(struct mrsas_softc *sc) 2212265555Sambrisko{ 2213275976Ssmh int ioc_init_size; 2214265555Sambrisko 2215275976Ssmh /* Allocate IOC INIT command */ 2216275976Ssmh ioc_init_size = 1024 + sizeof(MPI2_IOC_INIT_REQUEST); 2217275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 2218275976Ssmh 1, 0, 2219275976Ssmh BUS_SPACE_MAXADDR_32BIT, 2220275976Ssmh BUS_SPACE_MAXADDR, 2221275976Ssmh NULL, NULL, 2222275976Ssmh ioc_init_size, 2223275976Ssmh 1, 2224275976Ssmh ioc_init_size, 2225275976Ssmh BUS_DMA_ALLOCNOW, 2226275976Ssmh NULL, NULL, 2227275976Ssmh &sc->ioc_init_tag)) { 2228275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate ioc init tag\n"); 2229275976Ssmh return (ENOMEM); 2230275976Ssmh } 2231275976Ssmh if (bus_dmamem_alloc(sc->ioc_init_tag, (void **)&sc->ioc_init_mem, 2232275976Ssmh BUS_DMA_NOWAIT, &sc->ioc_init_dmamap)) { 2233275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate ioc init cmd mem\n"); 2234275976Ssmh return (ENOMEM); 2235275976Ssmh } 2236275976Ssmh bzero(sc->ioc_init_mem, ioc_init_size); 2237275976Ssmh if (bus_dmamap_load(sc->ioc_init_tag, sc->ioc_init_dmamap, 2238275976Ssmh sc->ioc_init_mem, ioc_init_size, mrsas_addr_cb, 2239275976Ssmh &sc->ioc_init_phys_mem, BUS_DMA_NOWAIT)) { 2240275976Ssmh device_printf(sc->mrsas_dev, "Cannot load ioc init cmd mem\n"); 2241275976Ssmh return (ENOMEM); 2242275976Ssmh } 2243275976Ssmh return (0); 2244265555Sambrisko} 2245265555Sambrisko 2246275976Ssmh/* 2247275976Ssmh * mrsas_free_ioc_cmd: Allocates memory for IOC Init command 2248275976Ssmh * input: Adapter soft state 2249265555Sambrisko * 2250265555Sambrisko * Deallocates memory of the IOC Init cmd. 2251265555Sambrisko */ 2252275976Ssmhvoid 2253275976Ssmhmrsas_free_ioc_cmd(struct mrsas_softc *sc) 2254265555Sambrisko{ 2255275976Ssmh if (sc->ioc_init_phys_mem) 2256275976Ssmh bus_dmamap_unload(sc->ioc_init_tag, sc->ioc_init_dmamap); 2257275976Ssmh if (sc->ioc_init_mem != NULL) 2258275976Ssmh bus_dmamem_free(sc->ioc_init_tag, sc->ioc_init_mem, sc->ioc_init_dmamap); 2259275976Ssmh if (sc->ioc_init_tag != NULL) 2260275976Ssmh bus_dma_tag_destroy(sc->ioc_init_tag); 2261265555Sambrisko} 2262265555Sambrisko 2263275976Ssmh/* 2264275976Ssmh * mrsas_ioc_init: Sends IOC Init command to FW 2265275976Ssmh * input: Adapter soft state 2266265555Sambrisko * 2267265555Sambrisko * Issues the IOC Init cmd to FW to initialize the ROC/controller. 2268265555Sambrisko */ 2269275976Ssmhint 2270275976Ssmhmrsas_ioc_init(struct mrsas_softc *sc) 2271265555Sambrisko{ 2272275976Ssmh struct mrsas_init_frame *init_frame; 2273275976Ssmh pMpi2IOCInitRequest_t IOCInitMsg; 2274275976Ssmh MRSAS_REQUEST_DESCRIPTOR_UNION req_desc; 2275275976Ssmh u_int8_t max_wait = MRSAS_IOC_INIT_WAIT_TIME; 2276275976Ssmh bus_addr_t phys_addr; 2277275976Ssmh int i, retcode = 0; 2278265555Sambrisko 2279275976Ssmh /* Allocate memory for the IOC INIT command */ 2280275976Ssmh if (mrsas_alloc_ioc_cmd(sc)) { 2281275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate IOC command.\n"); 2282275976Ssmh return (1); 2283275976Ssmh } 2284275976Ssmh IOCInitMsg = (pMpi2IOCInitRequest_t)(((char *)sc->ioc_init_mem) + 1024); 2285275976Ssmh IOCInitMsg->Function = MPI2_FUNCTION_IOC_INIT; 2286275976Ssmh IOCInitMsg->WhoInit = MPI2_WHOINIT_HOST_DRIVER; 2287275976Ssmh IOCInitMsg->MsgVersion = MPI2_VERSION; 2288275976Ssmh IOCInitMsg->HeaderVersion = MPI2_HEADER_VERSION; 2289275976Ssmh IOCInitMsg->SystemRequestFrameSize = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4; 2290275976Ssmh IOCInitMsg->ReplyDescriptorPostQueueDepth = sc->reply_q_depth; 2291275976Ssmh IOCInitMsg->ReplyDescriptorPostQueueAddress = sc->reply_desc_phys_addr; 2292275976Ssmh IOCInitMsg->SystemRequestFrameBaseAddress = sc->io_request_phys_addr; 2293275976Ssmh IOCInitMsg->HostMSIxVectors = (sc->msix_vectors > 0 ? sc->msix_vectors : 0); 2294265555Sambrisko 2295275976Ssmh init_frame = (struct mrsas_init_frame *)sc->ioc_init_mem; 2296275976Ssmh init_frame->cmd = MFI_CMD_INIT; 2297275976Ssmh init_frame->cmd_status = 0xFF; 2298275976Ssmh init_frame->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 2299265555Sambrisko 2300275976Ssmh /* driver support Extended MSIX */ 2301275976Ssmh if ((sc->device_id == MRSAS_INVADER) || 2302275976Ssmh (sc->device_id == MRSAS_FURY)) { 2303275976Ssmh init_frame->driver_operations. 2304275976Ssmh mfi_capabilities.support_additional_msix = 1; 2305275976Ssmh } 2306275976Ssmh if (sc->verbuf_mem) { 2307275976Ssmh snprintf((char *)sc->verbuf_mem, strlen(MRSAS_VERSION) + 2, "%s\n", 2308275976Ssmh MRSAS_VERSION); 2309275976Ssmh init_frame->driver_ver_lo = (bus_addr_t)sc->verbuf_phys_addr; 2310275976Ssmh init_frame->driver_ver_hi = 0; 2311275976Ssmh } 2312284267Skadesai init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb = 1; 2313275976Ssmh init_frame->driver_operations.mfi_capabilities.support_max_255lds = 1; 2314284267Skadesai init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw = 1; 2315275976Ssmh phys_addr = (bus_addr_t)sc->ioc_init_phys_mem + 1024; 2316275976Ssmh init_frame->queue_info_new_phys_addr_lo = phys_addr; 2317275976Ssmh init_frame->data_xfer_len = sizeof(Mpi2IOCInitRequest_t); 2318265555Sambrisko 2319275976Ssmh req_desc.addr.Words = (bus_addr_t)sc->ioc_init_phys_mem; 2320275976Ssmh req_desc.MFAIo.RequestFlags = 2321275976Ssmh (MRSAS_REQ_DESCRIPT_FLAGS_MFA << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 2322265555Sambrisko 2323275976Ssmh mrsas_disable_intr(sc); 2324275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "Issuing IOC INIT command to FW.\n"); 2325275976Ssmh mrsas_fire_cmd(sc, req_desc.addr.u.low, req_desc.addr.u.high); 2326265555Sambrisko 2327275976Ssmh /* 2328275976Ssmh * Poll response timer to wait for Firmware response. While this 2329275976Ssmh * timer with the DELAY call could block CPU, the time interval for 2330275976Ssmh * this is only 1 millisecond. 2331275976Ssmh */ 2332275976Ssmh if (init_frame->cmd_status == 0xFF) { 2333275976Ssmh for (i = 0; i < (max_wait * 1000); i++) { 2334275976Ssmh if (init_frame->cmd_status == 0xFF) 2335275976Ssmh DELAY(1000); 2336275976Ssmh else 2337275976Ssmh break; 2338275976Ssmh } 2339275976Ssmh } 2340275976Ssmh if (init_frame->cmd_status == 0) 2341275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2342275976Ssmh "IOC INIT response received from FW.\n"); 2343275976Ssmh else { 2344275976Ssmh if (init_frame->cmd_status == 0xFF) 2345275976Ssmh device_printf(sc->mrsas_dev, "IOC Init timed out after %d seconds.\n", max_wait); 2346275976Ssmh else 2347275976Ssmh device_printf(sc->mrsas_dev, "IOC Init failed, status = 0x%x\n", init_frame->cmd_status); 2348275976Ssmh retcode = 1; 2349275976Ssmh } 2350265555Sambrisko 2351275976Ssmh mrsas_free_ioc_cmd(sc); 2352275976Ssmh return (retcode); 2353265555Sambrisko} 2354265555Sambrisko 2355275976Ssmh/* 2356275976Ssmh * mrsas_alloc_mpt_cmds: Allocates the command packets 2357275976Ssmh * input: Adapter instance soft state 2358265555Sambrisko * 2359265555Sambrisko * This function allocates the internal commands for IOs. Each command that is 2360275976Ssmh * issued to FW is wrapped in a local data structure called mrsas_mpt_cmd. An 2361275976Ssmh * array is allocated with mrsas_mpt_cmd context. The free commands are 2362265555Sambrisko * maintained in a linked list (cmd pool). SMID value range is from 1 to 2363265555Sambrisko * max_fw_cmds. 2364265555Sambrisko */ 2365275976Ssmhint 2366275976Ssmhmrsas_alloc_mpt_cmds(struct mrsas_softc *sc) 2367265555Sambrisko{ 2368275976Ssmh int i, j; 2369275976Ssmh u_int32_t max_cmd, count; 2370275976Ssmh struct mrsas_mpt_cmd *cmd; 2371275976Ssmh pMpi2ReplyDescriptorsUnion_t reply_desc; 2372275976Ssmh u_int32_t offset, chain_offset, sense_offset; 2373275976Ssmh bus_addr_t io_req_base_phys, chain_frame_base_phys, sense_base_phys; 2374275976Ssmh u_int8_t *io_req_base, *chain_frame_base, *sense_base; 2375265555Sambrisko 2376275976Ssmh max_cmd = sc->max_fw_cmds; 2377265555Sambrisko 2378275976Ssmh sc->req_desc = malloc(sc->request_alloc_sz, M_MRSAS, M_NOWAIT); 2379275976Ssmh if (!sc->req_desc) { 2380275976Ssmh device_printf(sc->mrsas_dev, "Out of memory, cannot alloc req desc\n"); 2381275976Ssmh return (ENOMEM); 2382275976Ssmh } 2383275976Ssmh memset(sc->req_desc, 0, sc->request_alloc_sz); 2384265555Sambrisko 2385275976Ssmh /* 2386275976Ssmh * sc->mpt_cmd_list is an array of struct mrsas_mpt_cmd pointers. 2387275976Ssmh * Allocate the dynamic array first and then allocate individual 2388275976Ssmh * commands. 2389275976Ssmh */ 2390275976Ssmh sc->mpt_cmd_list = malloc(sizeof(struct mrsas_mpt_cmd *) * max_cmd, M_MRSAS, M_NOWAIT); 2391275976Ssmh if (!sc->mpt_cmd_list) { 2392275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc memory for mpt_cmd_list.\n"); 2393275976Ssmh return (ENOMEM); 2394275976Ssmh } 2395275976Ssmh memset(sc->mpt_cmd_list, 0, sizeof(struct mrsas_mpt_cmd *) * max_cmd); 2396275976Ssmh for (i = 0; i < max_cmd; i++) { 2397275976Ssmh sc->mpt_cmd_list[i] = malloc(sizeof(struct mrsas_mpt_cmd), 2398275976Ssmh M_MRSAS, M_NOWAIT); 2399275976Ssmh if (!sc->mpt_cmd_list[i]) { 2400275976Ssmh for (j = 0; j < i; j++) 2401275976Ssmh free(sc->mpt_cmd_list[j], M_MRSAS); 2402275976Ssmh free(sc->mpt_cmd_list, M_MRSAS); 2403275976Ssmh sc->mpt_cmd_list = NULL; 2404275976Ssmh return (ENOMEM); 2405275976Ssmh } 2406275976Ssmh } 2407265555Sambrisko 2408275976Ssmh io_req_base = (u_int8_t *)sc->io_request_mem + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; 2409275976Ssmh io_req_base_phys = (bus_addr_t)sc->io_request_phys_addr + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; 2410275976Ssmh chain_frame_base = (u_int8_t *)sc->chain_frame_mem; 2411275976Ssmh chain_frame_base_phys = (bus_addr_t)sc->chain_frame_phys_addr; 2412275976Ssmh sense_base = (u_int8_t *)sc->sense_mem; 2413275976Ssmh sense_base_phys = (bus_addr_t)sc->sense_phys_addr; 2414275976Ssmh for (i = 0; i < max_cmd; i++) { 2415275976Ssmh cmd = sc->mpt_cmd_list[i]; 2416275976Ssmh offset = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i; 2417275976Ssmh chain_offset = 1024 * i; 2418275976Ssmh sense_offset = MRSAS_SENSE_LEN * i; 2419275976Ssmh memset(cmd, 0, sizeof(struct mrsas_mpt_cmd)); 2420275976Ssmh cmd->index = i + 1; 2421275976Ssmh cmd->ccb_ptr = NULL; 2422275976Ssmh callout_init(&cmd->cm_callout, 0); 2423275976Ssmh cmd->sync_cmd_idx = (u_int32_t)MRSAS_ULONG_MAX; 2424275976Ssmh cmd->sc = sc; 2425275976Ssmh cmd->io_request = (MRSAS_RAID_SCSI_IO_REQUEST *) (io_req_base + offset); 2426275976Ssmh memset(cmd->io_request, 0, sizeof(MRSAS_RAID_SCSI_IO_REQUEST)); 2427275976Ssmh cmd->io_request_phys_addr = io_req_base_phys + offset; 2428275976Ssmh cmd->chain_frame = (MPI2_SGE_IO_UNION *) (chain_frame_base + chain_offset); 2429275976Ssmh cmd->chain_frame_phys_addr = chain_frame_base_phys + chain_offset; 2430275976Ssmh cmd->sense = sense_base + sense_offset; 2431275976Ssmh cmd->sense_phys_addr = sense_base_phys + sense_offset; 2432275976Ssmh if (bus_dmamap_create(sc->data_tag, 0, &cmd->data_dmamap)) { 2433275976Ssmh return (FAIL); 2434275976Ssmh } 2435275976Ssmh TAILQ_INSERT_TAIL(&(sc->mrsas_mpt_cmd_list_head), cmd, next); 2436275976Ssmh } 2437275976Ssmh 2438275976Ssmh /* Initialize reply descriptor array to 0xFFFFFFFF */ 2439275976Ssmh reply_desc = sc->reply_desc_mem; 2440275976Ssmh count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 2441275976Ssmh for (i = 0; i < sc->reply_q_depth * count; i++, reply_desc++) { 2442275976Ssmh reply_desc->Words = MRSAS_ULONG_MAX; 2443275976Ssmh } 2444275976Ssmh return (0); 2445265555Sambrisko} 2446265555Sambrisko 2447275976Ssmh/* 2448275976Ssmh * mrsas_fire_cmd: Sends command to FW 2449275976Ssmh * input: Adapter softstate 2450275976Ssmh * request descriptor address low 2451275976Ssmh * request descriptor address high 2452265555Sambrisko * 2453275976Ssmh * This functions fires the command to Firmware by writing to the 2454265555Sambrisko * inbound_low_queue_port and inbound_high_queue_port. 2455265555Sambrisko */ 2456284267Skadesaivoid 2457275976Ssmhmrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, 2458275976Ssmh u_int32_t req_desc_hi) 2459275976Ssmh{ 2460275976Ssmh mtx_lock(&sc->pci_lock); 2461275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_low_queue_port), 2462275976Ssmh req_desc_lo); 2463275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_high_queue_port), 2464275976Ssmh req_desc_hi); 2465275976Ssmh mtx_unlock(&sc->pci_lock); 2466265555Sambrisko} 2467265555Sambrisko 2468275976Ssmh/* 2469275976Ssmh * mrsas_transition_to_ready: Move FW to Ready state input: 2470275976Ssmh * Adapter instance soft state 2471265555Sambrisko * 2472275976Ssmh * During the initialization, FW passes can potentially be in any one of several 2473275976Ssmh * possible states. If the FW in operational, waiting-for-handshake states, 2474275976Ssmh * driver must take steps to bring it to ready state. Otherwise, it has to 2475275976Ssmh * wait for the ready state. 2476265555Sambrisko */ 2477275976Ssmhint 2478275976Ssmhmrsas_transition_to_ready(struct mrsas_softc *sc, int ocr) 2479265555Sambrisko{ 2480275976Ssmh int i; 2481275976Ssmh u_int8_t max_wait; 2482275976Ssmh u_int32_t val, fw_state; 2483275976Ssmh u_int32_t cur_state; 2484275976Ssmh u_int32_t abs_state, curr_abs_state; 2485265555Sambrisko 2486275976Ssmh val = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)); 2487275976Ssmh fw_state = val & MFI_STATE_MASK; 2488275976Ssmh max_wait = MRSAS_RESET_WAIT_TIME; 2489265555Sambrisko 2490275976Ssmh if (fw_state != MFI_STATE_READY) 2491275976Ssmh device_printf(sc->mrsas_dev, "Waiting for FW to come to ready state\n"); 2492265555Sambrisko 2493275976Ssmh while (fw_state != MFI_STATE_READY) { 2494275976Ssmh abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)); 2495275976Ssmh switch (fw_state) { 2496275976Ssmh case MFI_STATE_FAULT: 2497275976Ssmh device_printf(sc->mrsas_dev, "FW is in FAULT state!!\n"); 2498275976Ssmh if (ocr) { 2499275976Ssmh cur_state = MFI_STATE_FAULT; 2500275976Ssmh break; 2501275976Ssmh } else 2502275976Ssmh return -ENODEV; 2503275976Ssmh case MFI_STATE_WAIT_HANDSHAKE: 2504275976Ssmh /* Set the CLR bit in inbound doorbell */ 2505275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), 2506275976Ssmh MFI_INIT_CLEAR_HANDSHAKE | MFI_INIT_HOTPLUG); 2507275976Ssmh cur_state = MFI_STATE_WAIT_HANDSHAKE; 2508275976Ssmh break; 2509275976Ssmh case MFI_STATE_BOOT_MESSAGE_PENDING: 2510275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), 2511275976Ssmh MFI_INIT_HOTPLUG); 2512275976Ssmh cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; 2513275976Ssmh break; 2514275976Ssmh case MFI_STATE_OPERATIONAL: 2515275976Ssmh /* 2516275976Ssmh * Bring it to READY state; assuming max wait 10 2517275976Ssmh * secs 2518275976Ssmh */ 2519275976Ssmh mrsas_disable_intr(sc); 2520275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_RESET_FLAGS); 2521275976Ssmh for (i = 0; i < max_wait * 1000; i++) { 2522275976Ssmh if (mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)) & 1) 2523275976Ssmh DELAY(1000); 2524275976Ssmh else 2525275976Ssmh break; 2526275976Ssmh } 2527275976Ssmh cur_state = MFI_STATE_OPERATIONAL; 2528275976Ssmh break; 2529275976Ssmh case MFI_STATE_UNDEFINED: 2530275976Ssmh /* 2531275976Ssmh * This state should not last for more than 2 2532275976Ssmh * seconds 2533275976Ssmh */ 2534275976Ssmh cur_state = MFI_STATE_UNDEFINED; 2535275976Ssmh break; 2536275976Ssmh case MFI_STATE_BB_INIT: 2537275976Ssmh cur_state = MFI_STATE_BB_INIT; 2538275976Ssmh break; 2539275976Ssmh case MFI_STATE_FW_INIT: 2540275976Ssmh cur_state = MFI_STATE_FW_INIT; 2541275976Ssmh break; 2542275976Ssmh case MFI_STATE_FW_INIT_2: 2543275976Ssmh cur_state = MFI_STATE_FW_INIT_2; 2544275976Ssmh break; 2545275976Ssmh case MFI_STATE_DEVICE_SCAN: 2546275976Ssmh cur_state = MFI_STATE_DEVICE_SCAN; 2547275976Ssmh break; 2548275976Ssmh case MFI_STATE_FLUSH_CACHE: 2549275976Ssmh cur_state = MFI_STATE_FLUSH_CACHE; 2550275976Ssmh break; 2551275976Ssmh default: 2552275976Ssmh device_printf(sc->mrsas_dev, "Unknown state 0x%x\n", fw_state); 2553265555Sambrisko return -ENODEV; 2554275976Ssmh } 2555265555Sambrisko 2556275976Ssmh /* 2557275976Ssmh * The cur_state should not last for more than max_wait secs 2558275976Ssmh */ 2559275976Ssmh for (i = 0; i < (max_wait * 1000); i++) { 2560275976Ssmh fw_state = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2561275976Ssmh outbound_scratch_pad)) & MFI_STATE_MASK); 2562275976Ssmh curr_abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2563275976Ssmh outbound_scratch_pad)); 2564275976Ssmh if (abs_state == curr_abs_state) 2565275976Ssmh DELAY(1000); 2566275976Ssmh else 2567275976Ssmh break; 2568275976Ssmh } 2569265555Sambrisko 2570275976Ssmh /* 2571275976Ssmh * Return error if fw_state hasn't changed after max_wait 2572275976Ssmh */ 2573275976Ssmh if (curr_abs_state == abs_state) { 2574275976Ssmh device_printf(sc->mrsas_dev, "FW state [%d] hasn't changed " 2575275976Ssmh "in %d secs\n", fw_state, max_wait); 2576275976Ssmh return -ENODEV; 2577275976Ssmh } 2578265555Sambrisko } 2579275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "FW now in Ready state\n"); 2580275976Ssmh return 0; 2581265555Sambrisko} 2582265555Sambrisko 2583275976Ssmh/* 2584275976Ssmh * mrsas_get_mfi_cmd: Get a cmd from free command pool 2585275976Ssmh * input: Adapter soft state 2586265555Sambrisko * 2587265555Sambrisko * This function removes an MFI command from the command list. 2588265555Sambrisko */ 2589275976Ssmhstruct mrsas_mfi_cmd * 2590275976Ssmhmrsas_get_mfi_cmd(struct mrsas_softc *sc) 2591265555Sambrisko{ 2592275976Ssmh struct mrsas_mfi_cmd *cmd = NULL; 2593275976Ssmh 2594275976Ssmh mtx_lock(&sc->mfi_cmd_pool_lock); 2595275976Ssmh if (!TAILQ_EMPTY(&sc->mrsas_mfi_cmd_list_head)) { 2596275976Ssmh cmd = TAILQ_FIRST(&sc->mrsas_mfi_cmd_list_head); 2597275976Ssmh TAILQ_REMOVE(&sc->mrsas_mfi_cmd_list_head, cmd, next); 2598275976Ssmh } 2599275976Ssmh mtx_unlock(&sc->mfi_cmd_pool_lock); 2600275976Ssmh 2601275976Ssmh return cmd; 2602265555Sambrisko} 2603265555Sambrisko 2604275976Ssmh/* 2605275976Ssmh * mrsas_ocr_thread: Thread to handle OCR/Kill Adapter. 2606275976Ssmh * input: Adapter Context. 2607265555Sambrisko * 2608275976Ssmh * This function will check FW status register and flag do_timeout_reset flag. 2609275976Ssmh * It will do OCR/Kill adapter if FW is in fault state or IO timed out has 2610275976Ssmh * trigger reset. 2611265555Sambrisko */ 2612265555Sambriskostatic void 2613265555Sambriskomrsas_ocr_thread(void *arg) 2614265555Sambrisko{ 2615275976Ssmh struct mrsas_softc *sc; 2616275976Ssmh u_int32_t fw_status, fw_state; 2617265555Sambrisko 2618275976Ssmh sc = (struct mrsas_softc *)arg; 2619275976Ssmh 2620275976Ssmh mrsas_dprint(sc, MRSAS_TRACE, "%s\n", __func__); 2621275976Ssmh 2622275976Ssmh sc->ocr_thread_active = 1; 2623275976Ssmh mtx_lock(&sc->sim_lock); 2624275976Ssmh for (;;) { 2625275976Ssmh /* Sleep for 1 second and check the queue status */ 2626275976Ssmh msleep(&sc->ocr_chan, &sc->sim_lock, PRIBIO, 2627275976Ssmh "mrsas_ocr", sc->mrsas_fw_fault_check_delay * hz); 2628275976Ssmh if (sc->remove_in_progress) { 2629275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2630275976Ssmh "Exit due to shutdown from %s\n", __func__); 2631275976Ssmh break; 2632275976Ssmh } 2633275976Ssmh fw_status = mrsas_read_reg(sc, 2634275976Ssmh offsetof(mrsas_reg_set, outbound_scratch_pad)); 2635275976Ssmh fw_state = fw_status & MFI_STATE_MASK; 2636275976Ssmh if (fw_state == MFI_STATE_FAULT || sc->do_timedout_reset) { 2637275976Ssmh device_printf(sc->mrsas_dev, "OCR started due to %s!\n", 2638275976Ssmh sc->do_timedout_reset ? "IO Timeout" : 2639275976Ssmh "FW fault detected"); 2640275976Ssmh mtx_lock_spin(&sc->ioctl_lock); 2641275976Ssmh sc->reset_in_progress = 1; 2642275976Ssmh sc->reset_count++; 2643275976Ssmh mtx_unlock_spin(&sc->ioctl_lock); 2644275976Ssmh mrsas_xpt_freeze(sc); 2645275976Ssmh mrsas_reset_ctrl(sc); 2646275976Ssmh mrsas_xpt_release(sc); 2647275976Ssmh sc->reset_in_progress = 0; 2648275976Ssmh sc->do_timedout_reset = 0; 2649275976Ssmh } 2650275976Ssmh } 2651275976Ssmh mtx_unlock(&sc->sim_lock); 2652275976Ssmh sc->ocr_thread_active = 0; 2653275976Ssmh mrsas_kproc_exit(0); 2654265555Sambrisko} 2655265555Sambrisko 2656275976Ssmh/* 2657275976Ssmh * mrsas_reset_reply_desc: Reset Reply descriptor as part of OCR. 2658275976Ssmh * input: Adapter Context. 2659265555Sambrisko * 2660275976Ssmh * This function will clear reply descriptor so that post OCR driver and FW will 2661275976Ssmh * lost old history. 2662265555Sambrisko */ 2663275976Ssmhvoid 2664275976Ssmhmrsas_reset_reply_desc(struct mrsas_softc *sc) 2665265555Sambrisko{ 2666275976Ssmh int i, count; 2667275976Ssmh pMpi2ReplyDescriptorsUnion_t reply_desc; 2668265555Sambrisko 2669275976Ssmh count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 2670275976Ssmh for (i = 0; i < count; i++) 2671275976Ssmh sc->last_reply_idx[i] = 0; 2672275976Ssmh 2673275976Ssmh reply_desc = sc->reply_desc_mem; 2674275976Ssmh for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) { 2675275976Ssmh reply_desc->Words = MRSAS_ULONG_MAX; 2676275976Ssmh } 2677265555Sambrisko} 2678265555Sambrisko 2679275976Ssmh/* 2680275976Ssmh * mrsas_reset_ctrl: Core function to OCR/Kill adapter. 2681275976Ssmh * input: Adapter Context. 2682265555Sambrisko * 2683275976Ssmh * This function will run from thread context so that it can sleep. 1. Do not 2684275976Ssmh * handle OCR if FW is in HW critical error. 2. Wait for outstanding command 2685275976Ssmh * to complete for 180 seconds. 3. If #2 does not find any outstanding 2686275976Ssmh * command Controller is in working state, so skip OCR. Otherwise, do 2687275976Ssmh * OCR/kill Adapter based on flag disableOnlineCtrlReset. 4. Start of the 2688275976Ssmh * OCR, return all SCSI command back to CAM layer which has ccb_ptr. 5. Post 2689275976Ssmh * OCR, Re-fire Managment command and move Controller to Operation state. 2690265555Sambrisko */ 2691275976Ssmhint 2692275976Ssmhmrsas_reset_ctrl(struct mrsas_softc *sc) 2693265555Sambrisko{ 2694275976Ssmh int retval = SUCCESS, i, j, retry = 0; 2695275976Ssmh u_int32_t host_diag, abs_state, status_reg, reset_adapter; 2696275976Ssmh union ccb *ccb; 2697275976Ssmh struct mrsas_mfi_cmd *mfi_cmd; 2698275976Ssmh struct mrsas_mpt_cmd *mpt_cmd; 2699275976Ssmh MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc; 2700265555Sambrisko 2701275976Ssmh if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) { 2702275976Ssmh device_printf(sc->mrsas_dev, 2703275976Ssmh "mrsas: Hardware critical error, returning FAIL.\n"); 2704275976Ssmh return FAIL; 2705275976Ssmh } 2706275976Ssmh mrsas_set_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); 2707275976Ssmh sc->adprecovery = MRSAS_ADPRESET_SM_INFAULT; 2708275976Ssmh mrsas_disable_intr(sc); 2709275976Ssmh DELAY(1000 * 1000); 2710265555Sambrisko 2711275976Ssmh /* First try waiting for commands to complete */ 2712275976Ssmh if (mrsas_wait_for_outstanding(sc)) { 2713275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2714275976Ssmh "resetting adapter from %s.\n", 2715275976Ssmh __func__); 2716275976Ssmh /* Now return commands back to the CAM layer */ 2717275976Ssmh for (i = 0; i < sc->max_fw_cmds; i++) { 2718275976Ssmh mpt_cmd = sc->mpt_cmd_list[i]; 2719275976Ssmh if (mpt_cmd->ccb_ptr) { 2720275976Ssmh ccb = (union ccb *)(mpt_cmd->ccb_ptr); 2721275976Ssmh ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 2722275976Ssmh mrsas_cmd_done(sc, mpt_cmd); 2723275976Ssmh mrsas_atomic_dec(&sc->fw_outstanding); 2724275976Ssmh } 2725275976Ssmh } 2726265555Sambrisko 2727275976Ssmh status_reg = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2728275976Ssmh outbound_scratch_pad)); 2729275976Ssmh abs_state = status_reg & MFI_STATE_MASK; 2730275976Ssmh reset_adapter = status_reg & MFI_RESET_ADAPTER; 2731275976Ssmh if (sc->disableOnlineCtrlReset || 2732275976Ssmh (abs_state == MFI_STATE_FAULT && !reset_adapter)) { 2733275976Ssmh /* Reset not supported, kill adapter */ 2734275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "Reset not supported, killing adapter.\n"); 2735275976Ssmh mrsas_kill_hba(sc); 2736275976Ssmh retval = FAIL; 2737275976Ssmh goto out; 2738275976Ssmh } 2739275976Ssmh /* Now try to reset the chip */ 2740275976Ssmh for (i = 0; i < MRSAS_FUSION_MAX_RESET_TRIES; i++) { 2741275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2742275976Ssmh MPI2_WRSEQ_FLUSH_KEY_VALUE); 2743275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2744275976Ssmh MPI2_WRSEQ_1ST_KEY_VALUE); 2745275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2746275976Ssmh MPI2_WRSEQ_2ND_KEY_VALUE); 2747275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2748275976Ssmh MPI2_WRSEQ_3RD_KEY_VALUE); 2749275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2750275976Ssmh MPI2_WRSEQ_4TH_KEY_VALUE); 2751275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2752275976Ssmh MPI2_WRSEQ_5TH_KEY_VALUE); 2753275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset), 2754275976Ssmh MPI2_WRSEQ_6TH_KEY_VALUE); 2755265555Sambrisko 2756275976Ssmh /* Check that the diag write enable (DRWE) bit is on */ 2757275976Ssmh host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2758275976Ssmh fusion_host_diag)); 2759275976Ssmh retry = 0; 2760275976Ssmh while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { 2761275976Ssmh DELAY(100 * 1000); 2762275976Ssmh host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2763275976Ssmh fusion_host_diag)); 2764275976Ssmh if (retry++ == 100) { 2765275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2766275976Ssmh "Host diag unlock failed!\n"); 2767275976Ssmh break; 2768275976Ssmh } 2769275976Ssmh } 2770275976Ssmh if (!(host_diag & HOST_DIAG_WRITE_ENABLE)) 2771275976Ssmh continue; 2772265555Sambrisko 2773275976Ssmh /* Send chip reset command */ 2774275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_host_diag), 2775275976Ssmh host_diag | HOST_DIAG_RESET_ADAPTER); 2776275976Ssmh DELAY(3000 * 1000); 2777265555Sambrisko 2778275976Ssmh /* Make sure reset adapter bit is cleared */ 2779275976Ssmh host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2780275976Ssmh fusion_host_diag)); 2781275976Ssmh retry = 0; 2782275976Ssmh while (host_diag & HOST_DIAG_RESET_ADAPTER) { 2783275976Ssmh DELAY(100 * 1000); 2784275976Ssmh host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2785275976Ssmh fusion_host_diag)); 2786275976Ssmh if (retry++ == 1000) { 2787275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2788275976Ssmh "Diag reset adapter never cleared!\n"); 2789275976Ssmh break; 2790275976Ssmh } 2791275976Ssmh } 2792275976Ssmh if (host_diag & HOST_DIAG_RESET_ADAPTER) 2793275976Ssmh continue; 2794265555Sambrisko 2795275976Ssmh abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2796275976Ssmh outbound_scratch_pad)) & MFI_STATE_MASK; 2797275976Ssmh retry = 0; 2798265555Sambrisko 2799275976Ssmh while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) { 2800275976Ssmh DELAY(100 * 1000); 2801275976Ssmh abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2802275976Ssmh outbound_scratch_pad)) & MFI_STATE_MASK; 2803275976Ssmh } 2804275976Ssmh if (abs_state <= MFI_STATE_FW_INIT) { 2805275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "firmware state < MFI_STATE_FW_INIT," 2806275976Ssmh " state = 0x%x\n", abs_state); 2807275976Ssmh continue; 2808275976Ssmh } 2809275976Ssmh /* Wait for FW to become ready */ 2810275976Ssmh if (mrsas_transition_to_ready(sc, 1)) { 2811275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2812275976Ssmh "mrsas: Failed to transition controller to ready.\n"); 2813275976Ssmh continue; 2814275976Ssmh } 2815275976Ssmh mrsas_reset_reply_desc(sc); 2816275976Ssmh if (mrsas_ioc_init(sc)) { 2817275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n"); 2818275976Ssmh continue; 2819275976Ssmh } 2820275976Ssmh /* Re-fire management commands */ 2821275976Ssmh for (j = 0; j < sc->max_fw_cmds; j++) { 2822275976Ssmh mpt_cmd = sc->mpt_cmd_list[j]; 2823275976Ssmh if (mpt_cmd->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) { 2824275976Ssmh mfi_cmd = sc->mfi_cmd_list[mpt_cmd->sync_cmd_idx]; 2825275976Ssmh if (mfi_cmd->frame->dcmd.opcode == 2826275976Ssmh MR_DCMD_LD_MAP_GET_INFO) { 2827275976Ssmh mrsas_release_mfi_cmd(mfi_cmd); 2828275976Ssmh mrsas_release_mpt_cmd(mpt_cmd); 2829275976Ssmh } else { 2830275976Ssmh req_desc = mrsas_get_request_desc(sc, 2831275976Ssmh mfi_cmd->cmd_id.context.smid - 1); 2832275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2833275976Ssmh "Re-fire command DCMD opcode 0x%x index %d\n ", 2834275976Ssmh mfi_cmd->frame->dcmd.opcode, j); 2835275976Ssmh if (!req_desc) 2836275976Ssmh device_printf(sc->mrsas_dev, 2837275976Ssmh "Cannot build MPT cmd.\n"); 2838275976Ssmh else 2839275976Ssmh mrsas_fire_cmd(sc, req_desc->addr.u.low, 2840275976Ssmh req_desc->addr.u.high); 2841275976Ssmh } 2842275976Ssmh } 2843275976Ssmh } 2844265555Sambrisko 2845275976Ssmh /* Reset load balance info */ 2846275976Ssmh memset(sc->load_balance_info, 0, 2847275976Ssmh sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT); 2848265555Sambrisko 2849284267Skadesai if (mrsas_get_ctrl_info(sc)) { 2850284267Skadesai mrsas_kill_hba(sc); 2851284267Skadesai retval = FAIL; 2852284267Skadesai goto out; 2853284267Skadesai } 2854275976Ssmh if (!mrsas_get_map_info(sc)) 2855275976Ssmh mrsas_sync_map_info(sc); 2856265555Sambrisko 2857284267Skadesai mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); 2858284267Skadesai mrsas_enable_intr(sc); 2859284267Skadesai sc->adprecovery = MRSAS_HBA_OPERATIONAL; 2860284267Skadesai 2861275976Ssmh /* Adapter reset completed successfully */ 2862275976Ssmh device_printf(sc->mrsas_dev, "Reset successful\n"); 2863275976Ssmh retval = SUCCESS; 2864275976Ssmh goto out; 2865275976Ssmh } 2866275976Ssmh /* Reset failed, kill the adapter */ 2867275976Ssmh device_printf(sc->mrsas_dev, "Reset failed, killing adapter.\n"); 2868275976Ssmh mrsas_kill_hba(sc); 2869275976Ssmh retval = FAIL; 2870275976Ssmh } else { 2871275976Ssmh mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); 2872275976Ssmh mrsas_enable_intr(sc); 2873275976Ssmh sc->adprecovery = MRSAS_HBA_OPERATIONAL; 2874275976Ssmh } 2875265555Sambriskoout: 2876275976Ssmh mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); 2877275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2878275976Ssmh "Reset Exit with %d.\n", retval); 2879275976Ssmh return retval; 2880265555Sambrisko} 2881265555Sambrisko 2882275976Ssmh/* 2883275976Ssmh * mrsas_kill_hba: Kill HBA when OCR is not supported 2884275976Ssmh * input: Adapter Context. 2885265555Sambrisko * 2886265555Sambrisko * This function will kill HBA when OCR is not supported. 2887265555Sambrisko */ 2888275976Ssmhvoid 2889275976Ssmhmrsas_kill_hba(struct mrsas_softc *sc) 2890265555Sambrisko{ 2891284267Skadesai sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; 2892284267Skadesai pause("mrsas_kill_hba", 1000); 2893275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__); 2894275976Ssmh mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), 2895275976Ssmh MFI_STOP_ADP); 2896275976Ssmh /* Flush */ 2897275976Ssmh mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)); 2898284267Skadesai mrsas_complete_outstanding_ioctls(sc); 2899265555Sambrisko} 2900265555Sambrisko 2901284267Skadesai/** 2902284267Skadesai * mrsas_complete_outstanding_ioctls Complete pending IOCTLS after kill_hba 2903284267Skadesai * input: Controller softc 2904284267Skadesai * 2905284267Skadesai * Returns void 2906284267Skadesai */ 2907284267Skadesaivoid 2908284267Skadesaimrsas_complete_outstanding_ioctls(struct mrsas_softc *sc) 2909284267Skadesai{ 2910284267Skadesai int i; 2911284267Skadesai struct mrsas_mpt_cmd *cmd_mpt; 2912284267Skadesai struct mrsas_mfi_cmd *cmd_mfi; 2913284267Skadesai u_int32_t count, MSIxIndex; 2914284267Skadesai 2915284267Skadesai count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 2916284267Skadesai for (i = 0; i < sc->max_fw_cmds; i++) { 2917284267Skadesai cmd_mpt = sc->mpt_cmd_list[i]; 2918284267Skadesai 2919284267Skadesai if (cmd_mpt->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) { 2920284267Skadesai cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx]; 2921284267Skadesai if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) { 2922284267Skadesai for (MSIxIndex = 0; MSIxIndex < count; MSIxIndex++) 2923284267Skadesai mrsas_complete_mptmfi_passthru(sc, cmd_mfi, 2924284267Skadesai cmd_mpt->io_request->RaidContext.status); 2925284267Skadesai } 2926284267Skadesai } 2927284267Skadesai } 2928284267Skadesai} 2929284267Skadesai 2930275976Ssmh/* 2931275976Ssmh * mrsas_wait_for_outstanding: Wait for outstanding commands 2932275976Ssmh * input: Adapter Context. 2933265555Sambrisko * 2934275976Ssmh * This function will wait for 180 seconds for outstanding commands to be 2935275976Ssmh * completed. 2936265555Sambrisko */ 2937275976Ssmhint 2938275976Ssmhmrsas_wait_for_outstanding(struct mrsas_softc *sc) 2939265555Sambrisko{ 2940275976Ssmh int i, outstanding, retval = 0; 2941275976Ssmh u_int32_t fw_state, count, MSIxIndex; 2942265555Sambrisko 2943265555Sambrisko 2944275976Ssmh for (i = 0; i < MRSAS_RESET_WAIT_TIME; i++) { 2945275976Ssmh if (sc->remove_in_progress) { 2946275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2947275976Ssmh "Driver remove or shutdown called.\n"); 2948275976Ssmh retval = 1; 2949275976Ssmh goto out; 2950275976Ssmh } 2951275976Ssmh /* Check if firmware is in fault state */ 2952275976Ssmh fw_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, 2953275976Ssmh outbound_scratch_pad)) & MFI_STATE_MASK; 2954275976Ssmh if (fw_state == MFI_STATE_FAULT) { 2955275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2956275976Ssmh "Found FW in FAULT state, will reset adapter.\n"); 2957275976Ssmh retval = 1; 2958275976Ssmh goto out; 2959275976Ssmh } 2960275976Ssmh outstanding = mrsas_atomic_read(&sc->fw_outstanding); 2961275976Ssmh if (!outstanding) 2962275976Ssmh goto out; 2963265555Sambrisko 2964275976Ssmh if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { 2965275976Ssmh mrsas_dprint(sc, MRSAS_OCR, "[%2d]waiting for %d " 2966275976Ssmh "commands to complete\n", i, outstanding); 2967275976Ssmh count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; 2968275976Ssmh for (MSIxIndex = 0; MSIxIndex < count; MSIxIndex++) 2969275976Ssmh mrsas_complete_cmd(sc, MSIxIndex); 2970275976Ssmh } 2971275976Ssmh DELAY(1000 * 1000); 2972275976Ssmh } 2973275976Ssmh 2974275976Ssmh if (mrsas_atomic_read(&sc->fw_outstanding)) { 2975275976Ssmh mrsas_dprint(sc, MRSAS_OCR, 2976275976Ssmh " pending commands remain after waiting," 2977275976Ssmh " will reset adapter.\n"); 2978275976Ssmh retval = 1; 2979275976Ssmh } 2980265555Sambriskoout: 2981275976Ssmh return retval; 2982265555Sambrisko} 2983265555Sambrisko 2984275976Ssmh/* 2985275976Ssmh * mrsas_release_mfi_cmd: Return a cmd to free command pool 2986275976Ssmh * input: Command packet for return to free cmd pool 2987265555Sambrisko * 2988265555Sambrisko * This function returns the MFI command to the command list. 2989265555Sambrisko */ 2990275976Ssmhvoid 2991275976Ssmhmrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd) 2992265555Sambrisko{ 2993275976Ssmh struct mrsas_softc *sc = cmd->sc; 2994265555Sambrisko 2995275976Ssmh mtx_lock(&sc->mfi_cmd_pool_lock); 2996275976Ssmh cmd->ccb_ptr = NULL; 2997265555Sambrisko cmd->cmd_id.frame_count = 0; 2998275976Ssmh TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next); 2999275976Ssmh mtx_unlock(&sc->mfi_cmd_pool_lock); 3000265555Sambrisko 3001275976Ssmh return; 3002265555Sambrisko} 3003265555Sambrisko 3004275976Ssmh/* 3005275976Ssmh * mrsas_get_controller_info: Returns FW's controller structure 3006275976Ssmh * input: Adapter soft state 3007275976Ssmh * Controller information structure 3008265555Sambrisko * 3009275976Ssmh * Issues an internal command (DCMD) to get the FW's controller structure. This 3010275976Ssmh * information is mainly used to find out the maximum IO transfer per command 3011275976Ssmh * supported by the FW. 3012265555Sambrisko */ 3013275976Ssmhstatic int 3014284267Skadesaimrsas_get_ctrl_info(struct mrsas_softc *sc) 3015265555Sambrisko{ 3016275976Ssmh int retcode = 0; 3017275976Ssmh struct mrsas_mfi_cmd *cmd; 3018275976Ssmh struct mrsas_dcmd_frame *dcmd; 3019265555Sambrisko 3020275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3021265555Sambrisko 3022275976Ssmh if (!cmd) { 3023275976Ssmh device_printf(sc->mrsas_dev, "Failed to get a free cmd\n"); 3024275976Ssmh return -ENOMEM; 3025275976Ssmh } 3026275976Ssmh dcmd = &cmd->frame->dcmd; 3027265555Sambrisko 3028275976Ssmh if (mrsas_alloc_ctlr_info_cmd(sc) != SUCCESS) { 3029275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate get ctlr info cmd\n"); 3030275976Ssmh mrsas_release_mfi_cmd(cmd); 3031275976Ssmh return -ENOMEM; 3032275976Ssmh } 3033275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3034265555Sambrisko 3035275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3036275976Ssmh dcmd->cmd_status = 0xFF; 3037275976Ssmh dcmd->sge_count = 1; 3038275976Ssmh dcmd->flags = MFI_FRAME_DIR_READ; 3039275976Ssmh dcmd->timeout = 0; 3040275976Ssmh dcmd->pad_0 = 0; 3041275976Ssmh dcmd->data_xfer_len = sizeof(struct mrsas_ctrl_info); 3042275976Ssmh dcmd->opcode = MR_DCMD_CTRL_GET_INFO; 3043275976Ssmh dcmd->sgl.sge32[0].phys_addr = sc->ctlr_info_phys_addr; 3044275976Ssmh dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info); 3045265555Sambrisko 3046275976Ssmh if (!mrsas_issue_polled(sc, cmd)) 3047284267Skadesai memcpy(sc->ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); 3048275976Ssmh else 3049275976Ssmh retcode = 1; 3050265555Sambrisko 3051284267Skadesai mrsas_update_ext_vd_details(sc); 3052284267Skadesai 3053275976Ssmh mrsas_free_ctlr_info_cmd(sc); 3054275976Ssmh mrsas_release_mfi_cmd(cmd); 3055275976Ssmh return (retcode); 3056265555Sambrisko} 3057265555Sambrisko 3058275976Ssmh/* 3059284267Skadesai * mrsas_update_ext_vd_details : Update details w.r.t Extended VD 3060284267Skadesai * input: 3061284267Skadesai * sc - Controller's softc 3062284267Skadesai*/ 3063284267Skadesaistatic void 3064284267Skadesaimrsas_update_ext_vd_details(struct mrsas_softc *sc) 3065284267Skadesai{ 3066284267Skadesai sc->max256vdSupport = 3067284267Skadesai sc->ctrl_info->adapterOperations3.supportMaxExtLDs; 3068284267Skadesai /* Below is additional check to address future FW enhancement */ 3069284267Skadesai if (sc->ctrl_info->max_lds > 64) 3070284267Skadesai sc->max256vdSupport = 1; 3071284267Skadesai 3072284267Skadesai sc->drv_supported_vd_count = MRSAS_MAX_LD_CHANNELS 3073284267Skadesai * MRSAS_MAX_DEV_PER_CHANNEL; 3074284267Skadesai sc->drv_supported_pd_count = MRSAS_MAX_PD_CHANNELS 3075284267Skadesai * MRSAS_MAX_DEV_PER_CHANNEL; 3076284267Skadesai if (sc->max256vdSupport) { 3077284267Skadesai sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; 3078284267Skadesai sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; 3079284267Skadesai } else { 3080284267Skadesai sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES; 3081284267Skadesai sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; 3082284267Skadesai } 3083284267Skadesai 3084284267Skadesai sc->old_map_sz = sizeof(MR_FW_RAID_MAP) + 3085284267Skadesai (sizeof(MR_LD_SPAN_MAP) * 3086284267Skadesai (sc->fw_supported_vd_count - 1)); 3087284267Skadesai sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT); 3088284267Skadesai sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) + 3089284267Skadesai (sizeof(MR_LD_SPAN_MAP) * 3090284267Skadesai (sc->drv_supported_vd_count - 1)); 3091284267Skadesai 3092284267Skadesai sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz); 3093284267Skadesai 3094284267Skadesai if (sc->max256vdSupport) 3095284267Skadesai sc->current_map_sz = sc->new_map_sz; 3096284267Skadesai else 3097284267Skadesai sc->current_map_sz = sc->old_map_sz; 3098284267Skadesai} 3099284267Skadesai 3100284267Skadesai/* 3101275976Ssmh * mrsas_alloc_ctlr_info_cmd: Allocates memory for controller info command 3102275976Ssmh * input: Adapter soft state 3103265555Sambrisko * 3104265555Sambrisko * Allocates DMAable memory for the controller info internal command. 3105265555Sambrisko */ 3106275976Ssmhint 3107275976Ssmhmrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc) 3108265555Sambrisko{ 3109275976Ssmh int ctlr_info_size; 3110265555Sambrisko 3111275976Ssmh /* Allocate get controller info command */ 3112275976Ssmh ctlr_info_size = sizeof(struct mrsas_ctrl_info); 3113275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 3114275976Ssmh 1, 0, 3115275976Ssmh BUS_SPACE_MAXADDR_32BIT, 3116275976Ssmh BUS_SPACE_MAXADDR, 3117275976Ssmh NULL, NULL, 3118275976Ssmh ctlr_info_size, 3119275976Ssmh 1, 3120275976Ssmh ctlr_info_size, 3121275976Ssmh BUS_DMA_ALLOCNOW, 3122275976Ssmh NULL, NULL, 3123275976Ssmh &sc->ctlr_info_tag)) { 3124275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate ctlr info tag\n"); 3125275976Ssmh return (ENOMEM); 3126275976Ssmh } 3127275976Ssmh if (bus_dmamem_alloc(sc->ctlr_info_tag, (void **)&sc->ctlr_info_mem, 3128275976Ssmh BUS_DMA_NOWAIT, &sc->ctlr_info_dmamap)) { 3129275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate ctlr info cmd mem\n"); 3130275976Ssmh return (ENOMEM); 3131275976Ssmh } 3132275976Ssmh if (bus_dmamap_load(sc->ctlr_info_tag, sc->ctlr_info_dmamap, 3133275976Ssmh sc->ctlr_info_mem, ctlr_info_size, mrsas_addr_cb, 3134275976Ssmh &sc->ctlr_info_phys_addr, BUS_DMA_NOWAIT)) { 3135275976Ssmh device_printf(sc->mrsas_dev, "Cannot load ctlr info cmd mem\n"); 3136275976Ssmh return (ENOMEM); 3137275976Ssmh } 3138275976Ssmh memset(sc->ctlr_info_mem, 0, ctlr_info_size); 3139275976Ssmh return (0); 3140265555Sambrisko} 3141265555Sambrisko 3142275976Ssmh/* 3143275976Ssmh * mrsas_free_ctlr_info_cmd: Free memory for controller info command 3144275976Ssmh * input: Adapter soft state 3145265555Sambrisko * 3146265555Sambrisko * Deallocates memory of the get controller info cmd. 3147265555Sambrisko */ 3148275976Ssmhvoid 3149275976Ssmhmrsas_free_ctlr_info_cmd(struct mrsas_softc *sc) 3150265555Sambrisko{ 3151275976Ssmh if (sc->ctlr_info_phys_addr) 3152275976Ssmh bus_dmamap_unload(sc->ctlr_info_tag, sc->ctlr_info_dmamap); 3153275976Ssmh if (sc->ctlr_info_mem != NULL) 3154275976Ssmh bus_dmamem_free(sc->ctlr_info_tag, sc->ctlr_info_mem, sc->ctlr_info_dmamap); 3155275976Ssmh if (sc->ctlr_info_tag != NULL) 3156275976Ssmh bus_dma_tag_destroy(sc->ctlr_info_tag); 3157265555Sambrisko} 3158265555Sambrisko 3159275976Ssmh/* 3160275976Ssmh * mrsas_issue_polled: Issues a polling command 3161275976Ssmh * inputs: Adapter soft state 3162275976Ssmh * Command packet to be issued 3163265555Sambrisko * 3164275976Ssmh * This function is for posting of internal commands to Firmware. MFI requires 3165275976Ssmh * the cmd_status to be set to 0xFF before posting. The maximun wait time of 3166275976Ssmh * the poll response timer is 180 seconds. 3167265555Sambrisko */ 3168275976Ssmhint 3169275976Ssmhmrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3170265555Sambrisko{ 3171275976Ssmh struct mrsas_header *frame_hdr = &cmd->frame->hdr; 3172275976Ssmh u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME; 3173275976Ssmh int i, retcode = 0; 3174265555Sambrisko 3175275976Ssmh frame_hdr->cmd_status = 0xFF; 3176275976Ssmh frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 3177265555Sambrisko 3178275976Ssmh /* Issue the frame using inbound queue port */ 3179275976Ssmh if (mrsas_issue_dcmd(sc, cmd)) { 3180275976Ssmh device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n"); 3181275976Ssmh return (1); 3182275976Ssmh } 3183275976Ssmh /* 3184275976Ssmh * Poll response timer to wait for Firmware response. While this 3185275976Ssmh * timer with the DELAY call could block CPU, the time interval for 3186275976Ssmh * this is only 1 millisecond. 3187275976Ssmh */ 3188275976Ssmh if (frame_hdr->cmd_status == 0xFF) { 3189275976Ssmh for (i = 0; i < (max_wait * 1000); i++) { 3190275976Ssmh if (frame_hdr->cmd_status == 0xFF) 3191275976Ssmh DELAY(1000); 3192275976Ssmh else 3193275976Ssmh break; 3194275976Ssmh } 3195275976Ssmh } 3196275976Ssmh if (frame_hdr->cmd_status != 0) { 3197275976Ssmh if (frame_hdr->cmd_status == 0xFF) 3198275976Ssmh device_printf(sc->mrsas_dev, "DCMD timed out after %d seconds.\n", max_wait); 3199275976Ssmh else 3200275976Ssmh device_printf(sc->mrsas_dev, "DCMD failed, status = 0x%x\n", frame_hdr->cmd_status); 3201275976Ssmh retcode = 1; 3202275976Ssmh } 3203275976Ssmh return (retcode); 3204265555Sambrisko} 3205265555Sambrisko 3206275976Ssmh/* 3207275976Ssmh * mrsas_issue_dcmd: Issues a MFI Pass thru cmd 3208275976Ssmh * input: Adapter soft state mfi cmd pointer 3209265555Sambrisko * 3210265555Sambrisko * This function is called by mrsas_issued_blocked_cmd() and 3211275976Ssmh * mrsas_issued_polled(), to build the MPT command and then fire the command 3212275976Ssmh * to Firmware. 3213265555Sambrisko */ 3214265555Sambriskoint 3215265555Sambriskomrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3216265555Sambrisko{ 3217275976Ssmh MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc; 3218265555Sambrisko 3219275976Ssmh req_desc = mrsas_build_mpt_cmd(sc, cmd); 3220275976Ssmh if (!req_desc) { 3221275976Ssmh device_printf(sc->mrsas_dev, "Cannot build MPT cmd.\n"); 3222275976Ssmh return (1); 3223275976Ssmh } 3224275976Ssmh mrsas_fire_cmd(sc, req_desc->addr.u.low, req_desc->addr.u.high); 3225265555Sambrisko 3226275976Ssmh return (0); 3227265555Sambrisko} 3228265555Sambrisko 3229275976Ssmh/* 3230275976Ssmh * mrsas_build_mpt_cmd: Calls helper function to build Passthru cmd 3231275976Ssmh * input: Adapter soft state mfi cmd to build 3232265555Sambrisko * 3233275976Ssmh * This function is called by mrsas_issue_cmd() to build the MPT-MFI passthru 3234275976Ssmh * command and prepares the MPT command to send to Firmware. 3235265555Sambrisko */ 3236265555SambriskoMRSAS_REQUEST_DESCRIPTOR_UNION * 3237265555Sambriskomrsas_build_mpt_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3238265555Sambrisko{ 3239275976Ssmh MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc; 3240275976Ssmh u_int16_t index; 3241265555Sambrisko 3242275976Ssmh if (mrsas_build_mptmfi_passthru(sc, cmd)) { 3243275976Ssmh device_printf(sc->mrsas_dev, "Cannot build MPT-MFI passthru cmd.\n"); 3244275976Ssmh return NULL; 3245275976Ssmh } 3246275976Ssmh index = cmd->cmd_id.context.smid; 3247265555Sambrisko 3248275976Ssmh req_desc = mrsas_get_request_desc(sc, index - 1); 3249275976Ssmh if (!req_desc) 3250275976Ssmh return NULL; 3251265555Sambrisko 3252275976Ssmh req_desc->addr.Words = 0; 3253275976Ssmh req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 3254265555Sambrisko 3255275976Ssmh req_desc->SCSIIO.SMID = index; 3256265555Sambrisko 3257275976Ssmh return (req_desc); 3258265555Sambrisko} 3259265555Sambrisko 3260275976Ssmh/* 3261275976Ssmh * mrsas_build_mptmfi_passthru: Builds a MPT MFI Passthru command 3262275976Ssmh * input: Adapter soft state mfi cmd pointer 3263265555Sambrisko * 3264275976Ssmh * The MPT command and the io_request are setup as a passthru command. The SGE 3265275976Ssmh * chain address is set to frame_phys_addr of the MFI command. 3266265555Sambrisko */ 3267265555Sambriskou_int8_t 3268265555Sambriskomrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cmd) 3269265555Sambrisko{ 3270275976Ssmh MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain; 3271275976Ssmh PTR_MRSAS_RAID_SCSI_IO_REQUEST io_req; 3272275976Ssmh struct mrsas_mpt_cmd *mpt_cmd; 3273275976Ssmh struct mrsas_header *frame_hdr = &mfi_cmd->frame->hdr; 3274265555Sambrisko 3275275976Ssmh mpt_cmd = mrsas_get_mpt_cmd(sc); 3276275976Ssmh if (!mpt_cmd) 3277275976Ssmh return (1); 3278265555Sambrisko 3279275976Ssmh /* Save the smid. To be used for returning the cmd */ 3280275976Ssmh mfi_cmd->cmd_id.context.smid = mpt_cmd->index; 3281265555Sambrisko 3282275976Ssmh mpt_cmd->sync_cmd_idx = mfi_cmd->index; 3283265555Sambrisko 3284275976Ssmh /* 3285275976Ssmh * For cmds where the flag is set, store the flag and check on 3286275976Ssmh * completion. For cmds with this flag, don't call 3287275976Ssmh * mrsas_complete_cmd. 3288275976Ssmh */ 3289265555Sambrisko 3290275976Ssmh if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE) 3291275976Ssmh mpt_cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 3292265555Sambrisko 3293275976Ssmh io_req = mpt_cmd->io_request; 3294265555Sambrisko 3295275976Ssmh if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { 3296275976Ssmh pMpi25IeeeSgeChain64_t sgl_ptr_end = (pMpi25IeeeSgeChain64_t)&io_req->SGL; 3297265555Sambrisko 3298275976Ssmh sgl_ptr_end += sc->max_sge_in_main_msg - 1; 3299275976Ssmh sgl_ptr_end->Flags = 0; 3300275976Ssmh } 3301275976Ssmh mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *) & io_req->SGL.IeeeChain; 3302265555Sambrisko 3303275976Ssmh io_req->Function = MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST; 3304275976Ssmh io_req->SGLOffset0 = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 4; 3305275976Ssmh io_req->ChainOffset = sc->chain_offset_mfi_pthru; 3306265555Sambrisko 3307275976Ssmh mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr; 3308265555Sambrisko 3309275976Ssmh mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | 3310275976Ssmh MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; 3311265555Sambrisko 3312275976Ssmh mpi25_ieee_chain->Length = MRSAS_MAX_SZ_CHAIN_FRAME; 3313265555Sambrisko 3314275976Ssmh return (0); 3315265555Sambrisko} 3316265555Sambrisko 3317275976Ssmh/* 3318275976Ssmh * mrsas_issue_blocked_cmd: Synchronous wrapper around regular FW cmds 3319275976Ssmh * input: Adapter soft state Command to be issued 3320265555Sambrisko * 3321275976Ssmh * This function waits on an event for the command to be returned from the ISR. 3322275976Ssmh * Max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME secs. Used for issuing 3323275976Ssmh * internal and ioctl commands. 3324265555Sambrisko */ 3325275976Ssmhint 3326275976Ssmhmrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3327265555Sambrisko{ 3328275976Ssmh u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME; 3329275976Ssmh unsigned long total_time = 0; 3330275976Ssmh int retcode = 0; 3331265555Sambrisko 3332275976Ssmh /* Initialize cmd_status */ 3333275976Ssmh cmd->cmd_status = ECONNREFUSED; 3334265555Sambrisko 3335275976Ssmh /* Build MPT-MFI command for issue to FW */ 3336275976Ssmh if (mrsas_issue_dcmd(sc, cmd)) { 3337275976Ssmh device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n"); 3338275976Ssmh return (1); 3339275976Ssmh } 3340275976Ssmh sc->chan = (void *)&cmd; 3341265555Sambrisko 3342275976Ssmh while (1) { 3343275976Ssmh if (cmd->cmd_status == ECONNREFUSED) { 3344275976Ssmh tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz); 3345275976Ssmh } else 3346275976Ssmh break; 3347275976Ssmh total_time++; 3348275976Ssmh if (total_time >= max_wait) { 3349275976Ssmh device_printf(sc->mrsas_dev, 3350275976Ssmh "Internal command timed out after %d seconds.\n", max_wait); 3351275976Ssmh retcode = 1; 3352275976Ssmh break; 3353275976Ssmh } 3354275976Ssmh } 3355275976Ssmh return (retcode); 3356265555Sambrisko} 3357265555Sambrisko 3358275976Ssmh/* 3359275976Ssmh * mrsas_complete_mptmfi_passthru: Completes a command 3360275976Ssmh * input: @sc: Adapter soft state 3361275976Ssmh * @cmd: Command to be completed 3362275976Ssmh * @status: cmd completion status 3363265555Sambrisko * 3364275976Ssmh * This function is called from mrsas_complete_cmd() after an interrupt is 3365275976Ssmh * received from Firmware, and io_request->Function is 3366265555Sambrisko * MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST. 3367265555Sambrisko */ 3368265555Sambriskovoid 3369265555Sambriskomrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd, 3370275976Ssmh u_int8_t status) 3371265555Sambrisko{ 3372275976Ssmh struct mrsas_header *hdr = &cmd->frame->hdr; 3373275976Ssmh u_int8_t cmd_status = cmd->frame->hdr.cmd_status; 3374265555Sambrisko 3375275976Ssmh /* Reset the retry counter for future re-tries */ 3376275976Ssmh cmd->retry_for_fw_reset = 0; 3377265555Sambrisko 3378275976Ssmh if (cmd->ccb_ptr) 3379275976Ssmh cmd->ccb_ptr = NULL; 3380265555Sambrisko 3381275976Ssmh switch (hdr->cmd) { 3382275976Ssmh case MFI_CMD_INVALID: 3383275976Ssmh device_printf(sc->mrsas_dev, "MFI_CMD_INVALID command.\n"); 3384275976Ssmh break; 3385275976Ssmh case MFI_CMD_PD_SCSI_IO: 3386275976Ssmh case MFI_CMD_LD_SCSI_IO: 3387275976Ssmh /* 3388275976Ssmh * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been 3389275976Ssmh * issued either through an IO path or an IOCTL path. If it 3390275976Ssmh * was via IOCTL, we will send it to internal completion. 3391275976Ssmh */ 3392275976Ssmh if (cmd->sync_cmd) { 3393275976Ssmh cmd->sync_cmd = 0; 3394275976Ssmh mrsas_wakeup(sc, cmd); 3395275976Ssmh break; 3396275976Ssmh } 3397275976Ssmh case MFI_CMD_SMP: 3398275976Ssmh case MFI_CMD_STP: 3399275976Ssmh case MFI_CMD_DCMD: 3400275976Ssmh /* Check for LD map update */ 3401275976Ssmh if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) && 3402275976Ssmh (cmd->frame->dcmd.mbox.b[1] == 1)) { 3403275976Ssmh sc->fast_path_io = 0; 3404275976Ssmh mtx_lock(&sc->raidmap_lock); 3405275976Ssmh if (cmd_status != 0) { 3406275976Ssmh if (cmd_status != MFI_STAT_NOT_FOUND) 3407275976Ssmh device_printf(sc->mrsas_dev, "map sync failed, status=%x\n", cmd_status); 3408275976Ssmh else { 3409275976Ssmh mrsas_release_mfi_cmd(cmd); 3410275976Ssmh mtx_unlock(&sc->raidmap_lock); 3411275976Ssmh break; 3412275976Ssmh } 3413275976Ssmh } else 3414275976Ssmh sc->map_id++; 3415275976Ssmh mrsas_release_mfi_cmd(cmd); 3416275976Ssmh if (MR_ValidateMapInfo(sc)) 3417275976Ssmh sc->fast_path_io = 0; 3418275976Ssmh else 3419275976Ssmh sc->fast_path_io = 1; 3420275976Ssmh mrsas_sync_map_info(sc); 3421275976Ssmh mtx_unlock(&sc->raidmap_lock); 3422275976Ssmh break; 3423275976Ssmh } 3424275976Ssmh if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || 3425275976Ssmh cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { 3426275976Ssmh sc->mrsas_aen_triggered = 0; 3427275976Ssmh } 3428275976Ssmh /* See if got an event notification */ 3429275976Ssmh if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) 3430275976Ssmh mrsas_complete_aen(sc, cmd); 3431275976Ssmh else 3432275976Ssmh mrsas_wakeup(sc, cmd); 3433275976Ssmh break; 3434275976Ssmh case MFI_CMD_ABORT: 3435275976Ssmh /* Command issued to abort another cmd return */ 3436275976Ssmh mrsas_complete_abort(sc, cmd); 3437275976Ssmh break; 3438275976Ssmh default: 3439275976Ssmh device_printf(sc->mrsas_dev, "Unknown command completed! [0x%X]\n", hdr->cmd); 3440275976Ssmh break; 3441275976Ssmh } 3442265555Sambrisko} 3443265555Sambrisko 3444275976Ssmh/* 3445275976Ssmh * mrsas_wakeup: Completes an internal command 3446275976Ssmh * input: Adapter soft state 3447275976Ssmh * Command to be completed 3448265555Sambrisko * 3449275976Ssmh * In mrsas_issue_blocked_cmd(), after a command is issued to Firmware, a wait 3450275976Ssmh * timer is started. This function is called from 3451275976Ssmh * mrsas_complete_mptmfi_passthru() as it completes the command, to wake up 3452275976Ssmh * from the command wait. 3453265555Sambrisko */ 3454275976Ssmhvoid 3455275976Ssmhmrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3456265555Sambrisko{ 3457275976Ssmh cmd->cmd_status = cmd->frame->io.cmd_status; 3458265555Sambrisko 3459275976Ssmh if (cmd->cmd_status == ECONNREFUSED) 3460275976Ssmh cmd->cmd_status = 0; 3461265555Sambrisko 3462275976Ssmh sc->chan = (void *)&cmd; 3463275976Ssmh wakeup_one((void *)&sc->chan); 3464275976Ssmh return; 3465265555Sambrisko} 3466265555Sambrisko 3467275976Ssmh/* 3468275976Ssmh * mrsas_shutdown_ctlr: Instructs FW to shutdown the controller input: 3469275976Ssmh * Adapter soft state Shutdown/Hibernate 3470265555Sambrisko * 3471275976Ssmh * This function issues a DCMD internal command to Firmware to initiate shutdown 3472275976Ssmh * of the controller. 3473265555Sambrisko */ 3474275976Ssmhstatic void 3475275976Ssmhmrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode) 3476265555Sambrisko{ 3477275976Ssmh struct mrsas_mfi_cmd *cmd; 3478275976Ssmh struct mrsas_dcmd_frame *dcmd; 3479265555Sambrisko 3480275976Ssmh if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) 3481275976Ssmh return; 3482265555Sambrisko 3483275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3484275976Ssmh if (!cmd) { 3485275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate for shutdown cmd.\n"); 3486275976Ssmh return; 3487275976Ssmh } 3488275976Ssmh if (sc->aen_cmd) 3489275976Ssmh mrsas_issue_blocked_abort_cmd(sc, sc->aen_cmd); 3490265555Sambrisko 3491265555Sambrisko if (sc->map_update_cmd) 3492275976Ssmh mrsas_issue_blocked_abort_cmd(sc, sc->map_update_cmd); 3493265555Sambrisko 3494275976Ssmh dcmd = &cmd->frame->dcmd; 3495275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3496265555Sambrisko 3497275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3498275976Ssmh dcmd->cmd_status = 0x0; 3499275976Ssmh dcmd->sge_count = 0; 3500275976Ssmh dcmd->flags = MFI_FRAME_DIR_NONE; 3501275976Ssmh dcmd->timeout = 0; 3502275976Ssmh dcmd->pad_0 = 0; 3503275976Ssmh dcmd->data_xfer_len = 0; 3504275976Ssmh dcmd->opcode = opcode; 3505265555Sambrisko 3506275976Ssmh device_printf(sc->mrsas_dev, "Preparing to shut down controller.\n"); 3507265555Sambrisko 3508275976Ssmh mrsas_issue_blocked_cmd(sc, cmd); 3509275976Ssmh mrsas_release_mfi_cmd(cmd); 3510265555Sambrisko 3511275976Ssmh return; 3512265555Sambrisko} 3513265555Sambrisko 3514275976Ssmh/* 3515275976Ssmh * mrsas_flush_cache: Requests FW to flush all its caches input: 3516275976Ssmh * Adapter soft state 3517265555Sambrisko * 3518265555Sambrisko * This function is issues a DCMD internal command to Firmware to initiate 3519265555Sambrisko * flushing of all caches. 3520265555Sambrisko */ 3521275976Ssmhstatic void 3522275976Ssmhmrsas_flush_cache(struct mrsas_softc *sc) 3523265555Sambrisko{ 3524275976Ssmh struct mrsas_mfi_cmd *cmd; 3525275976Ssmh struct mrsas_dcmd_frame *dcmd; 3526265555Sambrisko 3527275976Ssmh if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) 3528275976Ssmh return; 3529265555Sambrisko 3530275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3531275976Ssmh if (!cmd) { 3532275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate for flush cache cmd.\n"); 3533275976Ssmh return; 3534275976Ssmh } 3535275976Ssmh dcmd = &cmd->frame->dcmd; 3536275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3537265555Sambrisko 3538275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3539275976Ssmh dcmd->cmd_status = 0x0; 3540275976Ssmh dcmd->sge_count = 0; 3541275976Ssmh dcmd->flags = MFI_FRAME_DIR_NONE; 3542275976Ssmh dcmd->timeout = 0; 3543275976Ssmh dcmd->pad_0 = 0; 3544275976Ssmh dcmd->data_xfer_len = 0; 3545275976Ssmh dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; 3546275976Ssmh dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; 3547265555Sambrisko 3548275976Ssmh mrsas_issue_blocked_cmd(sc, cmd); 3549275976Ssmh mrsas_release_mfi_cmd(cmd); 3550265555Sambrisko 3551275976Ssmh return; 3552265555Sambrisko} 3553265555Sambrisko 3554275976Ssmh/* 3555275976Ssmh * mrsas_get_map_info: Load and validate RAID map input: 3556275976Ssmh * Adapter instance soft state 3557265555Sambrisko * 3558275976Ssmh * This function calls mrsas_get_ld_map_info() and MR_ValidateMapInfo() to load 3559275976Ssmh * and validate RAID map. It returns 0 if successful, 1 other- wise. 3560265555Sambrisko */ 3561275976Ssmhstatic int 3562275976Ssmhmrsas_get_map_info(struct mrsas_softc *sc) 3563275976Ssmh{ 3564275976Ssmh uint8_t retcode = 0; 3565265555Sambrisko 3566275976Ssmh sc->fast_path_io = 0; 3567275976Ssmh if (!mrsas_get_ld_map_info(sc)) { 3568275976Ssmh retcode = MR_ValidateMapInfo(sc); 3569275976Ssmh if (retcode == 0) { 3570275976Ssmh sc->fast_path_io = 1; 3571275976Ssmh return 0; 3572275976Ssmh } 3573275976Ssmh } 3574275976Ssmh return 1; 3575265555Sambrisko} 3576265555Sambrisko 3577275976Ssmh/* 3578275976Ssmh * mrsas_get_ld_map_info: Get FW's ld_map structure input: 3579275976Ssmh * Adapter instance soft state 3580265555Sambrisko * 3581275976Ssmh * Issues an internal command (DCMD) to get the FW's controller PD list 3582275976Ssmh * structure. 3583265555Sambrisko */ 3584275976Ssmhstatic int 3585275976Ssmhmrsas_get_ld_map_info(struct mrsas_softc *sc) 3586265555Sambrisko{ 3587275976Ssmh int retcode = 0; 3588275976Ssmh struct mrsas_mfi_cmd *cmd; 3589275976Ssmh struct mrsas_dcmd_frame *dcmd; 3590275976Ssmh void *map; 3591275976Ssmh bus_addr_t map_phys_addr = 0; 3592265555Sambrisko 3593275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3594275976Ssmh if (!cmd) { 3595275976Ssmh device_printf(sc->mrsas_dev, 3596275976Ssmh "Cannot alloc for ld map info cmd.\n"); 3597275976Ssmh return 1; 3598275976Ssmh } 3599275976Ssmh dcmd = &cmd->frame->dcmd; 3600265555Sambrisko 3601275976Ssmh map = (void *)sc->raidmap_mem[(sc->map_id & 1)]; 3602275976Ssmh map_phys_addr = sc->raidmap_phys_addr[(sc->map_id & 1)]; 3603275976Ssmh if (!map) { 3604275976Ssmh device_printf(sc->mrsas_dev, 3605275976Ssmh "Failed to alloc mem for ld map info.\n"); 3606275976Ssmh mrsas_release_mfi_cmd(cmd); 3607275976Ssmh return (ENOMEM); 3608275976Ssmh } 3609275976Ssmh memset(map, 0, sizeof(sc->max_map_sz)); 3610275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3611265555Sambrisko 3612275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3613275976Ssmh dcmd->cmd_status = 0xFF; 3614275976Ssmh dcmd->sge_count = 1; 3615275976Ssmh dcmd->flags = MFI_FRAME_DIR_READ; 3616275976Ssmh dcmd->timeout = 0; 3617275976Ssmh dcmd->pad_0 = 0; 3618275976Ssmh dcmd->data_xfer_len = sc->current_map_sz; 3619275976Ssmh dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; 3620275976Ssmh dcmd->sgl.sge32[0].phys_addr = map_phys_addr; 3621275976Ssmh dcmd->sgl.sge32[0].length = sc->current_map_sz; 3622265555Sambrisko 3623275976Ssmh if (!mrsas_issue_polled(sc, cmd)) 3624275976Ssmh retcode = 0; 3625275976Ssmh else { 3626275976Ssmh device_printf(sc->mrsas_dev, 3627275976Ssmh "Fail to send get LD map info cmd.\n"); 3628275976Ssmh retcode = 1; 3629275976Ssmh } 3630275976Ssmh mrsas_release_mfi_cmd(cmd); 3631275976Ssmh 3632275976Ssmh return (retcode); 3633265555Sambrisko} 3634265555Sambrisko 3635275976Ssmh/* 3636275976Ssmh * mrsas_sync_map_info: Get FW's ld_map structure input: 3637275976Ssmh * Adapter instance soft state 3638265555Sambrisko * 3639275976Ssmh * Issues an internal command (DCMD) to get the FW's controller PD list 3640275976Ssmh * structure. 3641265555Sambrisko */ 3642275976Ssmhstatic int 3643275976Ssmhmrsas_sync_map_info(struct mrsas_softc *sc) 3644265555Sambrisko{ 3645275976Ssmh int retcode = 0, i; 3646275976Ssmh struct mrsas_mfi_cmd *cmd; 3647275976Ssmh struct mrsas_dcmd_frame *dcmd; 3648275976Ssmh uint32_t size_sync_info, num_lds; 3649275976Ssmh MR_LD_TARGET_SYNC *target_map = NULL; 3650275976Ssmh MR_DRV_RAID_MAP_ALL *map; 3651275976Ssmh MR_LD_RAID *raid; 3652275976Ssmh MR_LD_TARGET_SYNC *ld_sync; 3653275976Ssmh bus_addr_t map_phys_addr = 0; 3654265555Sambrisko 3655275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3656275976Ssmh if (!cmd) { 3657275976Ssmh device_printf(sc->mrsas_dev, 3658275976Ssmh "Cannot alloc for sync map info cmd\n"); 3659275976Ssmh return 1; 3660275976Ssmh } 3661275976Ssmh map = sc->ld_drv_map[sc->map_id & 1]; 3662275976Ssmh num_lds = map->raidMap.ldCount; 3663265555Sambrisko 3664275976Ssmh dcmd = &cmd->frame->dcmd; 3665275976Ssmh size_sync_info = sizeof(MR_LD_TARGET_SYNC) * num_lds; 3666275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3667265555Sambrisko 3668275976Ssmh target_map = (MR_LD_TARGET_SYNC *) sc->raidmap_mem[(sc->map_id - 1) & 1]; 3669275976Ssmh memset(target_map, 0, sc->max_map_sz); 3670265555Sambrisko 3671275976Ssmh map_phys_addr = sc->raidmap_phys_addr[(sc->map_id - 1) & 1]; 3672265555Sambrisko 3673275976Ssmh ld_sync = (MR_LD_TARGET_SYNC *) target_map; 3674265555Sambrisko 3675275976Ssmh for (i = 0; i < num_lds; i++, ld_sync++) { 3676275976Ssmh raid = MR_LdRaidGet(i, map); 3677275976Ssmh ld_sync->targetId = MR_GetLDTgtId(i, map); 3678275976Ssmh ld_sync->seqNum = raid->seqNum; 3679275976Ssmh } 3680265555Sambrisko 3681275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3682275976Ssmh dcmd->cmd_status = 0xFF; 3683275976Ssmh dcmd->sge_count = 1; 3684275976Ssmh dcmd->flags = MFI_FRAME_DIR_WRITE; 3685275976Ssmh dcmd->timeout = 0; 3686275976Ssmh dcmd->pad_0 = 0; 3687275976Ssmh dcmd->data_xfer_len = sc->current_map_sz; 3688275976Ssmh dcmd->mbox.b[0] = num_lds; 3689275976Ssmh dcmd->mbox.b[1] = MRSAS_DCMD_MBOX_PEND_FLAG; 3690275976Ssmh dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; 3691275976Ssmh dcmd->sgl.sge32[0].phys_addr = map_phys_addr; 3692275976Ssmh dcmd->sgl.sge32[0].length = sc->current_map_sz; 3693265555Sambrisko 3694275976Ssmh sc->map_update_cmd = cmd; 3695275976Ssmh if (mrsas_issue_dcmd(sc, cmd)) { 3696275976Ssmh device_printf(sc->mrsas_dev, 3697275976Ssmh "Fail to send sync map info command.\n"); 3698275976Ssmh return (1); 3699275976Ssmh } 3700275976Ssmh return (retcode); 3701265555Sambrisko} 3702265555Sambrisko 3703275976Ssmh/* 3704275976Ssmh * mrsas_get_pd_list: Returns FW's PD list structure input: 3705275976Ssmh * Adapter soft state 3706265555Sambrisko * 3707275976Ssmh * Issues an internal command (DCMD) to get the FW's controller PD list 3708275976Ssmh * structure. This information is mainly used to find out about system 3709275976Ssmh * supported by Firmware. 3710265555Sambrisko */ 3711275976Ssmhstatic int 3712275976Ssmhmrsas_get_pd_list(struct mrsas_softc *sc) 3713265555Sambrisko{ 3714275976Ssmh int retcode = 0, pd_index = 0, pd_count = 0, pd_list_size; 3715275976Ssmh struct mrsas_mfi_cmd *cmd; 3716275976Ssmh struct mrsas_dcmd_frame *dcmd; 3717275976Ssmh struct MR_PD_LIST *pd_list_mem; 3718275976Ssmh struct MR_PD_ADDRESS *pd_addr; 3719275976Ssmh bus_addr_t pd_list_phys_addr = 0; 3720275976Ssmh struct mrsas_tmp_dcmd *tcmd; 3721265555Sambrisko 3722275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3723275976Ssmh if (!cmd) { 3724275976Ssmh device_printf(sc->mrsas_dev, 3725275976Ssmh "Cannot alloc for get PD list cmd\n"); 3726275976Ssmh return 1; 3727275976Ssmh } 3728275976Ssmh dcmd = &cmd->frame->dcmd; 3729265555Sambrisko 3730275976Ssmh tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT); 3731275976Ssmh pd_list_size = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST); 3732275976Ssmh if (mrsas_alloc_tmp_dcmd(sc, tcmd, pd_list_size) != SUCCESS) { 3733275976Ssmh device_printf(sc->mrsas_dev, 3734275976Ssmh "Cannot alloc dmamap for get PD list cmd\n"); 3735275976Ssmh mrsas_release_mfi_cmd(cmd); 3736275976Ssmh return (ENOMEM); 3737275976Ssmh } else { 3738275976Ssmh pd_list_mem = tcmd->tmp_dcmd_mem; 3739275976Ssmh pd_list_phys_addr = tcmd->tmp_dcmd_phys_addr; 3740275976Ssmh } 3741275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3742265555Sambrisko 3743275976Ssmh dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; 3744275976Ssmh dcmd->mbox.b[1] = 0; 3745275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3746275976Ssmh dcmd->cmd_status = 0xFF; 3747275976Ssmh dcmd->sge_count = 1; 3748275976Ssmh dcmd->flags = MFI_FRAME_DIR_READ; 3749275976Ssmh dcmd->timeout = 0; 3750275976Ssmh dcmd->pad_0 = 0; 3751275976Ssmh dcmd->data_xfer_len = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST); 3752275976Ssmh dcmd->opcode = MR_DCMD_PD_LIST_QUERY; 3753275976Ssmh dcmd->sgl.sge32[0].phys_addr = pd_list_phys_addr; 3754275976Ssmh dcmd->sgl.sge32[0].length = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST); 3755265555Sambrisko 3756275976Ssmh if (!mrsas_issue_polled(sc, cmd)) 3757275976Ssmh retcode = 0; 3758275976Ssmh else 3759275976Ssmh retcode = 1; 3760265555Sambrisko 3761275976Ssmh /* Get the instance PD list */ 3762275976Ssmh pd_count = MRSAS_MAX_PD; 3763275976Ssmh pd_addr = pd_list_mem->addr; 3764275976Ssmh if (retcode == 0 && pd_list_mem->count < pd_count) { 3765275976Ssmh memset(sc->local_pd_list, 0, 3766275976Ssmh MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); 3767275976Ssmh for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) { 3768275976Ssmh sc->local_pd_list[pd_addr->deviceId].tid = pd_addr->deviceId; 3769275976Ssmh sc->local_pd_list[pd_addr->deviceId].driveType = 3770275976Ssmh pd_addr->scsiDevType; 3771275976Ssmh sc->local_pd_list[pd_addr->deviceId].driveState = 3772275976Ssmh MR_PD_STATE_SYSTEM; 3773275976Ssmh pd_addr++; 3774275976Ssmh } 3775275976Ssmh } 3776275976Ssmh /* 3777275976Ssmh * Use mutext/spinlock if pd_list component size increase more than 3778275976Ssmh * 32 bit. 3779275976Ssmh */ 3780275976Ssmh memcpy(sc->pd_list, sc->local_pd_list, sizeof(sc->local_pd_list)); 3781275976Ssmh mrsas_free_tmp_dcmd(tcmd); 3782275976Ssmh mrsas_release_mfi_cmd(cmd); 3783275976Ssmh free(tcmd, M_MRSAS); 3784275976Ssmh return (retcode); 3785265555Sambrisko} 3786265555Sambrisko 3787275976Ssmh/* 3788275976Ssmh * mrsas_get_ld_list: Returns FW's LD list structure input: 3789275976Ssmh * Adapter soft state 3790265555Sambrisko * 3791275976Ssmh * Issues an internal command (DCMD) to get the FW's controller PD list 3792275976Ssmh * structure. This information is mainly used to find out about supported by 3793275976Ssmh * the FW. 3794265555Sambrisko */ 3795275976Ssmhstatic int 3796275976Ssmhmrsas_get_ld_list(struct mrsas_softc *sc) 3797265555Sambrisko{ 3798275976Ssmh int ld_list_size, retcode = 0, ld_index = 0, ids = 0; 3799275976Ssmh struct mrsas_mfi_cmd *cmd; 3800275976Ssmh struct mrsas_dcmd_frame *dcmd; 3801275976Ssmh struct MR_LD_LIST *ld_list_mem; 3802275976Ssmh bus_addr_t ld_list_phys_addr = 0; 3803275976Ssmh struct mrsas_tmp_dcmd *tcmd; 3804265555Sambrisko 3805275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3806275976Ssmh if (!cmd) { 3807275976Ssmh device_printf(sc->mrsas_dev, 3808275976Ssmh "Cannot alloc for get LD list cmd\n"); 3809275976Ssmh return 1; 3810275976Ssmh } 3811275976Ssmh dcmd = &cmd->frame->dcmd; 3812265555Sambrisko 3813275976Ssmh tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT); 3814275976Ssmh ld_list_size = sizeof(struct MR_LD_LIST); 3815275976Ssmh if (mrsas_alloc_tmp_dcmd(sc, tcmd, ld_list_size) != SUCCESS) { 3816275976Ssmh device_printf(sc->mrsas_dev, 3817275976Ssmh "Cannot alloc dmamap for get LD list cmd\n"); 3818275976Ssmh mrsas_release_mfi_cmd(cmd); 3819275976Ssmh return (ENOMEM); 3820275976Ssmh } else { 3821275976Ssmh ld_list_mem = tcmd->tmp_dcmd_mem; 3822275976Ssmh ld_list_phys_addr = tcmd->tmp_dcmd_phys_addr; 3823275976Ssmh } 3824275976Ssmh memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 3825265555Sambrisko 3826275976Ssmh if (sc->max256vdSupport) 3827275976Ssmh dcmd->mbox.b[0] = 1; 3828265555Sambrisko 3829275976Ssmh dcmd->cmd = MFI_CMD_DCMD; 3830275976Ssmh dcmd->cmd_status = 0xFF; 3831275976Ssmh dcmd->sge_count = 1; 3832275976Ssmh dcmd->flags = MFI_FRAME_DIR_READ; 3833275976Ssmh dcmd->timeout = 0; 3834275976Ssmh dcmd->data_xfer_len = sizeof(struct MR_LD_LIST); 3835275976Ssmh dcmd->opcode = MR_DCMD_LD_GET_LIST; 3836275976Ssmh dcmd->sgl.sge32[0].phys_addr = ld_list_phys_addr; 3837275976Ssmh dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); 3838275976Ssmh dcmd->pad_0 = 0; 3839265555Sambrisko 3840275976Ssmh if (!mrsas_issue_polled(sc, cmd)) 3841275976Ssmh retcode = 0; 3842275976Ssmh else 3843275976Ssmh retcode = 1; 3844265555Sambrisko 3845275976Ssmh#if VD_EXT_DEBUG 3846275976Ssmh printf("Number of LDs %d\n", ld_list_mem->ldCount); 3847275976Ssmh#endif 3848265555Sambrisko 3849275976Ssmh /* Get the instance LD list */ 3850275976Ssmh if ((retcode == 0) && 3851275976Ssmh (ld_list_mem->ldCount <= sc->fw_supported_vd_count)) { 3852275976Ssmh sc->CurLdCount = ld_list_mem->ldCount; 3853275976Ssmh memset(sc->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT); 3854275976Ssmh for (ld_index = 0; ld_index < ld_list_mem->ldCount; ld_index++) { 3855275976Ssmh if (ld_list_mem->ldList[ld_index].state != 0) { 3856275976Ssmh ids = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; 3857275976Ssmh sc->ld_ids[ids] = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; 3858275976Ssmh } 3859275976Ssmh } 3860275976Ssmh } 3861275976Ssmh mrsas_free_tmp_dcmd(tcmd); 3862275976Ssmh mrsas_release_mfi_cmd(cmd); 3863275976Ssmh free(tcmd, M_MRSAS); 3864275976Ssmh return (retcode); 3865265555Sambrisko} 3866265555Sambrisko 3867275976Ssmh/* 3868275976Ssmh * mrsas_alloc_tmp_dcmd: Allocates memory for temporary command input: 3869275976Ssmh * Adapter soft state Temp command Size of alloction 3870265555Sambrisko * 3871265555Sambrisko * Allocates DMAable memory for a temporary internal command. The allocated 3872275976Ssmh * memory is initialized to all zeros upon successful loading of the dma 3873265555Sambrisko * mapped memory. 3874265555Sambrisko */ 3875284267Skadesaiint 3876275976Ssmhmrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, 3877275976Ssmh struct mrsas_tmp_dcmd *tcmd, int size) 3878265555Sambrisko{ 3879275976Ssmh if (bus_dma_tag_create(sc->mrsas_parent_tag, 3880275976Ssmh 1, 0, 3881275976Ssmh BUS_SPACE_MAXADDR_32BIT, 3882275976Ssmh BUS_SPACE_MAXADDR, 3883275976Ssmh NULL, NULL, 3884275976Ssmh size, 3885275976Ssmh 1, 3886275976Ssmh size, 3887275976Ssmh BUS_DMA_ALLOCNOW, 3888275976Ssmh NULL, NULL, 3889275976Ssmh &tcmd->tmp_dcmd_tag)) { 3890275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd tag\n"); 3891275976Ssmh return (ENOMEM); 3892275976Ssmh } 3893275976Ssmh if (bus_dmamem_alloc(tcmd->tmp_dcmd_tag, (void **)&tcmd->tmp_dcmd_mem, 3894275976Ssmh BUS_DMA_NOWAIT, &tcmd->tmp_dcmd_dmamap)) { 3895275976Ssmh device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd mem\n"); 3896275976Ssmh return (ENOMEM); 3897275976Ssmh } 3898275976Ssmh if (bus_dmamap_load(tcmd->tmp_dcmd_tag, tcmd->tmp_dcmd_dmamap, 3899275976Ssmh tcmd->tmp_dcmd_mem, size, mrsas_addr_cb, 3900275976Ssmh &tcmd->tmp_dcmd_phys_addr, BUS_DMA_NOWAIT)) { 3901275976Ssmh device_printf(sc->mrsas_dev, "Cannot load tmp dcmd mem\n"); 3902275976Ssmh return (ENOMEM); 3903275976Ssmh } 3904275976Ssmh memset(tcmd->tmp_dcmd_mem, 0, size); 3905275976Ssmh return (0); 3906265555Sambrisko} 3907265555Sambrisko 3908275976Ssmh/* 3909275976Ssmh * mrsas_free_tmp_dcmd: Free memory for temporary command input: 3910275976Ssmh * temporary dcmd pointer 3911265555Sambrisko * 3912275976Ssmh * Deallocates memory of the temporary command for use in the construction of 3913275976Ssmh * the internal DCMD. 3914265555Sambrisko */ 3915275976Ssmhvoid 3916275976Ssmhmrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp) 3917265555Sambrisko{ 3918275976Ssmh if (tmp->tmp_dcmd_phys_addr) 3919275976Ssmh bus_dmamap_unload(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_dmamap); 3920275976Ssmh if (tmp->tmp_dcmd_mem != NULL) 3921275976Ssmh bus_dmamem_free(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_mem, tmp->tmp_dcmd_dmamap); 3922275976Ssmh if (tmp->tmp_dcmd_tag != NULL) 3923275976Ssmh bus_dma_tag_destroy(tmp->tmp_dcmd_tag); 3924265555Sambrisko} 3925265555Sambrisko 3926275976Ssmh/* 3927275976Ssmh * mrsas_issue_blocked_abort_cmd: Aborts previously issued cmd input: 3928275976Ssmh * Adapter soft state Previously issued cmd to be aborted 3929265555Sambrisko * 3930275976Ssmh * This function is used to abort previously issued commands, such as AEN and 3931275976Ssmh * RAID map sync map commands. The abort command is sent as a DCMD internal 3932275976Ssmh * command and subsequently the driver will wait for a return status. The 3933275976Ssmh * max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME seconds. 3934265555Sambrisko */ 3935275976Ssmhstatic int 3936275976Ssmhmrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc, 3937275976Ssmh struct mrsas_mfi_cmd *cmd_to_abort) 3938265555Sambrisko{ 3939275976Ssmh struct mrsas_mfi_cmd *cmd; 3940275976Ssmh struct mrsas_abort_frame *abort_fr; 3941275976Ssmh u_int8_t retcode = 0; 3942275976Ssmh unsigned long total_time = 0; 3943275976Ssmh u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME; 3944265555Sambrisko 3945275976Ssmh cmd = mrsas_get_mfi_cmd(sc); 3946275976Ssmh if (!cmd) { 3947275976Ssmh device_printf(sc->mrsas_dev, "Cannot alloc for abort cmd\n"); 3948275976Ssmh return (1); 3949275976Ssmh } 3950275976Ssmh abort_fr = &cmd->frame->abort; 3951265555Sambrisko 3952275976Ssmh /* Prepare and issue the abort frame */ 3953275976Ssmh abort_fr->cmd = MFI_CMD_ABORT; 3954275976Ssmh abort_fr->cmd_status = 0xFF; 3955275976Ssmh abort_fr->flags = 0; 3956275976Ssmh abort_fr->abort_context = cmd_to_abort->index; 3957275976Ssmh abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr; 3958275976Ssmh abort_fr->abort_mfi_phys_addr_hi = 0; 3959265555Sambrisko 3960275976Ssmh cmd->sync_cmd = 1; 3961275976Ssmh cmd->cmd_status = 0xFF; 3962265555Sambrisko 3963275976Ssmh if (mrsas_issue_dcmd(sc, cmd)) { 3964275976Ssmh device_printf(sc->mrsas_dev, "Fail to send abort command.\n"); 3965275976Ssmh return (1); 3966275976Ssmh } 3967275976Ssmh /* Wait for this cmd to complete */ 3968275976Ssmh sc->chan = (void *)&cmd; 3969275976Ssmh while (1) { 3970275976Ssmh if (cmd->cmd_status == 0xFF) { 3971275976Ssmh tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz); 3972275976Ssmh } else 3973275976Ssmh break; 3974275976Ssmh total_time++; 3975275976Ssmh if (total_time >= max_wait) { 3976275976Ssmh device_printf(sc->mrsas_dev, "Abort cmd timed out after %d sec.\n", max_wait); 3977275976Ssmh retcode = 1; 3978275976Ssmh break; 3979275976Ssmh } 3980275976Ssmh } 3981265555Sambrisko 3982275976Ssmh cmd->sync_cmd = 0; 3983275976Ssmh mrsas_release_mfi_cmd(cmd); 3984275976Ssmh return (retcode); 3985265555Sambrisko} 3986265555Sambrisko 3987275976Ssmh/* 3988275976Ssmh * mrsas_complete_abort: Completes aborting a command input: 3989275976Ssmh * Adapter soft state Cmd that was issued to abort another cmd 3990265555Sambrisko * 3991275976Ssmh * The mrsas_issue_blocked_abort_cmd() function waits for the command status to 3992275976Ssmh * change after sending the command. This function is called from 3993265555Sambrisko * mrsas_complete_mptmfi_passthru() to wake up the sleep thread associated. 3994265555Sambrisko */ 3995275976Ssmhvoid 3996275976Ssmhmrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 3997265555Sambrisko{ 3998275976Ssmh if (cmd->sync_cmd) { 3999275976Ssmh cmd->sync_cmd = 0; 4000275976Ssmh cmd->cmd_status = 0; 4001275976Ssmh sc->chan = (void *)&cmd; 4002275976Ssmh wakeup_one((void *)&sc->chan); 4003275976Ssmh } 4004275976Ssmh return; 4005265555Sambrisko} 4006265555Sambrisko 4007275976Ssmh/* 4008275976Ssmh * mrsas_aen_handler: AEN processing callback function from thread context 4009275976Ssmh * input: Adapter soft state 4010265555Sambrisko * 4011275976Ssmh * Asynchronous event handler 4012265555Sambrisko */ 4013275976Ssmhvoid 4014275976Ssmhmrsas_aen_handler(struct mrsas_softc *sc) 4015265555Sambrisko{ 4016265555Sambrisko union mrsas_evt_class_locale class_locale; 4017275976Ssmh int doscan = 0; 4018265555Sambrisko u_int32_t seq_num; 4019265555Sambrisko int error; 4020265555Sambrisko 4021265555Sambrisko if (!sc) { 4022265555Sambrisko device_printf(sc->mrsas_dev, "invalid instance!\n"); 4023265555Sambrisko return; 4024265555Sambrisko } 4025265555Sambrisko if (sc->evt_detail_mem) { 4026265555Sambrisko switch (sc->evt_detail_mem->code) { 4027275976Ssmh case MR_EVT_PD_INSERTED: 4028275976Ssmh mrsas_get_pd_list(sc); 4029275976Ssmh mrsas_bus_scan_sim(sc, sc->sim_1); 4030275976Ssmh doscan = 0; 4031275976Ssmh break; 4032275976Ssmh case MR_EVT_PD_REMOVED: 4033275976Ssmh mrsas_get_pd_list(sc); 4034275976Ssmh mrsas_bus_scan_sim(sc, sc->sim_1); 4035275976Ssmh doscan = 0; 4036275976Ssmh break; 4037275976Ssmh case MR_EVT_LD_OFFLINE: 4038275976Ssmh case MR_EVT_CFG_CLEARED: 4039275976Ssmh case MR_EVT_LD_DELETED: 4040275976Ssmh mrsas_bus_scan_sim(sc, sc->sim_0); 4041275976Ssmh doscan = 0; 4042275976Ssmh break; 4043275976Ssmh case MR_EVT_LD_CREATED: 4044275976Ssmh mrsas_get_ld_list(sc); 4045275976Ssmh mrsas_bus_scan_sim(sc, sc->sim_0); 4046275976Ssmh doscan = 0; 4047275976Ssmh break; 4048275976Ssmh case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: 4049275976Ssmh case MR_EVT_FOREIGN_CFG_IMPORTED: 4050275976Ssmh case MR_EVT_LD_STATE_CHANGE: 4051275976Ssmh doscan = 1; 4052275976Ssmh break; 4053275976Ssmh default: 4054275976Ssmh doscan = 0; 4055275976Ssmh break; 4056265555Sambrisko } 4057265555Sambrisko } else { 4058265555Sambrisko device_printf(sc->mrsas_dev, "invalid evt_detail\n"); 4059265555Sambrisko return; 4060265555Sambrisko } 4061265555Sambrisko if (doscan) { 4062265555Sambrisko mrsas_get_pd_list(sc); 4063265555Sambrisko mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 1\n"); 4064265555Sambrisko mrsas_bus_scan_sim(sc, sc->sim_1); 4065265555Sambrisko mrsas_get_ld_list(sc); 4066265555Sambrisko mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 0\n"); 4067265555Sambrisko mrsas_bus_scan_sim(sc, sc->sim_0); 4068265555Sambrisko } 4069265555Sambrisko seq_num = sc->evt_detail_mem->seq_num + 1; 4070265555Sambrisko 4071275976Ssmh /* Register AEN with FW for latest sequence number plus 1 */ 4072265555Sambrisko class_locale.members.reserved = 0; 4073265555Sambrisko class_locale.members.locale = MR_EVT_LOCALE_ALL; 4074265555Sambrisko class_locale.members.class = MR_EVT_CLASS_DEBUG; 4075265555Sambrisko 4076275976Ssmh if (sc->aen_cmd != NULL) 4077275976Ssmh return; 4078275976Ssmh 4079265555Sambrisko mtx_lock(&sc->aen_lock); 4080265555Sambrisko error = mrsas_register_aen(sc, seq_num, 4081275976Ssmh class_locale.word); 4082265555Sambrisko mtx_unlock(&sc->aen_lock); 4083265555Sambrisko 4084265555Sambrisko if (error) 4085265555Sambrisko device_printf(sc->mrsas_dev, "register aen failed error %x\n", error); 4086265555Sambrisko 4087265555Sambrisko} 4088265555Sambrisko 4089265555Sambrisko 4090275976Ssmh/* 4091275976Ssmh * mrsas_complete_aen: Completes AEN command 4092275976Ssmh * input: Adapter soft state 4093275976Ssmh * Cmd that was issued to abort another cmd 4094265555Sambrisko * 4095275976Ssmh * This function will be called from ISR and will continue event processing from 4096275976Ssmh * thread context by enqueuing task in ev_tq (callback function 4097275976Ssmh * "mrsas_aen_handler"). 4098265555Sambrisko */ 4099275976Ssmhvoid 4100275976Ssmhmrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 4101265555Sambrisko{ 4102265555Sambrisko /* 4103275976Ssmh * Don't signal app if it is just an aborted previously registered 4104275976Ssmh * aen 4105275976Ssmh */ 4106265555Sambrisko if ((!cmd->abort_aen) && (sc->remove_in_progress == 0)) { 4107275976Ssmh sc->mrsas_aen_triggered = 1; 4108284267Skadesai mtx_lock(&sc->aen_lock); 4109275976Ssmh if (sc->mrsas_poll_waiting) { 4110275976Ssmh sc->mrsas_poll_waiting = 0; 4111275976Ssmh selwakeup(&sc->mrsas_select); 4112275976Ssmh } 4113284267Skadesai mtx_unlock(&sc->aen_lock); 4114275976Ssmh } else 4115265555Sambrisko cmd->abort_aen = 0; 4116265555Sambrisko 4117265555Sambrisko sc->aen_cmd = NULL; 4118265555Sambrisko mrsas_release_mfi_cmd(cmd); 4119265555Sambrisko 4120265555Sambrisko if (!sc->remove_in_progress) 4121265555Sambrisko taskqueue_enqueue(sc->ev_tq, &sc->ev_task); 4122265555Sambrisko 4123265555Sambrisko return; 4124265555Sambrisko} 4125265555Sambrisko 4126265555Sambriskostatic device_method_t mrsas_methods[] = { 4127275976Ssmh DEVMETHOD(device_probe, mrsas_probe), 4128275976Ssmh DEVMETHOD(device_attach, mrsas_attach), 4129275976Ssmh DEVMETHOD(device_detach, mrsas_detach), 4130275976Ssmh DEVMETHOD(device_suspend, mrsas_suspend), 4131275976Ssmh DEVMETHOD(device_resume, mrsas_resume), 4132275976Ssmh DEVMETHOD(bus_print_child, bus_generic_print_child), 4133275976Ssmh DEVMETHOD(bus_driver_added, bus_generic_driver_added), 4134275976Ssmh {0, 0} 4135265555Sambrisko}; 4136265555Sambrisko 4137265555Sambriskostatic driver_t mrsas_driver = { 4138275976Ssmh "mrsas", 4139275976Ssmh mrsas_methods, 4140275976Ssmh sizeof(struct mrsas_softc) 4141265555Sambrisko}; 4142265555Sambrisko 4143275976Ssmhstatic devclass_t mrsas_devclass; 4144275976Ssmh 4145265555SambriskoDRIVER_MODULE(mrsas, pci, mrsas_driver, mrsas_devclass, 0, 0); 4146275976SsmhMODULE_DEPEND(mrsas, cam, 1, 1, 1); 4147