Print this page
OS-1997 mpt_sas: expose LED controls to libtopo
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>

*** 369,380 **** uint32_t *status, uint8_t cmd); static dev_info_t *mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask); static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask); ! static int mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, ! uint32_t slotstatus); /* * Enumeration / DR functions */ --- 369,379 ---- uint32_t *status, uint8_t cmd); static dev_info_t *mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask); static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask); ! static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt); /* * Enumeration / DR functions */
*** 6451,6461 **** break; } } mutex_enter(&mpt->m_mutex); ! if (mptsas_set_led_status(mpt, ptgt, 0) != DDI_SUCCESS) { NDBG14(("mptsas: clear LED for tgt %x failed", ptgt->m_slot_num)); } if (rval == DDI_SUCCESS) { mptsas_tgt_free(&mpt->m_active->m_tgttbl, --- 6450,6461 ---- break; } } mutex_enter(&mpt->m_mutex); ! ptgt->m_led_status = 0; ! if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) { NDBG14(("mptsas: clear LED for tgt %x failed", ptgt->m_slot_num)); } if (rval == DDI_SUCCESS) { mptsas_tgt_free(&mpt->m_active->m_tgttbl,
*** 11951,11960 **** --- 11951,12020 ---- mutex_exit(&mpt->m_mutex); return (status); } static int + led_control(mptsas_t *mpt, intptr_t data, int mode) + { + int ret = 0; + mptsas_led_control_t lc; + mptsas_target_t *ptgt; + + if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) { + return (EFAULT); + } + + if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET && + lc.Command != MPTSAS_LEDCTL_FLAG_GET) || + lc.Led < MPTSAS_LEDCTL_LED_IDENT || + lc.Led > MPTSAS_LEDCTL_LED_OK2RM || + (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 && + lc.LedStatus != 1)) { + return (EINVAL); + } + + /* Locate the target we're interrogating... */ + mutex_enter(&mpt->m_mutex); + ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl, + MPTSAS_HASH_FIRST); + while (ptgt != NULL) { + if (ptgt->m_enclosure == lc.Enclosure && + ptgt->m_slot_num == lc.Slot) { + break; + } + ptgt = (mptsas_target_t *)mptsas_hash_traverse( + &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT); + } + if (ptgt == NULL) { + /* We could not find a target for that enclosure/slot. */ + mutex_exit(&mpt->m_mutex); + return (ENOENT); + } + + if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) { + /* Update our internal LED state. */ + ptgt->m_led_status &= ~(1 << (lc.Led - 1)); + ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1); + + /* Flush it to the controller. */ + ret = mptsas_flush_led_status(mpt, ptgt); + mutex_exit(&mpt->m_mutex); + return (ret); + } + + /* Return our internal LED state. */ + lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1; + mutex_exit(&mpt->m_mutex); + + if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) { + return (EFAULT); + } + + return (0); + } + + static int get_disk_info(mptsas_t *mpt, intptr_t data, int mode) { int i = 0; int count = 0; int ret = 0;
*** 12127,12161 **** if (cmd == DEVCTL_DEVICE_ONLINE) { ptgt->m_tgt_unconfigured = 0; } else if (cmd == DEVCTL_DEVICE_OFFLINE) { ptgt->m_tgt_unconfigured = 1; } - slotstatus = 0; - #ifdef MPTSAS_GET_LED - /* - * The get led status can't get a valid/reasonable - * state, so ignore the get led status, and write the - * required value directly - */ - if (mptsas_get_led_status(mpt, ptgt, &slotstatus) != - DDI_SUCCESS) { - NDBG14(("mptsas_ioctl: get LED for tgt %s " - "failed %x", addr, slotstatus)); - slotstatus = 0; - } - NDBG14(("mptsas_ioctl: LED status %x for %s", - slotstatus, addr)); - #endif if (cmd == DEVCTL_DEVICE_OFFLINE) { ! slotstatus |= ! MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE; } else { ! slotstatus &= ! ~MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE; } ! if (mptsas_set_led_status(mpt, ptgt, slotstatus) != ! DDI_SUCCESS) { NDBG14(("mptsas_ioctl: set LED for tgt %s " "failed %x", addr, slotstatus)); } mutex_exit(&mpt->m_mutex); ndi_dc_freehdl(dcp); --- 12187,12204 ---- if (cmd == DEVCTL_DEVICE_ONLINE) { ptgt->m_tgt_unconfigured = 0; } else if (cmd == DEVCTL_DEVICE_OFFLINE) { ptgt->m_tgt_unconfigured = 1; } if (cmd == DEVCTL_DEVICE_OFFLINE) { ! ptgt->m_led_status |= ! (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)); } else { ! ptgt->m_led_status &= ! ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)); } ! if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) { NDBG14(("mptsas_ioctl: set LED for tgt %s " "failed %x", addr, slotstatus)); } mutex_exit(&mpt->m_mutex); ndi_dc_freehdl(dcp);
*** 12164,12173 **** --- 12207,12219 ---- } switch (cmd) { case MPTIOCTL_GET_DISK_INFO: status = get_disk_info(mpt, data, mode); break; + case MPTIOCTL_LED_CONTROL: + status = led_control(mpt, data, mode); + break; case MPTIOCTL_UPDATE_FLASH: if (ddi_copyin((void *)data, &flashdata, sizeof (struct mptsas_update_flash), mode)) { status = EFAULT; break;
*** 14624,14635 **** if ((!MDI_PI_IS_ONLINE(*pip)) && (!MDI_PI_IS_STANDBY(*pip)) && (ptgt->m_tgt_unconfigured == 0)) { rval = mdi_pi_online(*pip, 0); mutex_enter(&mpt->m_mutex); ! (void) mptsas_set_led_status(mpt, ptgt, ! 0); mutex_exit(&mpt->m_mutex); } else { rval = DDI_SUCCESS; } if (rval != DDI_SUCCESS) { --- 14670,14682 ---- if ((!MDI_PI_IS_ONLINE(*pip)) && (!MDI_PI_IS_STANDBY(*pip)) && (ptgt->m_tgt_unconfigured == 0)) { rval = mdi_pi_online(*pip, 0); mutex_enter(&mpt->m_mutex); ! ptgt->m_led_status = 0; ! (void) mptsas_flush_led_status(mpt, ! ptgt); mutex_exit(&mpt->m_mutex); } else { rval = DDI_SUCCESS; } if (rval != DDI_SUCCESS) {
*** 14882,14893 **** } NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr)); mdi_rtn = mdi_pi_online(*pip, 0); if (mdi_rtn == MDI_SUCCESS) { mutex_enter(&mpt->m_mutex); ! if (mptsas_set_led_status(mpt, ptgt, 0) != ! DDI_SUCCESS) { NDBG14(("mptsas: clear LED for slot %x " "failed", ptgt->m_slot_num)); } mutex_exit(&mpt->m_mutex); } --- 14929,14940 ---- } NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr)); mdi_rtn = mdi_pi_online(*pip, 0); if (mdi_rtn == MDI_SUCCESS) { mutex_enter(&mpt->m_mutex); ! ptgt->m_led_status = 0; ! if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) { NDBG14(("mptsas: clear LED for slot %x " "failed", ptgt->m_slot_num)); } mutex_exit(&mpt->m_mutex); }
*** 15244,15255 **** */ ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH); } if (ndi_rtn == NDI_SUCCESS) { mutex_enter(&mpt->m_mutex); ! if (mptsas_set_led_status(mpt, ptgt, 0) != ! DDI_SUCCESS) { NDBG14(("mptsas: clear LED for tgt %x " "failed", ptgt->m_slot_num)); } mutex_exit(&mpt->m_mutex); } --- 15291,15302 ---- */ ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH); } if (ndi_rtn == NDI_SUCCESS) { mutex_enter(&mpt->m_mutex); ! ptgt->m_led_status = 0; ! if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) { NDBG14(("mptsas: clear LED for tgt %x " "failed", ptgt->m_slot_num)); } mutex_exit(&mpt->m_mutex); }
*** 16146,16172 **** ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum); } return (ptgt); } - #ifdef MPTSAS_GET_LED - static int - mptsas_get_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, - uint32_t *slotstatus) - { - return (mptsas_send_sep(mpt, ptgt, slotstatus, - MPI2_SEP_REQ_ACTION_READ_STATUS)); - } - #endif static int ! mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t slotstatus) { NDBG14(("mptsas_ioctl: set LED status %x for slot %x", slotstatus, ptgt->m_slot_num)); return (mptsas_send_sep(mpt, ptgt, &slotstatus, MPI2_SEP_REQ_ACTION_WRITE_STATUS)); } /* * send sep request, use enclosure/slot addressing */ static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t *status, uint8_t act) --- 16193,16222 ---- ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum); } return (ptgt); } static int ! mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt) { + uint32_t slotstatus = 0; + + /* Build an MPI2 Slot Status based on our view of the world */ + if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1))) + slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST; + if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1))) + slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT; + if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1))) + slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE; + + /* Write it to the controller */ NDBG14(("mptsas_ioctl: set LED status %x for slot %x", slotstatus, ptgt->m_slot_num)); return (mptsas_send_sep(mpt, ptgt, &slotstatus, MPI2_SEP_REQ_ACTION_WRITE_STATUS)); } + /* * send sep request, use enclosure/slot addressing */ static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t *status, uint8_t act)