# HG changeset patch # User Dan McDonald # Date 1365100009 14400 # Node ID f0c04f0fa2ad5f7453d4ca8377cf2214e51d782b # Parent 4ba0940c01f8a893f6cd73a1fb2e910fb9b89191 3500 Support LSI SAS2008 (Falcon) Skinny FW for mr_sas(7D) Reviewed by: Gordon Ross Reviewed by: Saso Kiselkov Reviewed by: Richard Lowe Approved by: Garrett D'Amore diff -r 4ba0940c01f8 -r f0c04f0fa2ad usr/src/cmd/mdb/common/modules/mr_sas/mr_sas.c --- a/usr/src/cmd/mdb/common/modules/mr_sas/mr_sas.c Sun Mar 31 04:00:15 2013 +0000 +++ b/usr/src/cmd/mdb/common/modules/mr_sas/mr_sas.c Thu Apr 04 14:26:49 2013 -0400 @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + #include #include #include @@ -57,15 +61,16 @@ } void -display_targets(struct mrsas_instance m, int verbose) +display_targets(struct mrsas_instance *m, int verbose) { int tgt; - struct mrsas_ld *mr_ldp; + struct mrsas_ld mr_ldp[MRDRV_MAX_LD]; + struct mrsas_tbolt_pd mr_pdp[MRSAS_TBOLT_PD_TGT_MAX]; char device_path[PATH_MAX]; if (verbose) { *device_path = 0; - if (construct_path((uintptr_t)m.dip, device_path) != DCMD_OK) { + if (construct_path((uintptr_t)m->dip, device_path) != DCMD_OK) { strcpy(device_path, "couldn't determine device path"); } } @@ -73,29 +78,41 @@ mdb_printf("\n"); if (verbose) mdb_printf("%s\n", device_path); - mdb_printf("dev_type target\n"); - mdb_printf("----------"); - mdb_printf("\n"); + mdb_printf("Physical/Logical Target\n"); + mdb_printf("-----------------------\n"); + + if (mdb_vread(&mr_ldp, sizeof (mr_ldp), (uintptr_t)m->mr_ld_list) + == -1 || + mdb_vread(&mr_pdp, sizeof (mr_pdp), (uintptr_t)m->mr_tbolt_pd_list) + == -1) { + mdb_warn("can't read list of disks"); + return; + } + for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) { - mr_ldp = (struct mrsas_ld *)&m.mr_ld_list[tgt]; - if ((mr_ldp != NULL) && (mr_ldp->dip != NULL) && - (mr_ldp->lun_type == MRSAS_LD_LUN)) { - mdb_printf("sd %d", tgt); - mdb_printf("\n"); + if (mr_ldp[tgt].dip != NULL && + mr_ldp[tgt].lun_type == MRSAS_LD_LUN) { + mdb_printf("Logical sd %d\n", tgt); + } + } + for (tgt = 0; tgt < MRSAS_TBOLT_PD_TGT_MAX; tgt++) { + if (mr_pdp[tgt].dip != NULL && + mr_pdp[tgt].lun_type == MRSAS_TBOLT_PD_LUN) { + mdb_printf("Physical sd %d\n", tgt); } } mdb_printf("\n"); } void -display_deviceinfo(struct mrsas_instance m) +display_deviceinfo(struct mrsas_instance *m) { uint16_t vid, did, svid, sid; - vid = m.vendor_id; - did = m.device_id; - svid = m.subsysvid; - sid = m.subsysid; + vid = m->vendor_id; + did = m->device_id; + svid = m->subsysvid; + sid = m->subsysid; mdb_printf("\n"); mdb_printf("vendor_id device_id subsysvid subsysid"); @@ -178,10 +195,10 @@ mdb_printf("\n"); if (target_info) - display_targets(m, verbose); + display_targets(&m, verbose); if (device_info) - display_deviceinfo(m); + display_deviceinfo(&m); return (rv); } diff -r 4ba0940c01f8 -r f0c04f0fa2ad usr/src/pkg/manifests/driver-storage-mr_sas.mf --- a/usr/src/pkg/manifests/driver-storage-mr_sas.mf Sun Mar 31 04:00:15 2013 +0000 +++ b/usr/src/pkg/manifests/driver-storage-mr_sas.mf Thu Apr 04 14:26:49 2013 -0400 @@ -21,7 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright 2012 Nexenta Systems, Inc. All rights reserved. +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. # # @@ -46,11 +46,15 @@ alias=pci1000,79 \ alias=pciex1000,5b \ alias=pciex1000,5d \ + alias=pciex1000,71 \ + alias=pciex1000,73 \ alias=pciex1000,78 \ alias=pciex1000,79 $(i386_ONLY)driver name=mr_sas class=scsi-self-identifying \ alias=pciex1000,5b \ alias=pciex1000,5d \ + alias=pciex1000,71 \ + alias=pciex1000,73 \ alias=pciex1000,78 \ alias=pciex1000,79 file path=kernel/drv/$(ARCH64)/mr_sas group=sys diff -r 4ba0940c01f8 -r f0c04f0fa2ad usr/src/uts/common/io/mr_sas/mr_sas.c --- a/usr/src/uts/common/io/mr_sas/mr_sas.c Sun Mar 31 04:00:15 2013 +0000 +++ b/usr/src/uts/common/io/mr_sas/mr_sas.c Thu Apr 04 14:26:49 2013 -0400 @@ -44,7 +44,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - * Copyright 2012 Nexenta System, Inc. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #include @@ -80,6 +80,15 @@ #include #include +/* Macros to help Skinny and stock 2108/MFI live together. */ +#define WR_IB_PICK_QPORT(addr, instance) \ + if ((instance)->skinny) { \ + WR_IB_LOW_QPORT((addr), (instance)); \ + WR_IB_HIGH_QPORT(0, (instance)); \ + } else { \ + WR_IB_QPORT((addr), (instance)); \ + } + /* * Local static data */ @@ -135,9 +144,6 @@ static uint_t mrsas_isr(); static uint_t mrsas_softintr(); static void mrsas_undo_resources(dev_info_t *, struct mrsas_instance *); -static struct mrsas_cmd *get_mfi_pkt(struct mrsas_instance *); -static void return_mfi_pkt(struct mrsas_instance *, - struct mrsas_cmd *); static void free_space_for_mfi(struct mrsas_instance *); static uint32_t read_fw_status_reg_ppc(struct mrsas_instance *); @@ -575,6 +581,18 @@ instance->tbolt = 1; break; + case PCI_DEVICE_ID_LSI_SKINNY: + case PCI_DEVICE_ID_LSI_SKINNY_NEW: + /* + * FALLTHRU to PPC-style functions, but mark this + * instance as Skinny, because the register set is + * slightly different (See WR_IB_PICK_QPORT), and + * certain other features are available to a Skinny + * HBA. + */ + instance->skinny = 1; + /* FALLTHRU */ + case PCI_DEVICE_ID_LSI_2108VDE: case PCI_DEVICE_ID_LSI_2108V: con_log(CL_ANN, (CE_NOTE, @@ -815,15 +833,11 @@ tran->tran_tgt_init = mrsas_tran_tgt_init; tran->tran_tgt_probe = scsi_hba_probe; tran->tran_tgt_free = mrsas_tran_tgt_free; - if (instance->tbolt) { - tran->tran_init_pkt = - mrsas_tbolt_tran_init_pkt; - tran->tran_start = - mrsas_tbolt_tran_start; - } else { - tran->tran_init_pkt = mrsas_tran_init_pkt; - tran->tran_start = mrsas_tran_start; - } + tran->tran_init_pkt = mrsas_tran_init_pkt; + if (instance->tbolt) + tran->tran_start = mrsas_tbolt_tran_start; + else + tran->tran_start = mrsas_tran_start; tran->tran_abort = mrsas_tran_abort; tran->tran_reset = mrsas_tran_reset; tran->tran_getcap = mrsas_tran_getcap; @@ -940,7 +954,7 @@ instance->unroll.ldlist_buff = 1; #ifdef PDSUPPORT - if (instance->tbolt) { + if (instance->tbolt || instance->skinny) { instance->mr_tbolt_pd_max = MRSAS_TBOLT_PD_TGT_MAX; instance->mr_tbolt_pd_list = kmem_zalloc(MRSAS_TBOLT_GET_PD_MAX(instance) * @@ -1663,7 +1677,7 @@ } #ifdef PDSUPPORT - else if (instance->tbolt) { + else if (instance->tbolt || instance->skinny) { if (instance->mr_tbolt_pd_list[tgt].dip == NULL) { mutex_enter(&instance->config_dev_mtx); instance->mr_tbolt_pd_list[tgt].dip = tgt_dip; @@ -1701,7 +1715,7 @@ } #ifdef PDSUPPORT - else if (instance->tbolt) { + else if (instance->tbolt || instance->skinny) { mutex_enter(&instance->config_dev_mtx); instance->mr_tbolt_pd_list[tgt].dip = NULL; mutex_exit(&instance->config_dev_mtx); @@ -1938,7 +1952,7 @@ DTRACE_PROBE2(start_tran_err, uint16_t, instance->fw_outstanding, uint16_t, instance->max_fw_cmds); - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); return (TRAN_BUSY); } @@ -1987,7 +2001,7 @@ (void) mrsas_common_check(instance, cmd); DTRACE_PROBE2(start_nointr_done, uint8_t, hdr->cmd, uint8_t, hdr->cmd_status); - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); if (pkt->pkt_comp) { (*pkt->pkt_comp)(pkt); @@ -2461,8 +2475,8 @@ * After clearing the frame buffer the context id of the * frame buffer SHOULD be restored back. */ -static struct mrsas_cmd * -get_mfi_pkt(struct mrsas_instance *instance) +struct mrsas_cmd * +mrsas_get_mfi_pkt(struct mrsas_instance *instance) { mlist_t *head = &instance->cmd_pool_list; struct mrsas_cmd *cmd = NULL; @@ -2509,8 +2523,8 @@ /* * return_mfi_pkt : Return a cmd to free command pool */ -static void -return_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd) +void +mrsas_return_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd) { mutex_enter(&instance->cmd_pool_mtx); /* use mlist_add_tail for debug assistance */ @@ -3162,7 +3176,13 @@ INIT_LIST_HEAD(&instance->cmd_pend_list); INIT_LIST_HEAD(&instance->app_cmd_pool_list); - reserve_cmd = MRSAS_APP_RESERVED_CMDS; + /* + * When max_cmd is lower than MRSAS_APP_RESERVED_CMDS, how do I split + * into app_cmd and regular cmd? For now, just take + * max(1/8th of max, 4); + */ + reserve_cmd = min(MRSAS_APP_RESERVED_CMDS, + max(max_cmd >> 3, MRSAS_APP_MIN_RESERVED_CMDS)); for (i = 0; i < reserve_cmd; i++) { cmd = instance->cmd_list[i]; @@ -3276,7 +3296,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { @@ -3299,7 +3319,7 @@ if (!ci) { cmn_err(CE_WARN, "Failed to alloc mem for ctrl info"); - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); return (DDI_FAILURE); } @@ -3358,7 +3378,7 @@ if (instance->tbolt) { return_raid_msg_mfi_pkt(instance, cmd); } else { - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); } return (ret); @@ -3381,7 +3401,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { @@ -3434,7 +3454,7 @@ if (instance->tbolt) { return_raid_msg_mfi_pkt(instance, cmd); } else { - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); } atomic_add_16(&instance->fw_outstanding, (-1)); @@ -3569,7 +3589,12 @@ } /* Build INIT command */ - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); + if (cmd == NULL) { + DTRACE_PROBE2(init_adapter_mfi_err, uint16_t, + instance->fw_outstanding, uint16_t, instance->max_fw_cmds); + return (DDI_FAILURE); + } if (mrsas_build_init_cmd(instance, &cmd) != DDI_SUCCESS) { con_log(CL_ANN, @@ -3589,7 +3614,7 @@ if (mrsas_common_check(instance, cmd) != DDI_SUCCESS) goto fail_fw_init; - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); if (ctio_enable && (instance->func_ptr->read_fw_status_reg(instance) & 0x04000000)) { @@ -3599,6 +3624,8 @@ instance->flag_ieee = 0; } + ASSERT(!instance->skinny || instance->flag_ieee); + instance->unroll.alloc_space_mfi = 1; instance->unroll.verBuff = 1; @@ -3609,7 +3636,7 @@ (void) mrsas_free_dma_obj(instance, instance->drv_ver_dma_obj); fail_undo_alloc_mfi_space: - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); free_space_for_mfi(instance); return (DDI_FAILURE); @@ -3761,7 +3788,7 @@ } if (mrsas_common_check(instance, cmd) != DDI_SUCCESS) { - return_mfi_pkt(instance, cmd); + return_mfi_app_pkt(instance, cmd); return (DDI_FAILURE); } @@ -3814,7 +3841,7 @@ * to be set */ /* WR_IB_MSG_0(MFI_INIT_CLEAR_HANDSHAKE, instance); */ - if (!instance->tbolt) { + if (!instance->tbolt && !instance->skinny) { WR_IB_DOORBELL(MFI_INIT_CLEAR_HANDSHAKE | MFI_INIT_HOTPLUG, instance); } else { @@ -3833,7 +3860,7 @@ * (MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG) * to be set */ - if (!instance->tbolt) { + if (!instance->tbolt && !instance->skinny) { WR_IB_DOORBELL(MFI_INIT_HOTPLUG, instance); } else { WR_RESERVED0_REGISTER(MFI_INIT_HOTPLUG, @@ -3853,7 +3880,7 @@ * to be set */ /* WR_IB_DOORBELL(MFI_INIT_READY, instance); */ - if (!instance->tbolt) { + if (!instance->tbolt && !instance->skinny) { WR_IB_DOORBELL(MFI_RESET_FLAGS, instance); } else { WR_RESERVED0_REGISTER(MFI_RESET_FLAGS, @@ -3937,7 +3964,8 @@ } }; - if (!instance->tbolt) { + /* This may also need to apply to Skinny, but for now, don't worry. */ + if (!instance->tbolt && !instance->skinny) { fw_ctrl = RD_IB_DOORBELL(instance); con_log(CL_ANN1, (CE_CONT, "mfi_state_transition_to_ready:FW ctrl = 0x%x", fw_ctrl)); @@ -3976,7 +4004,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { @@ -4052,7 +4080,7 @@ if (instance->tbolt) { return_raid_msg_mfi_pkt(instance, cmd); } else { - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); } return (ret); @@ -4105,7 +4133,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { @@ -4151,7 +4179,7 @@ if (instance->tbolt) { return_raid_msg_mfi_pkt(instance, cmd); } else { - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); } } @@ -4251,7 +4279,7 @@ #ifdef PDSUPPORT case MR_EVT_PD_REMOVED_EXT: { - if (instance->tbolt) { + if (instance->tbolt || instance->skinny) { pd_addr = &evt_detail->args.pd_addr; dtype = pd_addr->scsi_dev_type; con_log(CL_DLEVEL1, (CE_NOTE, @@ -4275,7 +4303,7 @@ } /* End of MR_EVT_PD_REMOVED_EXT */ case MR_EVT_PD_INSERTED_EXT: { - if (instance->tbolt) { + if (instance->tbolt || instance->skinny) { rval = mrsas_service_evt(instance, ddi_get16(acc_handle, &evt_detail->args.pd.device_id), @@ -4289,7 +4317,7 @@ } /* End of MR_EVT_PD_INSERTED_EXT */ case MR_EVT_PD_STATE_CHANGE: { - if (instance->tbolt) { + if (instance->tbolt || instance->skinny) { tgt = ddi_get16(acc_handle, &evt_detail->args.pd.device_id); if ((evt_detail->args.pd_state.prevState == @@ -4525,6 +4553,12 @@ inq = (struct scsi_inquiry *) acmd->cmd_buf->b_un.b_addr; +#ifdef PDSUPPORT + if (hdr->cmd_status == MFI_STAT_OK) { + display_scsi_inquiry( + (caddr_t)inq); + } +#else /* don't expose physical drives to OS */ if (acmd->islogical && (hdr->cmd_status == MFI_STAT_OK)) { @@ -4541,6 +4575,7 @@ hdr->cmd_status = MFI_STAT_DEVICE_NOT_FOUND; } +#endif /* PDSUPPORT */ } } @@ -4649,19 +4684,14 @@ } } + mrsas_return_mfi_pkt(instance, cmd); + /* Call the callback routine */ if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp) { - - con_log(CL_DLEVEL1, (CE_NOTE, "mrsas_softintr: " - "posting to scsa cmd %p index %x pkt %p " - "time %llx", (void *)cmd, cmd->index, - (void *)pkt, gethrtime())); (*pkt->pkt_comp)(pkt); - } - return_mfi_pkt(instance, cmd); break; case MFI_CMD_OP_SMP: @@ -5088,7 +5118,7 @@ *cmd_done = 0; /* get the command packet */ - if (!(cmd = get_mfi_pkt(instance))) { + if (!(cmd = mrsas_get_mfi_pkt(instance))) { DTRACE_PROBE2(build_cmd_mfi_err, uint16_t, instance->fw_outstanding, uint16_t, instance->max_fw_cmds); return (NULL); @@ -5136,7 +5166,7 @@ /* * case SCMD_SYNCHRONIZE_CACHE: * flush_cache(instance); - * return_mfi_pkt(instance, cmd); + * mrsas_return_mfi_pkt(instance, cmd); * *cmd_done = 1; * * return (NULL); @@ -5245,7 +5275,7 @@ break; } - /* fall through For all non-rd/wr cmds */ + /* fall through For all non-rd/wr and physical disk cmds */ default: switch (pkt->pkt_cdbp[0]) { @@ -5260,7 +5290,7 @@ case 0x3: case 0x4: (void) mrsas_mode_sense_build(pkt); - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); *cmd_done = 1; return (NULL); } @@ -6294,7 +6324,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { con_log(CL_ANN, (CE_WARN, "mr_sas: " @@ -6338,7 +6368,7 @@ if (instance->tbolt) { return_raid_msg_mfi_pkt(instance, cmd); } else { - return_mfi_pkt(instance, cmd); + mrsas_return_mfi_pkt(instance, cmd); } return (rval); @@ -6435,7 +6465,7 @@ if (instance->tbolt) { cmd = get_raid_msg_mfi_pkt(instance); } else { - cmd = get_mfi_pkt(instance); + cmd = mrsas_get_mfi_pkt(instance); } if (!cmd) { @@ -6728,7 +6758,7 @@ mutex_enter(&instance->reg_write_mtx); /* Issue the command to the FW */ - WR_IB_QPORT((cmd->frame_phys_addr) | + WR_IB_PICK_QPORT((cmd->frame_phys_addr) | (((cmd->frame_count - 1) << 1) | 1), instance); mutex_exit(&instance->reg_write_mtx); @@ -6739,10 +6769,10 @@ */ static int issue_cmd_in_sync_mode_ppc(struct mrsas_instance *instance, -struct mrsas_cmd *cmd) + struct mrsas_cmd *cmd) { int i; - uint32_t msecs = MFI_POLL_TIMEOUT_SECS * (10 * MILLISEC); + uint32_t msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC; struct mrsas_header *hdr = &cmd->frame->hdr; con_log(CL_ANN1, (CE_NOTE, "issue_cmd_in_sync_mode_ppc: called")); @@ -6755,7 +6785,7 @@ con_log(CL_ANN1, (CE_NOTE, "sync_mode_ppc: " "issue and return in reset case\n")); - WR_IB_QPORT((cmd->frame_phys_addr) | + WR_IB_PICK_QPORT((cmd->frame_phys_addr) | (((cmd->frame_count - 1) << 1) | 1), instance); return (DDI_SUCCESS); @@ -6768,7 +6798,7 @@ mutex_enter(&instance->reg_write_mtx); /* Issue the command to the FW */ - WR_IB_QPORT((cmd->frame_phys_addr) | + WR_IB_PICK_QPORT((cmd->frame_phys_addr) | (((cmd->frame_count - 1) << 1) | 1), instance); mutex_exit(&instance->reg_write_mtx); @@ -6810,7 +6840,7 @@ ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags); /* issue the frame using inbound queue port */ - WR_IB_QPORT((cmd->frame_phys_addr) | + WR_IB_PICK_QPORT((cmd->frame_phys_addr) | (((cmd->frame_count - 1) << 1) | 1), instance); /* wait for cmd_status to change from 0xFF */ @@ -6837,11 +6867,16 @@ con_log(CL_ANN1, (CE_NOTE, "enable_intr_ppc: called")); - /* WR_OB_DOORBELL_CLEAR(0xFFFFFFFF, instance); */ - WR_OB_DOORBELL_CLEAR(OB_DOORBELL_CLEAR_MASK, instance); - - /* WR_OB_INTR_MASK(~0x80000000, instance); */ - WR_OB_INTR_MASK(~(MFI_REPLY_2108_MESSAGE_INTR_MASK), instance); + if (instance->skinny) { + /* For SKINNY, write ~0x1, from BSD's mfi driver. */ + WR_OB_INTR_MASK(0xfffffffe, instance); + } else { + /* WR_OB_DOORBELL_CLEAR(0xFFFFFFFF, instance); */ + WR_OB_DOORBELL_CLEAR(OB_DOORBELL_CLEAR_MASK, instance); + + /* WR_OB_INTR_MASK(~0x80000000, instance); */ + WR_OB_INTR_MASK(~(MFI_REPLY_2108_MESSAGE_INTR_MASK), instance); + } /* dummy read to force PCI flush */ mask = RD_OB_INTR_MASK(instance); @@ -6860,7 +6895,8 @@ con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: before : " "outbound_intr_mask = 0x%x", RD_OB_INTR_MASK(instance))); - /* WR_OB_INTR_MASK(0xFFFFFFFF, instance); */ + /* For now, assume there are no extras needed for Skinny support. */ + WR_OB_INTR_MASK(OB_INTR_MASK, instance); con_log(CL_ANN1, (CE_NOTE, "disable_intr_ppc: after : " @@ -6886,6 +6922,10 @@ con_log(CL_ANN1, (CE_NOTE, "intr_ack_ppc: status = 0x%x", status)); + /* + * NOTE: Some drivers call out SKINNY here, but the return is the same + * for SKINNY and 2108. + */ if (!(status & MFI_REPLY_2108_MESSAGE_INTR)) { ret = DDI_INTR_UNCLAIMED; } @@ -6898,8 +6938,16 @@ if (ret == DDI_INTR_UNCLAIMED) { return (ret); } - /* clear the interrupt by writing back the same value */ - WR_OB_DOORBELL_CLEAR(status, instance); + + /* + * Clear the interrupt by writing back the same value. + * Another case where SKINNY is slightly different. + */ + if (instance->skinny) { + WR_OB_INTR_STATUS(status, instance); + } else { + WR_OB_DOORBELL_CLEAR(status, instance); + } /* dummy READ */ status = RD_OB_INTR_STATUS(instance); @@ -7485,7 +7533,7 @@ if (lun == 0) { rval = mrsas_config_ld(instance, tgt, lun, childp); #ifdef PDSUPPORT - } else if (instance->tbolt == 1 && lun != 0) { + } else if ((instance->tbolt || instance->skinny) && lun != 0) { rval = mrsas_tbolt_config_pd(instance, tgt, lun, childp); #endif @@ -7528,7 +7576,7 @@ #ifdef PDSUPPORT /* Config PD devices connected to the card */ - if (instance->tbolt) { + if (instance->tbolt || instance->skinny) { for (tgt = 0; tgt < instance->mr_tbolt_pd_max; tgt++) { (void) mrsas_tbolt_config_pd(instance, tgt, 1, NULL); } @@ -7782,7 +7830,7 @@ (void) mrsas_config_ld(instance, mrevt->tgt, 0, NULL); #ifdef PDSUPPORT - } else if (instance->tbolt) { + } else if (instance->tbolt || instance->skinny) { (void) mrsas_tbolt_config_pd(instance, mrevt->tgt, 1, NULL); diff -r 4ba0940c01f8 -r f0c04f0fa2ad usr/src/uts/common/io/mr_sas/mr_sas.h --- a/usr/src/uts/common/io/mr_sas/mr_sas.h Sun Mar 31 04:00:15 2013 +0000 +++ b/usr/src/uts/common/io/mr_sas/mr_sas.h Thu Apr 04 14:26:49 2013 -0400 @@ -43,6 +43,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MR_SAS_H_ @@ -90,6 +91,8 @@ */ #define PCI_DEVICE_ID_LSI_2108VDE 0x0078 #define PCI_DEVICE_ID_LSI_2108V 0x0079 +#define PCI_DEVICE_ID_LSI_SKINNY 0x0071 +#define PCI_DEVICE_ID_LSI_SKINNY_NEW 0x0073 #define PCI_DEVICE_ID_LSI_TBOLT 0x005b #define PCI_DEVICE_ID_LSI_INVADER 0x005d @@ -100,6 +103,7 @@ #define MRSAS_MAX_SGE_CNT 0x50 #define MRSAS_APP_RESERVED_CMDS 32 +#define MRSAS_APP_MIN_RESERVED_CMDS 4 #define MRSAS_IOCTL_DRIVER 0x12341234 #define MRSAS_IOCTL_FIRMWARE 0x12345678 @@ -594,7 +598,8 @@ uint8_t fast_path_io; - uint16_t tbolt; + uint8_t skinny; + uint8_t tbolt; uint16_t reply_read_index; uint16_t reply_size; /* Single Reply struct size */ uint16_t raid_io_msg_size; /* Single message size */ @@ -2045,6 +2050,9 @@ int mfi_state_transition_to_ready(struct mrsas_instance *); +struct mrsas_cmd *mrsas_get_mfi_pkt(struct mrsas_instance *); +void mrsas_return_mfi_pkt(struct mrsas_instance *, struct mrsas_cmd *); + /* FMA functions. */ int mrsas_common_check(struct mrsas_instance *, struct mrsas_cmd *); diff -r 4ba0940c01f8 -r f0c04f0fa2ad usr/src/uts/common/io/mr_sas/mr_sas_tbolt.c --- a/usr/src/uts/common/io/mr_sas/mr_sas_tbolt.c Sun Mar 31 04:00:15 2013 +0000 +++ b/usr/src/uts/common/io/mr_sas/mr_sas_tbolt.c Thu Apr 04 14:26:49 2013 -0400 @@ -15,6 +15,10 @@ * Shakeel Bukhari */ +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + #include #include @@ -46,8 +50,6 @@ extern int debug_level_g; extern unsigned int enable_fp; volatile int dump_io_wait_time = 90; -extern void -io_timeout_checker(void *arg); extern volatile int debug_timeout_g; extern int mrsas_issue_pending_cmds(struct mrsas_instance *); extern int mrsas_complete_pending_cmds(struct mrsas_instance *instance); @@ -1882,96 +1884,6 @@ return (cmd); } -/* - * mrsas_tbolt_tran_init_pkt - allocate & initialize a scsi_pkt structure - * @ap: - * @pkt: - * @bp: - * @cmdlen: - * @statuslen: - * @tgtlen: - * @flags: - * @callback: - * - * The tran_init_pkt() entry point allocates and initializes a scsi_pkt - * structure and DMA resources for a target driver request. The - * tran_init_pkt() entry point is called when the target driver calls the - * SCSA function scsi_init_pkt(). Each call of the tran_init_pkt() entry point - * is a request to perform one or more of three possible services: - * - allocation and initialization of a scsi_pkt structure - * - allocation of DMA resources for data transfer - * - reallocation of DMA resources for the next portion of the data transfer - */ -struct scsi_pkt * -mrsas_tbolt_tran_init_pkt(struct scsi_address *ap, - register struct scsi_pkt *pkt, - struct buf *bp, int cmdlen, int statuslen, int tgtlen, - int flags, int (*callback)(), caddr_t arg) -{ - struct scsa_cmd *acmd; - struct mrsas_instance *instance; - struct scsi_pkt *new_pkt; - - instance = ADDR2MR(ap); - - /* step #1 : pkt allocation */ - if (pkt == NULL) { - pkt = scsi_hba_pkt_alloc(instance->dip, ap, cmdlen, statuslen, - tgtlen, sizeof (struct scsa_cmd), callback, arg); - if (pkt == NULL) { - return (NULL); - } - - acmd = PKT2CMD(pkt); - - /* - * Initialize the new pkt - we redundantly initialize - * all the fields for illustrative purposes. - */ - acmd->cmd_pkt = pkt; - acmd->cmd_flags = 0; - acmd->cmd_scblen = statuslen; - acmd->cmd_cdblen = cmdlen; - acmd->cmd_dmahandle = NULL; - acmd->cmd_ncookies = 0; - acmd->cmd_cookie = 0; - acmd->cmd_cookiecnt = 0; - acmd->cmd_nwin = 0; - - pkt->pkt_address = *ap; - pkt->pkt_comp = (void (*)())NULL; - pkt->pkt_flags = 0; - pkt->pkt_time = 0; - pkt->pkt_resid = 0; - pkt->pkt_state = 0; - pkt->pkt_statistics = 0; - pkt->pkt_reason = 0; - new_pkt = pkt; - } else { - acmd = PKT2CMD(pkt); - new_pkt = NULL; - } - - /* step #2 : dma allocation/move */ - if (bp && bp->b_bcount != 0) { - if (acmd->cmd_dmahandle == NULL) { - if (mrsas_dma_alloc(instance, pkt, bp, flags, - callback) == DDI_FAILURE) { - if (new_pkt) { - scsi_hba_pkt_free(ap, new_pkt); - } - return ((struct scsi_pkt *)NULL); - } - } else { - if (mrsas_dma_move(instance, pkt, bp) == DDI_FAILURE) { - return ((struct scsi_pkt *)NULL); - } - } - } - return (pkt); -} - - uint32_t tbolt_read_fw_status_reg(struct mrsas_instance *instance) { @@ -3632,6 +3544,14 @@ #ifdef PDSUPPORT +/* + * Even though these functions were originally intended for 2208 only, it + * turns out they're useful for "Skinny" support as well. In a perfect world, + * these two functions would be either in mr_sas.c, or in their own new source + * file. Since this driver needs some cleanup anyway, keep this portion in + * mind as well. + */ + int mrsas_tbolt_config_pd(struct mrsas_instance *instance, uint16_t tgt, uint8_t lun, dev_info_t **ldip) @@ -3694,7 +3614,6 @@ sd->sd_inq = (struct scsi_inquiry *)NULL; } kmem_free(sd, sizeof (struct scsi_device)); - rval = NDI_SUCCESS; } else { con_log(CL_ANN1, (CE_NOTE, "Device not supported: tgt %d lun %d dtype %d", @@ -3716,7 +3635,12 @@ struct mrsas_dcmd_frame *dcmd; dma_obj_t dcmd_dma_obj; - cmd = get_raid_msg_pkt(instance); + ASSERT(instance->tbolt || instance->skinny); + + if (instance->tbolt) + cmd = get_raid_msg_pkt(instance); + else + cmd = mrsas_get_mfi_pkt(instance); if (!cmd) { con_log(CL_ANN1, @@ -3761,9 +3685,8 @@ cmd->sync_cmd = MRSAS_TRUE; cmd->frame_count = 1; - if (instance->tbolt) { + if (instance->tbolt) mr_sas_tbolt_build_mfi_cmd(instance, cmd); - } instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd); @@ -3771,6 +3694,10 @@ (uint8_t *)dcmd_dma_obj.buffer, sizeof (struct mrsas_tbolt_pd_info), DDI_DEV_AUTOINCR); (void) mrsas_free_dma_obj(instance, dcmd_dma_obj); - return_raid_msg_pkt(instance, cmd); + + if (instance->tbolt) + return_raid_msg_pkt(instance, cmd); + else + mrsas_return_mfi_pkt(instance, cmd); } #endif