3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * CDDL HEADER START
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * The contents of this file are subject to the terms of the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Common Development and Distribution License (the "License").
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * You may not use this file except in compliance with the License.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * or http://www.opensolaris.org/os/licensing.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * See the License for the specific language governing permissions
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * and limitations under the License.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * When distributing Covered Code, include this CDDL HEADER in each
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * If applicable, add the following below this CDDL HEADER, with the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * fields enclosed by brackets "[]" replaced with your own identifying
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * information: Portions Copyright [yyyy] [name of copyright owner]
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * CDDL HEADER END
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Use is subject to license terms.
89b43686db1fe9681d80a7cf5662730cb9378caeBayard Bell * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * sf - Solaris Fibre Channel driver
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * This module implements some of the Fibre Channel FC-4 layer, converting
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * from FC frames to SCSI and back. (Note: no sequence management is done
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * here, though.)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#if defined(lint) && !defined(DEBUG)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define DEBUG 1
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Need to use the ugly RAID LUN mappings in FCP Annex D
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * to prevent SCSA from barfing. This *REALLY* needs to
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * be addressed by the standards committee.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define RAID_LUNS 1
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sfdebug = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/debug.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_DEBUG(level, args) \
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sfdebug >= (level)) sf_log args
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_DEBUG(level, args)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_bus_config_debug = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/scsi/scsi.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/fc4/fcal.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/fc4/fcp.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/fc4/fcal_linkapp.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/socal_cq_defs.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/fc4/fcal_transport.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/fc4/fcio.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/scsi/adapters/sfvar.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/scsi/impl/scsi_reset_notify.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/stat.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/varargs.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/var.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/thread.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/proc.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/kstat.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/devctl.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/scsi/targets/ses.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#include <sys/callb.h>
5c5f137104b2d56181283389fa902220f2023809Richard Lowe#include <sys/sysmacros.h>
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_attach(dev_info_t *, ddi_attach_cmd_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_detach(dev_info_t *, ddi_detach_cmd_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_softstate_unlink(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_bus_config(dev_info_t *parent, uint_t flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_bus_config_op_t op, void *arg);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_tgt_init(dev_info_t *, dev_info_t *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_t *, struct scsi_device *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_scsi_tgt_free(dev_info_t *, dev_info_t *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_t *, struct scsi_device *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_pkt_alloc_extern(struct sf *, struct sf_pkt *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int, int, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_pkt_destroy_extern(struct sf *, struct sf_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct scsi_pkt *sf_scsi_init_pkt(struct scsi_address *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_reset_notify(struct scsi_address *, int,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel void (*)(caddr_t), caddr_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_get_name(struct scsi_device *, char *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_scsi_get_bus_addr(struct scsi_device *, char *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_add_cr_pool(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_cr_alloc(struct sf *, struct sf_pkt *, int (*)());
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_cr_free(struct sf_cr_pool *, struct sf_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_crpool_free(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_kmem_cache_constructor(void *, void *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_kmem_cache_destructor(void *, void *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_statec_callback(void *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_login(struct sf *, uchar_t, uchar_t, uint_t, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_els_transport(struct sf *, struct sf_els_hdr *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_els_callback(struct fcal_packet *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_do_prli(struct sf *, struct sf_els_hdr *, struct la_els_logi *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_do_adisc(struct sf *, struct sf_els_hdr *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_do_reportlun(struct sf *, struct sf_els_hdr *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_reportlun_callback(struct fcal_packet *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_do_inquiry(struct sf *, struct sf_els_hdr *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_inq_callback(struct fcal_packet *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct fcal_packet *sf_els_alloc(struct sf *, uchar_t, int, int,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int, caddr_t *, caddr_t *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_els_free(struct fcal_packet *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *sf_create_target(struct sf *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *, int, int64_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int64_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_finish_init(struct sf *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_offline_target(struct sf *, struct sf_target *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_create_devinfo(struct sf *, struct sf_target *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_create_props(dev_info_t *, struct sf_target *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_commoncap(struct scsi_address *, char *, int, int, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_getcap(struct scsi_address *, char *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_setcap(struct scsi_address *, char *, int, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_abort(struct scsi_address *, struct scsi_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_reset(struct scsi_address *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_abort_all(struct sf *, struct sf_target *, int, int, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_start(struct scsi_address *, struct scsi_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_start_internal(struct sf *, struct sf_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_fill_ids(struct sf *, struct sf_pkt *, struct sf_target *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_prepare_pkt(struct sf *, struct sf_pkt *, struct sf_target *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_dopoll(struct sf *, struct sf_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_cmd_callback(struct fcal_packet *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_throttle(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_watch(void *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_throttle_start(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_check_targets(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_check_reset_delay(void *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_target_timeout(struct sf *, struct sf_pkt *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_force_lip(struct sf *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_unsol_els_callback(void *, soc_response_t *, caddr_t);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_els_hdr *sf_els_timeout(struct sf *, struct sf_els_hdr *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*PRINTFLIKE3*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_log(struct sf *, int, const char *, ...);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_kstat_update(kstat_t *, int);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_open(dev_t *, int, int, cred_t *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_close(dev_t, int, int, cred_t *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *sf_get_target_from_dip(struct sf *, dev_info_t *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_bus_get_eventcookie(dev_info_t *, dev_info_t *, char *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_bus_add_eventcall(dev_info_t *, dev_info_t *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t, void (*)(), void *, ddi_callback_id_t *cb_id);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_bus_post_event(dev_info_t *, dev_info_t *,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t, void *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void sf_hp_daemon(void *);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this is required to be able to supply a control node
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * where ioctls can be executed
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstruct cb_ops sf_cb_ops = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_open, /* open */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_close, /* close */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* strategy */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* print */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* dump */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* read */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* write */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_ioctl, /* ioctl */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* devmap */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* mmap */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* segmap */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nochpoll, /* poll */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_prop_op, /* cb_prop_op */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0, /* streamtab */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel D_MP | D_NEW | D_HOTPLUG /* driver flags */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * autoconfiguration routines.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct dev_ops sf_ops = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DEVO_REV, /* devo_rev, */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0, /* refcnt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_info, /* info */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nulldev, /* identify */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nulldev, /* probe */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_attach, /* attach */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_detach, /* detach */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nodev, /* reset */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf_cb_ops, /* driver operations */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power management */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_NAME "FC-AL FCP Nexus Driver" /* Name of the module. */
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic char sf_version[] = "1.72 08/19/2008"; /* version of the module */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct modldrv modldrv = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &mod_driverops, /* Type of module. This one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_NAME,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf_ops, /* driver ops */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct modlinkage modlinkage = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel MODREV_1, (void *)&modldrv, NULL
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX The following is here to handle broken targets -- remove it later */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_reportlun_forever = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_lip_on_plogo = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_els_retries = SF_ELS_RETRIES;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf *sf_head = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_target_scan_cnt = 4;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_pkt_scan_cnt = 5;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_pool_scan_cnt = 1800;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void *sf_state = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_watchdog_init = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_watchdog_time = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_watchdog_timeout = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_watchdog_tick;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_watch_running = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic timeout_id_t sf_watchdog_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic timeout_id_t sf_reset_timeout_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_max_targets = SF_MAX_TARGETS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic kmutex_t sf_global_mutex;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelint *sf_token = NULL; /* Must not be static or lint complains. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic kcondvar_t sf_watch_cv;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelextern pri_t minclsyspri;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic ddi_eventcookie_t sf_insert_eid;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic ddi_eventcookie_t sf_remove_eid;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic ndi_event_definition_t sf_event_defs[] = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{ SF_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL, 0 },
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{ SF_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT, 0 }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_N_NDI_EVENTS \
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sizeof (sf_event_defs) / sizeof (ndi_event_definition_t))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_lip_flag = 1; /* bool: to allow LIPs */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_reset_flag = 1; /* bool: to allow reset after LIP */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int sf_abort_flag = 0; /* bool: to do just one abort */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoniextern int64_t ddi_get_lbolt64(void);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * for converting between target number (switch) and hard address/AL_PA
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic uchar_t sf_switch_to_alpa[] = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic uchar_t sf_alpa_to_switch[] = {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel};
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * these macros call the proper transport-layer function given
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * a particular transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_transport(a, b, c, d) (*a->fcal_ops->fcal_transport)(b, c, d)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_transport_poll(a, b, c, d)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_transport_poll)(b, c, d)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_get_lilp_map(a, b, c, d, e)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_lilp_map)(b, c, d, e)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_force_lip(a, b, c, d, e)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_force_lip)(b, c, d, e)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_abort(a, b, c, d, e)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_abort_cmd)(b, c, d, e)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_force_reset(a, b, c, d)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_force_reset)(b, c, d)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_add_ulp(a, b, c, d, e, f, g, h)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_add_ulp)(b, c, d, e, f, g, h)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_remove_ulp(a, b, c, d, e)\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*a->fcal_ops->fcal_remove_ulp)(b, c, d, e)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define soc_take_core(a, b) (*a->fcal_ops->fcal_take_core)(b)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* power management property defines (should be in a common include file?) */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define PM_HARDWARE_STATE_PROP "pm-hardware-state"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define PM_NEEDS_SUSPEND_RESUME "needs-suspend-resume"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* node properties */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define NODE_WWN_PROP "node-wwn"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define PORT_WWN_PROP "port-wwn"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define LIP_CNT_PROP "lip-count"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define TARGET_PROP "target"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define LUN_PROP "lun"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * initialize this driver and install this module
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelint
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel_init(void)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = ddi_soft_state_init(&sf_state, sizeof (struct sf),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_INIT_ITEMS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (i != 0)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((i = scsi_hba_init(&modlinkage)) != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_soft_state_fini(&sf_state);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&sf_global_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watch_running = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_init(&sf_watch_cv, NULL, CV_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((i = mod_install(&modlinkage)) != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf_watch_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_fini(&modlinkage);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_soft_state_fini(&sf_state);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * remove this driver module from the system
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelint
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel_fini(void)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((i = mod_remove(&modlinkage)) == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_fini(&modlinkage);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf_watch_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_soft_state_fini(&sf_state);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelint
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel_info(struct modinfo *modinfop)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (mod_info(&modlinkage, modinfop));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Given the device number return the devinfo pointer or instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*ARGSUSED*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int instance = SF_MINOR2INST(getminor((dev_t)arg));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (infocmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_INFO_DEVT2DEVINFO:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *result = sf->sf_dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *result = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_INFO_DEVT2INSTANCE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *result = (void *)(uintptr_t)instance;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * either attach or resume this driver
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int instance;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int mutex_initted = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t ccount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t i, real_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_transport *handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char buf[64];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf, *tsf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_t *tran = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int handle_bound = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kthread_t *tp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch ((int)cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_RESUME:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * we've previously been SF_STATE_OFFLINEd by a DDI_SUSPEND,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * so time to undo that and get going again by forcing a
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * lip
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance = ddi_get_instance(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_attach: DDI_RESUME for sf%d\n", instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: bad soft state", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * clear suspended flag so that normal operations can resume
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state &= ~SF_STATE_SUSPENDED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * force a login by setting our state to offline
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call transport routine to register state change and
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * ELS callback routines (to register us as a ULP)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_statec_callback, sf_unsol_els_callback, NULL, sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call transport routine to force loop initialization
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * increment watchdog init flag, setting watchdog timeout
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if we are the first (since somebody has to do it)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_watchdog_init++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_id = timeout(sf_watch,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)0, sf_watchdog_tick);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_ATTACH:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this instance attaching for the first time
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance = ddi_get_instance(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_soft_state_zalloc(sf_state, instance) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: failed to allocate soft state",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_attach: DDI_ATTACH for sf%d\n", instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this shouldn't happen since we just allocated it */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: bad soft state", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * from this point on, if there's an error, we must de-allocate
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * soft state before returning DDI_FAILURE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((handle = ddi_get_parent_data(dip)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf%d: failed to obtain transport handle",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* fill in our soft state structure */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_dip = dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_INIT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = handle->fcal_cmdmax;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle = handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp = handle->fcal_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_check_n_close = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create a command/response buffer pool for this instance */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf%d: failed to allocate command/response pool",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create a a cache for this instance */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(buf, "sf%d_cache", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_cache = kmem_cache_create(buf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (fcal_packet_t) + sizeof (struct sf_pkt) +
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth scsi_pkt_size(), 8,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_kmem_cache_constructor, sf_kmem_cache_destructor,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, NULL, NULL, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_pkt_cache == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: failed to allocate kmem cache",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up a handle and allocate memory for DMA */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_dmaattr, DDI_DMA_DONTWAIT, NULL, &sf->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_lilp_dmahandle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf%d: failed to allocate dma handle for lilp map",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = sizeof (struct fcal_lilp_map) + 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(sf->sf_lilp_dmahandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i, sf->sf_sochandle->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_accattr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t *)&sf->sf_lilp_map, &real_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf->sf_lilp_acchandle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: failed to allocate lilp map",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (real_size < i) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* no error message ??? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* trouble allocating memory */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * set up the address for the DMA transfers (getting a cookie)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(sf->sf_lilp_dmahandle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)sf->sf_lilp_map, real_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf->sf_lilp_dmacookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf%d: failed to bind dma handle for lilp map",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel handle_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure only one cookie was allocated */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure LILP map and DMA cookie addresses are even?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map = (struct fcal_lilp_map *)(((uintptr_t)sf->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_lilp_map + 1) & ~1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_dmacookie.dmac_address = (sf->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_lilp_dmacookie.dmac_address + 1) & ~1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up all of our mutexes and condition variables */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&sf->sf_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&sf->sf_cmd_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&sf->sf_cr_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&sf->sf_hp_daemon_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_init(&sf->sf_cr_cv, NULL, CV_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_init(&sf->sf_hp_daemon_cv, NULL, CV_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_initted = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create our devctl minor node */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_INST2DEVCTL_MINOR(instance),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
193974072f41a843678abf5f61979c748687e66bSherry Moore " for devctl", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create fc minor node */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_create_minor_node(dip, "fc", S_IFCHR,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_INST2FC_MINOR(instance), DDI_NT_FC_ATTACHMENT_POINT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
193974072f41a843678abf5f61979c748687e66bSherry Moore " for fc", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate a SCSI transport structure */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran = scsi_hba_tran_alloc(dip, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tran == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove all minor nodes created */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_remove_minor_node(dip, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: scsi_hba_tran_alloc failed",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth scsi_size_clean(dip); /* SCSI_SIZE_CLEAN_VERIFY ok */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* save ptr to new transport structure and fill it in */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_tran = tran;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_hba_private = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_tgt_private = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_tgt_init = sf_scsi_tgt_init;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_tgt_probe = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_tgt_free = sf_scsi_tgt_free;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_start = sf_start;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_abort = sf_abort;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_reset = sf_reset;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_getcap = sf_getcap;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_setcap = sf_setcap;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_init_pkt = sf_scsi_init_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_destroy_pkt = sf_scsi_destroy_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_dmafree = sf_scsi_dmafree;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_sync_pkt = sf_scsi_sync_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_reset_notify = sf_scsi_reset_notify;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * register event notification routines with scsa
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_get_eventcookie = sf_bus_get_eventcookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_add_eventcall = sf_bus_add_eventcall;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_remove_eventcall = sf_bus_remove_eventcall;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_post_event = sf_bus_post_event;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * register bus configure/unconfigure
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_bus_config = sf_scsi_bus_config;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_bus_unconfig = sf_scsi_bus_unconfig;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * allocate an ndi event handle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_event_defs = (ndi_event_definition_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (sf_event_defs), KM_SLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy(sf_event_defs, sf->sf_event_defs,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (sf_event_defs));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_alloc_hdl(dip, NULL,
193974072f41a843678abf5f61979c748687e66bSherry Moore &sf->sf_event_hdl, NDI_SLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_events.ndi_events_version = NDI_EVENTS_REV1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_events.ndi_n_events = SF_N_NDI_EVENTS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_events.ndi_event_defs = sf->sf_event_defs;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_event_bind_set(sf->sf_event_hdl,
193974072f41a843678abf5f61979c748687e66bSherry Moore &sf->sf_events, NDI_SLEEP) != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_get_name = sf_scsi_get_name;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tran->tran_get_bus_addr = sf_scsi_get_bus_addr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* setup and attach SCSI hba transport */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (scsi_hba_attach_setup(dip, sf->sf_sochandle->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_dmaattr, tran, SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: scsi_hba_attach_setup failed",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up kstats */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_ksp = kstat_create("sf", instance, "statistics",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "controller", KSTAT_TYPE_RAW, sizeof (struct sf_stats),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel KSTAT_FLAG_VIRTUAL)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: failed to create kstat",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.version = 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(sf->sf_stats.drvr_name,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "%s: %s", SF_NAME, sf_version);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ksp->ks_data = (void *)&sf->sf_stats;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ksp->ks_private = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ksp->ks_update = sf_kstat_update;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kstat_install(sf->sf_ksp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create the hotplug thread */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp = thread_create(NULL, 0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void (*)())sf_hp_daemon, sf, 0, &p0, TS_RUN, minclsyspri);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_tid = tp->t_did;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add this soft state instance to the head of the list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_next = sf_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf = sf_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_head = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * find entry in list that has the same FC-AL handle (if any)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (tsf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tsf->sf_socp == sf->sf_socp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break; /* found matching entry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf = tsf->sf_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tsf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* if we found a matching entry keep track of it */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sibling = tsf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * increment watchdog init flag, setting watchdog timeout
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if we are the first (since somebody has to do it)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_watchdog_init++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_tick = sf_watchdog_timeout *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel drv_usectohz(1000000);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_id = timeout(sf_watch,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, sf_watchdog_tick);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tsf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * set up matching entry to be our sibling
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&tsf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf->sf_sibling = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&tsf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * create this property so that PM code knows we want
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * to be suspended at PM time
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* log the fact that we have a new device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_report_dev(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * force a login by setting our state to offline
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call transport routine to register state change and
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * ELS callback routines (to register us as a ULP)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_statec_callback, sf_unsol_els_callback, NULL, sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call transport routine to force loop initialization
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sf->sf_reset_time = ddi_get_lbolt64();
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: failed to attach", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Unbind and free event set
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_event_hdl) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_unbind_set(sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf->sf_events, NDI_SLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_free_hdl(sf->sf_event_hdl);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_event_defs) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_tran != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_free(sf->sf_tran);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (sf->sf_cr_pool != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_crpool_free(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_dmahandle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (handle_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_pkt_cache != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_cache_destroy(sf->sf_pkt_cache);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&sf->sf_lilp_acchandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ksp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kstat_delete(sf->sf_ksp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (mutex_initted) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf->sf_cr_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf->sf_hp_daemon_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * kill off the watchdog if we are the last instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!--sf_watchdog_init) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel timeout_id_t tid = sf_watchdog_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) untimeout(tid);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_soft_state_free(sf_state, instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tran != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove all minor nodes */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_remove_minor_node(dip, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int instance;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel timeout_id_t tid;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* NO OTHER THREADS ARE RUNNING */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance = ddi_get_instance(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf = ddi_get_soft_state(sf_state, instance)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf_detach, sf%d: bad soft state", instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_SUSPEND:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * suspend our instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_detach: DDI_SUSPEND for sf%d\n", instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * There is a race condition in socal where while doing
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * callbacks if a ULP removes it self from the callback list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the for loop in socal may panic as cblist is junk and
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * while trying to get cblist->next the system will panic.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to remove our unregister our callbacks */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * begin process of clearing outstanding commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * by issuing a lip
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * toggle the device OFFLINE in order to cause
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * outstanding commands to drain
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = (SF_STATE_OFFLINE | SF_STATE_SUSPENDED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |=
193974072f41a843678abf5f61979c748687e66bSherry Moore (SF_TARGET_BUSY | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* do this for all LUNs as well */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (ntarget = target->sft_next_lun;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget = ntarget->sft_next_lun) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(ntarget->sft_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_state |=
193974072f41a843678abf5f61979c748687e66bSherry Moore (SF_TARGET_BUSY |
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * kill off the watchdog if we are the last instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!--sf_watchdog_init) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tid = sf_watchdog_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) untimeout(tid);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_DETACH:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * detach this instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_detach: DDI_DETACH for sf%d\n", instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove this "sf" from the list of sf softstates */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_softstate_unlink(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * prior to taking any DDI_DETACH actions, toggle the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * device OFFLINE in order to cause outstanding
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * commands to drain
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (SF_TARGET_BUSY | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (ntarget = target->sft_next_lun;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget = ntarget->sft_next_lun) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(ntarget->sft_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_state |=
193974072f41a843678abf5f61979c748687e66bSherry Moore (SF_TARGET_BUSY |
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to remove and unregister our callbacks */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * kill off the watchdog if we are the last instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!--sf_watchdog_init) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tid = sf_watchdog_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) untimeout(tid);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* signal sf_hp_daemon() to exit and wait for exit */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_hp_tid);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_exit = 1; /* flag exit */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_signal(&sf->sf_hp_daemon_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel thread_join(sf->sf_hp_tid); /* wait for hotplug to exit */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Unbind and free event set
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_event_hdl) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_unbind_set(sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf->sf_events, NDI_SLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_free_hdl(sf->sf_event_hdl);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_event_defs) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* detach this instance of the HBA driver */
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki (void) scsi_hba_detach(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_free(sf->sf_tran);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* deallocate/unbind DMA handle for lilp map */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_dmahandle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&sf->sf_lilp_acchandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the kmem cache must be destroyed before free'ing
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * up the crpools
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * our finagle of "ntot" and "nfree"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * causes an ASSERT failure in "sf_cr_free()"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if the kmem cache is free'd after invoking
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * "sf_crpool_free()".
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_cache_destroy(sf->sf_pkt_cache);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_detach: sf_crpool_free() for instance 0x%x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (sf->sf_cr_pool != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * set ntot to nfree for this particular entry
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this causes sf_crpool_free() to update
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the cr_pool list when deallocating this entry
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_pool->ntot = sf->sf_cr_pool->nfree;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_crpool_free(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * now that the cr_pool's are gone it's safe
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * to destroy all softstate mutex's and cv's
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf->sf_cr_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_destroy(&sf->sf_hp_daemon_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove all minor nodes from the device tree */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_remove_minor_node(dip, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove properties created during attach() */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_prop_remove_all(dip);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove kstat's if present */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ksp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kstat_delete(sf->sf_ksp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sf_detach: ddi_soft_state_free() for instance 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_soft_state_free(sf_state, instance);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT, "sf_detach: sf%d unknown cmd %x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel instance, (int)cmd));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * sf_softstate_unlink() - remove an sf instance from the list of softstates
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_softstate_unlink(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf_ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf_found_sibling;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf_reposition = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (sf_watch_running) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Busy working the list -- wait */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_wait(&sf_watch_cv, &sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf_found_sibling = sf->sf_sibling) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * we have a sibling so NULL out its reference to us
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_found_sibling->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_found_sibling->sf_sibling = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_found_sibling->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove our instance from the global list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == sf_head) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we were at at head of the list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_head = sf->sf_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* find us in the list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (sf_ptr = sf_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_ptr != NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_ptr = sf_ptr->sf_next) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_ptr == sf) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remember this place */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_reposition = sf_ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf_ptr == sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf_reposition != NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_reposition->sf_next = sf_ptr->sf_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_bus_config(dev_info_t *parent, uint_t flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int64_t reset_delay;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, ddi_get_instance(parent));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reset_delay = (int64_t)(USEC_TO_TICK(SF_INIT_WAIT_TIMEOUT)) -
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (ddi_get_lbolt64() - sf->sf_reset_time);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (reset_delay < 0)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reset_delay = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_bus_config_debug)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel flag |= NDI_DEVI_DEBUG;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_busop_bus_config(parent, flag, op,
193974072f41a843678abf5f61979c748687e66bSherry Moore arg, childp, (clock_t)reset_delay));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_bus_config_op_t op, void *arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_bus_config_debug)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel flag |= NDI_DEVI_DEBUG;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_busop_bus_unconfig(parent, flag, op, arg));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to initialize a SCSI target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int64_t lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = (struct sf *)hba_tran->tran_hba_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i, t_len;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel unsigned int lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel unsigned char wwn[FC_WWN_SIZE];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get and validate our SCSI target ID */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = sd->sd_address.a_target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (i >= sf_max_targets) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_NOT_WELL_FORMED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get our port WWN property */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel t_len = sizeof (wwn);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&wwn, &t_len) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* no port WWN property - ignore the OBP stub node */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_NOT_WELL_FORMED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get our LIP count property */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel t_len = sizeof (lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, LIP_CNT_PROP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&lip_cnt, &t_len) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* and our LUN property */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel t_len = sizeof (lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&lun, &t_len) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* find the target structure for this instance */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target = sf_lookup_target(sf, wwn, lun)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_lip_cnt == lip_cnt) && !(target->sft_state
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel & SF_TARGET_INIT_DONE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * set links between HBA transport and target structures
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * and set done flag
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hba_tran->tran_tgt_private = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_tran = hba_tran;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_INIT_DONE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* already initialized ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to free a target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = hba_tran->tran_tgt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_tran = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~SF_TARGET_INIT_DONE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * allocator for non-std size cdb/pkt_private/status -- return TRUE iff
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * success, else return FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*ARGSUSED*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_pkt_alloc_extern(struct sf *sf, struct sf_pkt *cmd,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgtlen, int statuslen, int kf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t scbp, tgt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int failure = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt = CMD2PKT(cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt = scbp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tgtlen > PKT_PRIV_LEN) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((tgt = kmem_zalloc(tgtlen, kf)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel failure = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags |= CFLAG_PRIVEXTERN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_private = tgt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (statuslen > EXTCMDS_STATUS_SIZE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel failure = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags |= CFLAG_SCBEXTERN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_scbp = (opaque_t)scbp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (failure) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_pkt_destroy_extern(sf, cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (failure);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * deallocator for non-std size cdb/pkt_private/status
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_pkt_destroy_extern(struct sf *sf, struct sf_pkt *cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt = CMD2PKT(cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_FREE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_PANIC,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_scsi_impl_pktfree: freeing free packet");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel _NOTE(NOT_REACHED)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* NOTREACHED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free((caddr_t)pkt->pkt_scbp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (size_t)cmd->cmd_scblen);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free((caddr_t)pkt->pkt_private,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (size_t)cmd->cmd_privlen);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags = CFLAG_FREE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * create or initialize a SCSI packet -- called internally and
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * by the transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct scsi_pkt *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct buf *bp, int cmdlen, int statuslen, int tgtlen,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int flags, int (*callback)(), caddr_t arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int kf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int failure = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *new_cmd = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_cmd *fcmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * If we've already allocated a pkt once,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this request is for dma allocation only.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * First step of sf_scsi_init_pkt: pkt allocation
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmdlen > FCP_CDB_SIZE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd = kmem_cache_alloc(sf->sf_pkt_cache, kf)) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Selective zeroing of the pkt.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_forw = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_back = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_next = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt = (struct scsi_pkt *)((char *)cmd +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct sf_pkt) + sizeof (struct
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_packet));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt = (struct fcal_packet *)((char *)cmd +
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct sf_pkt));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_private = (opaque_t)cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_scbp = (opaque_t)cmd->cmd_scsi_scb;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_comp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_time = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_resid = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_reason = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_cdblen = (uchar_t)cmdlen;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_scblen = statuslen;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_privlen = tgtlen;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_address = *ap;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* zero pkt_private */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (int *)(cmd->cmd_pkt->pkt_private =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt_private);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)cmd->cmd_pkt->pkt_private,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel PKT_PRIV_LEN);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel failure = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (failure ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (tgtlen > PKT_PRIV_LEN) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (statuslen > EXTCMDS_STATUS_SIZE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!failure) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* need to allocate more space */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel failure = sf_pkt_alloc_extern(sf, cmd,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgtlen, statuslen, kf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (failure) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_block == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate cmd/response pool buffers */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_cr_alloc(sf, cmd, callback) == DDI_FAILURE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_pkt_destroy_extern(sf, cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* fill in the FC-AL packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_cookie = sf->sf_socp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_comp = sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_magic = FCALP_MAGIC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (ushort_t)(SOC_FC_HEADER |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_base =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)cmd->cmd_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct fcp_cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[1].fc_base =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)cmd->cmd_rsp_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[1].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCP_MAX_RSP_IU_SIZE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Fill in the Fabric Channel Header */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->r_ctl = R_CTL_COMMAND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->type = TYPE_SCSI_FCP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->reserved1 = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->seq_id = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->df_ctl = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->seq_cnt = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->ox_id = 0xffff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->rx_id = 0xffff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->ro = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Establish the LUN */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&target->sft_lun.b,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)&cmd->cmd_block->fcp_ent_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore FCP_LUN_SIZE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *((int32_t *)&cmd->cmd_block->fcp_cntl) = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_cdbp = cmd->cmd_block->fcp_cdb;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_pkt_tail->cmd_forw = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_back = target->sft_pkt_tail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_forw = (struct sf_pkt *)&target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_pkt_tail = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel new_cmd = cmd; /* for later cleanup if needed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* pkt already exists -- just a request for DMA allocation */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* zero cdb (bzero is too slow) */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)cmd->cmd_pkt->pkt_cdbp, cmdlen);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Second step of sf_scsi_init_pkt: dma allocation
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Set up dma info
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((bp != NULL) && (bp->b_bcount != 0)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmd_flags, dma_flags;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t dmacookie_count;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* there is a buffer and some data to transfer */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up command and DMA flags */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_flags = cmd->cmd_flags;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (bp->b_flags & B_READ) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a read */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_flags &= ~CFLAG_DMASEND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dma_flags = DDI_DMA_READ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a write */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_flags |= CFLAG_DMASEND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dma_flags = DDI_DMA_WRITE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (flags & PKT_CONSISTENT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_flags |= CFLAG_CMDIOPB;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dma_flags |= DDI_DMA_CONSISTENT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure we have a DMA handle */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_dmahandle == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = ddi_dma_alloc_handle(sf->sf_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_dmaattr, callback, arg,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &cmd->cmd_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rval == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* bind our DMA handle to our buffer */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dma_flags, callback, arg, &cmd->cmd_dmacookie,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &dmacookie_count);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rval != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* DMA failure */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT, "ddi_dma_buf.. failed\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (rval) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_DMA_NORESOURCES:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bioerror(bp, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_DMA_BADATTR:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_DMA_NOMAPPING:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bioerror(bp, EFAULT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DDI_DMA_TOOBIG:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bioerror(bp, EINVAL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* clear valid flag */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags = cmd_flags & ~CFLAG_DMAVALID;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (new_cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* destroy packet if we just created it */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_scsi_destroy_pkt(ap, new_cmd->cmd_pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(dmacookie_count == 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up amt to transfer and set valid flag */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_dmacount = bp->b_bcount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags = cmd_flags | CFLAG_DMAVALID;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cmd->cmd_dmahandle != NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up FC-AL packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd = cmd->cmd_block;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMASEND) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* DMA write */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_read_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_write_data = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_TYPE_IO_WRITE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* DMA read */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_read_data = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_write_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_TYPE_IO_READ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)cmd->cmd_dmacookie.dmac_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_dmacookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_dmacookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_data_len = cmd->cmd_dmacookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* not a read or write */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_read_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_write_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct fcp_cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_data_len = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (cmd->cmd_pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * destroy a SCSI packet -- called internally and by the transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth struct sf_pkt *cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* DMA was set up -- clean up */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags ^= CFLAG_DMAVALID;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* take this packet off the doubly-linked list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_back->cmd_forw = cmd->cmd_forw;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_forw->cmd_back = cmd->cmd_back;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* free the packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd->cmd_flags &
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (CFLAG_FREE | CFLAG_PRIVEXTERN | CFLAG_SCBEXTERN)) == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* just a regular packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags = CFLAG_FREE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a packet with extra memory */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_pkt_destroy_extern(sf, cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to unbind DMA handle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth struct sf_pkt *cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags ^= CFLAG_DMAVALID;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to synchronize CPU and I/O views of memory
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth struct sf_pkt *cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_sync(cmd->cmd_dmahandle, (off_t)0, (size_t)0,
193974072f41a843678abf5f61979c748687e66bSherry Moore (cmd->cmd_flags & CFLAG_DMASEND) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf: sync pkt failed");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * routine for reset notification setup, to register or cancel. -- called
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * by transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_reset_notify(struct scsi_address *ap, int flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel void (*callback)(caddr_t), caddr_t arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
193974072f41a843678abf5f61979c748687e66bSherry Moore &sf->sf_mutex, &sf->sf_reset_notify_listf));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to get port WWN property (except sun4u)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_get_name(struct scsi_device *sd, char *name, int len)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char tbuf[(FC_WWN_SIZE*2)+1];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel unsigned char wwn[FC_WWN_SIZE];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i, lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *tgt_dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_dip = sd->sd_dev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = sizeof (wwn);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&wwn, &i) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel name[0] = '\0';
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = sizeof (lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&lun, &i) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel name[0] = '\0';
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < FC_WWN_SIZE; i++)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(&tbuf[i << 1], "%02x", wwn[i]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(name, "w%s,%x", tbuf, lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport to get target soft AL-PA (except sun4u)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(&sd->sd_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target == NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(name, "%x", target->sft_al_pa);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * add to the command/response buffer pool for this sf instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_add_cr_pool(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmd_buf_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t real_cmd_buf_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rsp_buf_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t real_rsp_buf_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t i, ccount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_pool *ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_free_elem *cptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t dptr, eptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t cmd_cookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t rsp_cookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmd_bound = FALSE, rsp_bound = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate room for the pool */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((ptr = kmem_zalloc(sizeof (struct sf_cr_pool), KM_NOSLEEP)) ==
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate a DMA handle for the command pool */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &ptr->cmd_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Get a piece of memory in which to put commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_buf_size = (sizeof (struct fcp_cmd) * SF_ELEMS_IN_POOL + 7) & ~7;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(ptr->cmd_dma_handle, cmd_buf_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->cmd_base,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_cmd_buf_size, &ptr->cmd_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* bind the DMA handle to an address */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(ptr->cmd_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->cmd_base, real_cmd_buf_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_WRITE | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, &cmd_cookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure only one cookie was allocated */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate a DMA handle for the response pool */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &ptr->rsp_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Get a piece of memory in which to put responses
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_buf_size = FCP_MAX_RSP_IU_SIZE * SF_ELEMS_IN_POOL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(ptr->rsp_dma_handle, rsp_buf_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->rsp_base,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_rsp_buf_size, &ptr->rsp_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* bind the DMA handle to an address */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(ptr->rsp_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->rsp_base, real_rsp_buf_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, &rsp_cookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure only one cookie was allocated */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Generate a (cmd/rsp structure) free list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure ptr points to start of long word (8-byte block) */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dptr = (caddr_t)((uintptr_t)(ptr->cmd_base) + 7 & ~7);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* keep track of actual size after moving pointer */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel real_cmd_buf_size -= (dptr - ptr->cmd_base);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel eptr = ptr->rsp_base;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set actual total number of entries */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->ntot = min((real_cmd_buf_size / sizeof (struct fcp_cmd)),
193974072f41a843678abf5f61979c748687e66bSherry Moore (real_rsp_buf_size / FCP_MAX_RSP_IU_SIZE));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->nfree = ptr->ntot;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->free = (struct sf_cr_free_elem *)ptr->cmd_base;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->sf = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up DMA for each pair of entries */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (i < ptr->ntot) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr = (struct sf_cr_free_elem *)dptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dptr += sizeof (struct fcp_cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr->next = (struct sf_cr_free_elem *)dptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr->rsp = eptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr->cmd_dmac = cmd_cookie.dmac_address +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)((caddr_t)cptr - ptr->cmd_base);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr->rsp_dmac = rsp_cookie.dmac_address +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)((caddr_t)eptr - ptr->rsp_base);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel eptr += FCP_MAX_RSP_IU_SIZE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* terminate the list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr->next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add this list at front of current one */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->next = sf->sf_cr_pool;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_pool = ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_pool_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we failed so clean up */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->cmd_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(ptr->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&ptr->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->rsp_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(ptr->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&ptr->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->cmd_base != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&ptr->cmd_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->rsp_base != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&ptr->rsp_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free((caddr_t)ptr, sizeof (struct sf_cr_pool));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * allocate a command/response buffer from the pool, allocating more
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * in the pool as needed
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_cr_alloc(struct sf *sf, struct sf_pkt *cmd, int (*func)())
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_pool *ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_free_elem *cptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8steveltry_again:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* find a free buffer in the existing pool */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr = sf->sf_cr_pool;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (ptr != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->nfree != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->nfree--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr = ptr->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* did we find a free buffer ? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we found a free buffer -- take it off the free list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cptr = ptr->free;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->free = cptr->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up the command to use the buffer pair */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block = (struct fcp_cmd *)cptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_dmac = cptr->cmd_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_rsp_dmac = cptr->rsp_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_rsp_block = (struct fcp_rsp *)cptr->rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_cr_pool = ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_SUCCESS); /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* no free buffer available -- can we allocate more ? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_cr_pool_cnt < SF_CR_POOL_MAX) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we need to allocate more buffer pairs */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_cr_flag) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* somebody already allocating for this instance */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (func == SLEEP_FUNC) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* user wants to wait */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_wait(&sf->sf_cr_cv, &sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we've been woken so go try again */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto try_again;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* user does not want to wait */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.cralloc_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE); /* give up */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set flag saying we're allocating */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_flag = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add to our pool */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* couldn't add to our pool for some reason */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_flag = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_broadcast(&sf->sf_cr_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.cralloc_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE); /* give up */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * clear flag saying we're allocating and tell all other
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * that care
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_flag = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_broadcast(&sf->sf_cr_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* now that we have more buffers try again */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto try_again;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we don't have room to allocate any more buffers */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.cralloc_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE); /* give up */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * free a cmd/response buffer pair in our pool
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_cr_free(struct sf_cr_pool *cp, struct sf_pkt *cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = cp->sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_free_elem *elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem = (struct sf_cr_free_elem *)cmd->cmd_block;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->rsp = (caddr_t)cmd->cmd_rsp_block;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->cmd_dmac = cmd->cmd_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->rsp_dmac = cmd->cmd_rsp_dmac;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cp->nfree++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cp->nfree <= cp->ntot);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->next = cp->free;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cp->free = elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * free our pool of cmd/response buffers
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_crpool_free(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_cr_pool *cp, *prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cp = sf->sf_cr_pool;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cp->nfree == cp->ntot) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev->next = cp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_pool = cp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_cr_pool_cnt--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(cp->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&cp->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(cp->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&cp->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&cp->cmd_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&cp->rsp_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free((caddr_t)cp, sizeof (struct sf_cr_pool));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev = cp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cp = cp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cr_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_kmem_cache_constructor(void *buf, void *arg, int size)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd = buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&cmd->cmd_abort_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_dmahandle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_kmem_cache_destructor(void *buf, void *size)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd = buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_dmahandle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&cmd->cmd_dmahandle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_block != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_cr_free(cmd->cmd_cr_pool, cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_destroy(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by transport when a state change occurs
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_statec_callback(void *arg, int msg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = (struct sf *)arg;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (msg) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_LOOP_ONLINE: {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uchar_t al_pa; /* to save AL-PA */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int ret; /* ret value from getmap */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lip_cnt; /* to save current count */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cnt; /* map length */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the loop has gone online
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop online\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_ONLINING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* scan each target hash queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_wwn_lists[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * foreach target, if it's not offline then
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * mark it as busy
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= (SF_TARGET_BUSY
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * for debugging, print out info on any
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * pending commands (left hanging)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != (struct sf_pkt *)&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state ==
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_STATE_ISSUED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "cmd 0x%p pending "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "after lip\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void *)cmd->cmd_fp_pkt));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_forw;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * since the loop has just gone online get a new map from
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((ret = soc_get_lilp_map(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, (uint32_t)sf->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_lilp_dmacookie.dmac_address, 1)) != FCAL_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_LILP_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!soc lilp map failed status=0x%x\n", ret);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure consistent view of DMA memory */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(sf->sf_lilp_dmahandle, (off_t)0, (size_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* how many entries in map ? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cnt = sf->sf_lilp_map->lilp_length;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cnt >= SF_MAX_LILP_ENTRIES) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "invalid lilp map\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count = cnt - 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_al_pa = sf->sf_lilp_map->lilp_myalpa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt = sf->sf_lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel al_pa = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!lilp map has %d entries, al_pa is %x\n", cnt, al_pa));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * since the last entry of the map may be mine (common) check
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * for that, and if it is we have one less entry to look at
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map->lilp_alpalist[cnt-1] == al_pa) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cnt--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* If we didn't get a valid loop map enable all targets */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sizeof (sf_switch_to_alpa); i++)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_alpalist[i] =
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_switch_to_alpa[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cnt = i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count = cnt - 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!statec_callback: starting with %d targets\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_device_count));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* scan loop map, logging into all ports (except mine) */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < cnt; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!lilp map entry %d = %x,%x\n", i,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_alpalist[i],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_lilp_map->lilp_alpalist[i]]));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* is this entry for somebody else ? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map->lilp_alpalist[i] != al_pa) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* do a PLOGI to this port */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_login(sf, LA_ELS_PLOGI,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_alpalist[i],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_alpalist[cnt-1],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a problem logging in */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * problem not from a new LIP
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_device_count
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_ERR_OFFLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * loop has gone offline due to an error
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop offline\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf->sf_online_timer) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_online_timer = sf_watchdog_time +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_ONLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * since throttling logic in sf_watch() depends on
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * preservation of this flag while device is suspended
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state & SF_STATE_SUSPENDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state |= SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_statec_callback, sf%d: "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "got FCAL_STATE_OFFLINE during DDI_SUSPEND\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* scan each possible target on the loop */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= (SF_TARGET_BUSY
193974072f41a843678abf5f61979c748687e66bSherry Moore | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATE_RESET: {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp; /* ptr to private list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *tmpp1; /* tmp prev hdr ptr */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *tmpp2; /* tmp next hdr ptr */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *head; /* to save our private list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt; /* ptr to pkt in hdr */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * a transport reset
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT, "!sf%d: soc reset\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp1 = head = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_RESET_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * since throttling logic in sf_watch() depends on
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * preservation of this flag while device is suspended
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state & SF_STATE_SUSPENDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state |= SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_statec_callback, sf%d: "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "got FCAL_STATE_RESET during DDI_SUSPEND\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * scan each possible target on the loop, looking for targets
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * that need callbacks ran
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= (SF_TARGET_BUSY
193974072f41a843678abf5f61979c748687e66bSherry Moore | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * run remove event callbacks for lun
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * We have a nasty race condition here
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * 'cause we're dropping this mutex to
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * run the callback and expect the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * linked list to be the same.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_retrieve_cookie(
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_event_hdl, target->sft_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_REMOVE_EVENT, &sf_remove_eid,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NDI_EVENT_NOPASS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_run_callbacks(
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_event_hdl,
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_remove_eid, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * scan for ELS commands that are in transport, not complete,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * and have a valid timeout, building a private list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (privp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((fpkt->fcal_cmd_state & FCAL_CMD_IN_TRANSPORT) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (!(fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE)) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (privp->timeout != SF_INVALID_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * cmd in transport && not complete &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * timeout valid
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * move this entry from ELS input list to our
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * private list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp2 = privp->next; /* save ptr to next */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* push this on private list head */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next = head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel head = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove this entry from input list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tmpp1 != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * remove this entry from somewhere in
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the middle of the list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp1->next = tmpp2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tmpp2 != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp2->prev = tmpp1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * remove this entry from the head
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * of the list
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = tmpp2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tmpp2 != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp2->prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = tmpp2; /* skip to next entry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tmpp1 = privp; /* save ptr to prev entry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = privp->next; /* skip to next entry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * foreach cmd in our list free the ELS packet associated
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * with it
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (privp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * scan for commands from each possible target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * scan all active commands for this target,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * looking for commands that have been issued,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * are in transport, and are not yet complete
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * (so we can terminate them because of the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * reset)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != (struct sf_pkt *)&target->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_pkt_head) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd->cmd_state ==
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_STATE_ISSUED) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (fpkt->fcal_cmd_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_CMD_IN_TRANSPORT) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (!(fpkt->fcal_cmd_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_CMD_COMPLETE))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a command to be reset */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |=
193974072f41a843678abf5f61979c748687e66bSherry Moore STAT_BUS_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get next command */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_forw;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * get packet queue for this target, resetting all remaining
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = sf->sf_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_head = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_BUS_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called to send a PLOGI (N_port login) ELS request to a destination ID,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning TRUE upon success, else returning FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_login(struct sf *sf, uchar_t els_code, uchar_t dest_id, uint_t arg1,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lip_cnt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_logi *logi;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (union sf_els_cmd), sizeof (union sf_els_rsp),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t *)&privp, (caddr_t *)&logi) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "Cannot allocate PLOGI for target %x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "due to DVMA shortage.\n", sf_alpa_to_switch[dest_id]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->lip_cnt = lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (els_code == LA_ELS_PLOGI) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)sf->sf_sochandle->fcal_loginparms,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&logi->common_service, sizeof (struct la_els_logi)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel - 4);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&logi->nport_ww_name, sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&logi->node_ww_name, sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)&logi->reserved, 16);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (els_code == LA_ELS_LOGO) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&(((struct la_els_logo *)logi)->nport_ww_name), 8);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct la_els_logo *)logi)->reserved = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct la_els_logo *)logi)->nport_id[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct la_els_logo *)logi)->nport_id[1] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct la_els_logo *)logi)->nport_id[2] = arg1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = els_code;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel logi->ls_code = els_code;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel logi->mbz[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel logi->mbz[1] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel logi->mbz[2] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_els_transport(sf, privp));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * send an ELS IU via the transport,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning TRUE upon success, else returning FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_els_transport(struct sf *sf, struct sf_els_hdr *privp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->cmd_dma_handle, (off_t)0, (size_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORDEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list->prev = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to send a packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (soc_transport(sf->sf_sochandle, fpkt, FCAL_NOSLEEP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE); /* failure */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRUE); /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called as the pkt_comp routine for ELS FC packets
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_els_callback(struct fcal_packet *fpkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp = fpkt->fcal_pkt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = privp->sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *tsf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_logi *ptr = (struct la_els_logi *)privp->rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_adisc *adisc = (struct la_els_adisc *)ptr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel short ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel short free_pkt = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * we've received an ELS callback, i.e. an ELS packet has arrived
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* take the current packet off of the queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->timeout == SF_INVALID_TIMEOUT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = privp->next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get # pkts in this callback */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmds = fpkt->fcal_ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(ncmds >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds = ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* sync idea of memory */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0, (size_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* was this an OK ACC msg ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((fpkt->fcal_pkt_status == FCAL_STATUS_OK) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (ptr->ls_code == LA_ELS_ACC)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this was an OK ACC pkt
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (privp->els_code) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case LA_ELS_PLOGI:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * was able to to an N_port login
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!PLOGI to al_pa %x succeeded, wwn %x%x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *((int *)&ptr->nport_ww_name.raw_wwn[0]),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *((int *)&ptr->nport_ww_name.raw_wwn[4])));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* try to do a process login */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_do_prli(sf, privp, ptr)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel free_pkt = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* PRLI failed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case LA_ELS_PRLI:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * was able to do a process login
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!PRLI to al_pa %x succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* try to do address discovery */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_do_adisc(sf, privp) != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel free_pkt = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* ADISC failed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case LA_ELS_ADISC:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * found a target via ADISC
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!ADISC to al_pa %x succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create the target info */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target = sf_create_target(sf, privp,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[(uchar_t)adisc->hard_address],
193974072f41a843678abf5f61979c748687e66bSherry Moore (int64_t)0))
193974072f41a843678abf5f61979c748687e66bSherry Moore == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* can't create target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * ensure address discovered matches what we thought
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * it would be
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((uchar_t)adisc->hard_address !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "target 0x%x, AL-PA 0x%x and "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "hard address 0x%x don't match\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)privp->dest_nport_id],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uchar_t)adisc->hard_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* addr doesn't match */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * get inquiry data from the target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_do_reportlun(sf, privp, target)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel free_pkt = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail; /* inquiry failed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!ELS %x to al_pa %x succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code, privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * oh oh -- this was not an OK ACC packet
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get target ID from dest loop address */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = sf_alpa_to_switch[(uchar_t)privp->dest_nport_id];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* keep track of failures */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[tgt_id].els_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (++(privp->retries) < sf_els_retries &&
193974072f41a843678abf5f61979c748687e66bSherry Moore fpkt->fcal_pkt_status != FCAL_STATUS_OPEN_FAIL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_STATUS_MAX_XCHG_EXCEEDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf = sf->sf_sibling;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tsf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&tsf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf->sf_flag = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf->sf_throttle = SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&tsf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!ELS %x to al_pa %x failed, retrying",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code, privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list->prev = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* device busy? wait a bit ... */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_STATUS_MAX_XCHG_EXCEEDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->delayed_retry = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to send a pkt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (soc_transport(sf->sf_sochandle, fpkt,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_NOSLEEP, CQ_REQUEST_1) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next =
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev =
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status != 0x36 || sfdebug > 4) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE, "ELS %x to al_pa %x failed",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code, privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "els reply code = %x", ptr->ls_code));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->ls_code == LA_ELS_RJT)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "LS_RJT reason = %x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *(((uint_t *)ptr) + 1)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "fc packet status = %x",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_status));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return; /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_device_count >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, privp->lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (free_pkt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * send a PRLI (process login) ELS IU via the transport,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning TRUE upon success, else returning FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_do_prli(struct sf *sf, struct sf_els_hdr *privp, struct la_els_logi *ptr)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_prli *prli = (struct la_els_prli *)privp->cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_prli *fprli;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct la_els_prli);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = LA_ELS_PRLI;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli = (struct fcp_prli *)prli->service_params;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prli->ls_code = LA_ELS_PRLI;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prli->page_length = 0x10;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prli->payload_length = sizeof (struct la_els_prli);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->type = 0x08; /* no define here? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->resvd1 = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->orig_process_assoc_valid = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->resp_process_assoc_valid = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->establish_image_pair = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->resvd2 = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->resvd3 = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->data_overlay_allowed = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->initiator_fn = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->target_fn = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->cmd_data_mixed = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->data_resp_mixed = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->read_xfer_rdy_disabled = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fprli->write_xfer_rdy_disabled = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&ptr->nport_ww_name, (caddr_t)&privp->port_wwn,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (privp->port_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&ptr->node_ww_name, (caddr_t)&privp->node_wwn,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (privp->node_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_els_transport(sf, privp));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * send an ADISC (address discovery) ELS IU via the transport,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning TRUE upon success, else returning FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_do_adisc(struct sf *sf, struct sf_els_hdr *privp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_adisc *adisc = (struct la_els_adisc *)privp->cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = LA_ELS_ADISC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->ls_code = LA_ELS_ADISC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->mbz[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->mbz[1] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->mbz[2] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->hard_address = 0; /* ??? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct la_els_adisc);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&adisc->port_wwn, sizeof (adisc->port_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&adisc->node_wwn, sizeof (adisc->node_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel adisc->nport_id = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_els_transport(sf, privp));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct fcal_packet *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_els_alloc(struct sf *sf, uchar_t dest_id, int priv_size, int cmd_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rsp_size, caddr_t *rprivp, caddr_t *cmd_buf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t pcookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t rcookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_handle_t cmd_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_handle_t rsp_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_acc_handle_t cmd_acc_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_acc_handle_t rsp_acc_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t real_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t ccount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmd_bound = FALSE, rsp_bound = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t cmd = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t rsp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((fpkt = (struct fcal_packet *)kmem_zalloc(
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct fcal_packet), KM_NOSLEEP)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Could not allocate fcal_packet for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((privp = (struct sf_els_hdr *)kmem_zalloc(priv_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel KM_NOSLEEP)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not allocate sf_els_hdr for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->size = priv_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_private = (caddr_t)privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &cmd_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not allocate DMA handle for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(cmd_dma_handle, cmd_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &cmd,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_size, &cmd_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not allocate DMA memory for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (real_size < cmd_size) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "DMA memory too small for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(cmd_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd, real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not bind DMA memory for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Wrong cookie count for ELS\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &rsp_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not allocate DMA handle for ELS rsp\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(rsp_dma_handle, rsp_size,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &rsp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_size, &rsp_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not allocate DMA memory for ELS rsp\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (real_size < rsp_size) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "DMA memory too small for ELS rsp\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(rsp_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &rcookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Could not bind DMA memory for ELS rsp\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Wrong cookie count for ELS rsp\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->cmd = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->sf = sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->cmd_dma_handle = cmd_dma_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->cmd_acc_handle = cmd_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->rsp = rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->rsp_dma_handle = rsp_dma_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->rsp_acc_handle = rsp_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id = dest_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->fpkt = fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_cookie = sf->sf_socp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_comp = sf_els_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_magic = FCALP_MAGIC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (ushort_t)(SOC_FC_HEADER | sf->sf_sochandle->fcal_portno);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = cmd_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_base = (uint32_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcookie.dmac_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count = cmd_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[1].fc_base = (uint32_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rcookie.dmac_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[1].fc_count = rsp_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Fill in the Fabric Channel Header */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->r_ctl = R_CTL_ELS_REQ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->d_id = dest_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->s_id = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->type = TYPE_EXTENDED_LS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->reserved1 = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->seq_id = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->df_ctl = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->seq_cnt = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->ox_id = 0xffff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->rx_id = 0xffff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->ro = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *rprivp = (caddr_t)privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *cmd_buf = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->cmd_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->rsp_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_els_free(struct fcal_packet *fpkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp = fpkt->fcal_pkt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->cmd_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(privp->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&privp->cmd_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&privp->cmd_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->rsp_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(privp->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&privp->rsp_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->rsp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&privp->rsp_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->data_dma_handle) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(privp->data_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&privp->data_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->data_buf) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&privp->data_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(privp, privp->size);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(fpkt, sizeof (struct fcal_packet));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_create_target(struct sf *sf, struct sf_els_hdr *privp, int tnum, int64_t lun)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target, *ntarget, *otarget, *ptarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int hash;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int64_t orig_lun = lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* XXXX Work around SCSA limitations. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lun = *((short *)&lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget = kmem_zalloc(sizeof (struct sf_target), KM_NOSLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt != privp->lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf_lookup_target(sf, privp->port_wwn, lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lun != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Since LUNs != 0 are queued up after LUN == 0, find LUN == 0
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * and enqueue the new LUN.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((ptarget = sf_lookup_target(sf, privp->port_wwn,
193974072f41a843678abf5f61979c748687e66bSherry Moore (int64_t)0)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Yeep -- no LUN 0?
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "target 0x%x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "lun %" PRIx64 ": No LUN 0\n", tnum, lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL && ptarget->sft_lip_cnt == sf->sf_lip_cnt &&
193974072f41a843678abf5f61979c748687e66bSherry Moore ptarget->sft_state&SF_TARGET_OFFLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* LUN 0 already finished, duplicate its state */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * LUN 0 online or not examined yet.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Try to bring the LUN back online
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_lip_cnt = privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~(SF_TARGET_OFFLINE|
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_hard_address = sf_switch_to_alpa[tnum];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Initialize new target structure */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&privp->node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&privp->port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_lun.l = lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_lun.l = orig_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_raid_lun = (uint_t)lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Don't let anyone use this till we finishup init. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hash = SF_HASH(privp->port_wwn, lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_next = sf->sf_wwn_lists[hash];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_wwn_lists[hash] = ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_lip_cnt = privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_al_pa = (uchar_t)privp->dest_nport_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_hard_address = sf_switch_to_alpa[tnum];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_device_type = DTYPE_UNKNOWN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_state = SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_pkt_head = (struct sf_pkt *)&ntarget->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_pkt_tail = (struct sf_pkt *)&ntarget->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Traverse the list looking for this target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (target = ptarget; target->sft_next_lun;
193974072f41a843678abf5f61979c748687e66bSherry Moore target = target->sft_next_lun) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel otarget = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_next_lun = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_next_lun = ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ptarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ntarget);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL && target->sft_lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* It's been touched this LIP -- duplicate WWNs */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target); /* And all the baby targets */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "target 0x%x, duplicate port wwns\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tnum);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((otarget = sf->sf_targets[tnum]) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Someone else is in our slot */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&otarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (otarget->sft_lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&otarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, otarget);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "target 0x%x, duplicate switch settings\n", tnum);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&otarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (bcmp((caddr_t)&privp->port_wwn, (caddr_t)&otarget->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_port_wwn, sizeof (privp->port_wwn))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, otarget);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "wwn changed on target 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore tnum);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)&sf->sf_stats.tstats[tnum],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct sf_target_stats));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_targets[tnum] = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target = sf->sf_targets[tnum]) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&privp->node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&privp->port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_lun.l = lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_lun.l = orig_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_raid_lun = (uint_t)lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hash = SF_HASH(privp->port_wwn, lun); /* lun 0 */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_next = sf->sf_wwn_lists[hash];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_wwn_lists[hash] = ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_lip_cnt = privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_hard_address = sf_switch_to_alpa[tnum];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_device_type = DTYPE_UNKNOWN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state = SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_pkt_head = (struct sf_pkt *)&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_pkt_tail = (struct sf_pkt *)&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_targets[tnum] = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_lip_cnt = privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~(SF_TARGET_OFFLINE|SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_hard_address = sf_switch_to_alpa[tnum];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(ntarget, sizeof (struct sf_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * find the target for a given sf instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_lookup_target(struct sf *sf, uchar_t *wwn, int lun)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_lookup_target(struct sf *sf, uchar_t *wwn, int64_t lun)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int hash;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(mutex_owned(&sf->sf_mutex));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hash = SF_HASH(wwn, lun);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_wwn_lists[hash];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifndef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (target->sft_port_wwn)) == 0 &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_lun.l == lun)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (target->sft_port_wwn)) == 0 &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_raid_lun == lun)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Send out a REPORT_LUNS command.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_do_reportlun(struct sf *sf, struct sf_els_hdr *privp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t pcookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_handle_t lun_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_acc_handle_t lun_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t ccount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t real_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t lun_buf = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int handle_bound = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_cmd *reportlun = (struct fcp_cmd *)privp->cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *msg = "Transport";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &lun_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_alloc_handle()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(lun_dma_handle, REPORT_LUNS_SIZE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &lun_buf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_size, &lun_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_mem_alloc()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (real_size < REPORT_LUNS_SIZE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "DMA mem < REPORT_LUNS_SIZE";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(lun_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lun_buf, real_size, DDI_DMA_READ |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_addr_bind_handle()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel handle_bound = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ccount != 1";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->target = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_dma_handle = lun_dma_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_acc_handle = lun_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_buf = lun_buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_comp = sf_reportlun_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct fcp_cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)pcookie.dmac_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->r_ctl = R_CTL_COMMAND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->type = TYPE_SCSI_FCP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)reportlun, sizeof (struct fcp_cmd));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)reportlun->fcp_cdb)->scc_cmd = SCMD_REPORT_LUNS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Now set the buffer size. If DDI gave us extra, that's O.K. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count0 =
193974072f41a843678abf5f61979c748687e66bSherry Moore (real_size&0x0ff);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count1 =
193974072f41a843678abf5f61979c748687e66bSherry Moore (real_size>>8)&0x0ff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count2 =
193974072f41a843678abf5f61979c748687e66bSherry Moore (real_size>>16)&0x0ff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count3 =
193974072f41a843678abf5f61979c748687e66bSherry Moore (real_size>>24)&0x0ff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reportlun->fcp_cntl.cntl_read_data = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reportlun->fcp_cntl.cntl_write_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reportlun->fcp_data_len = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reportlun->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(lun_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* We know he's there, so this should be fast */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_els_transport(sf, privp) == 1)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s failure for REPORTLUN to target 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore msg, sf_alpa_to_switch[privp->dest_nport_id]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lun_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (handle_bound)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(lun_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&lun_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lun_buf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&lun_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Handle the results of a REPORT_LUNS command:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Create additional targets if necessary
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Initiate INQUIRYs on all LUNs.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_reportlun_callback(struct fcal_packet *fpkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_pkt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_report_luns *ptr =
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct scsi_report_luns *)privp->data_buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = privp->sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = privp->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_rsp *rsp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int delayed_retry = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tid = sf_alpa_to_switch[target->sft_hard_address];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i, free_pkt = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel short ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* use as temporary state variable */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->timeout == SF_INVALID_TIMEOUT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = privp->next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmds = fpkt->fcal_ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(ncmds >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds = ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->rsp_dma_handle, 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp = (struct fcp_rsp *)privp->rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!REPORTLUN to al_pa %x pkt status %x scsi status %x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore fpkt->fcal_pkt_status,
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp?rsp->fcp_u.fcp_status.scsi_status:0));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* See if target simply does not support REPORT_LUNS. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK &&
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp->fcp_u.fcp_status.sense_len_set &&
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp->fcp_sense_len >=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel offsetof(struct scsi_extended_sense, es_qual_code)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_extended_sense *sense;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sense = (struct scsi_extended_sense *)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((caddr_t)rsp + sizeof (struct fcp_rsp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel + rsp->fcp_response_len);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sense->es_key == KEY_ILLEGAL_REQUEST) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sense->es_add_code == 0x20) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Fake LUN 0 */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORTLUN Faking good "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "completion for alpa %x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->lun_list_len = FCP_LUN_SIZE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->lun[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->fcp_u.fcp_status.scsi_status =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATUS_GOOD;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (sense->es_add_code == 0x25) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORTLUN device alpa %x "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "key %x code %x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sense->es_key, sense->es_add_code));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (sense->es_key ==
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel KEY_UNIT_ATTENTION &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sense->es_add_code == 0x29) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORTLUN device alpa %x was reset\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORTLUN device alpa %x "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "key %x code %x\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sense->es_key, sense->es_add_code));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX The following is here to handle broken targets -- remove it later */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_reportlun_forever &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sense->es_key == KEY_UNIT_ATTENTION)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto retry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sense->es_key == KEY_NOT_READY)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel delayed_retry = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_rsp_info *bep;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bep = (struct fcp_rsp_info *)(&rsp->
193974072f41a843678abf5f61979c748687e66bSherry Moore fcp_response_len + 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!rsp->fcp_u.fcp_status.rsp_len_set ||
193974072f41a843678abf5f61979c748687e66bSherry Moore bep->rsp_code == FCP_NO_FAILURE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->data_dma_handle,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, 0, DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Convert from #bytes to #ints */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->lun_list_len = ptr->lun_list_len >> 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!REPORTLUN to al_pa %x succeeded: %d LUNs\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id, ptr->lun_list_len));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!ptr->lun_list_len) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* No LUNs? Ya gotta be kidding... */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "SCSI violation -- "
193974072f41a843678abf5f61979c748687e66bSherry Moore "target 0x%x reports no LUNs\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->lun_list_len = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ptr->lun[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count += ptr->lun_list_len - 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < ptr->lun_list_len && privp->lip_cnt ==
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_lip_cnt; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *nprivp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *nfpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* LUN 0 is already in `target' */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ptr->lun[i] != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf_create_target(sf,
193974072f41a843678abf5f61979c748687e66bSherry Moore privp, tid, ptr->lun[i]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nprivp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nfpkt = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nfpkt = sf_els_alloc(sf,
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct sf_els_hdr),
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (union sf_els_cmd),
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (union sf_els_rsp),
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&nprivp,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&rsp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (nprivp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel nprivp->lip_cnt =
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (nfpkt && nprivp &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (sf_do_inquiry(sf, nprivp, target) ==
193974072f41a843678abf5f61979c748687e66bSherry Moore 0)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->
193974072f41a843678abf5f61979c748687e66bSherry Moore lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count --;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!REPORTLUN al_pa %x fcp failure, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "fcp_rsp_code %x scsi status %x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id, bep->rsp_code,
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp ? rsp->fcp_u.fcp_status.scsi_status:0));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp && ((rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel delayed_retry = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (++(privp->retries) < sf_els_retries ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX The following is here to handle broken targets -- remove it later */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelretry:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXXXX */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (delayed_retry) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->retries--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->delayed_retry = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!delayed_retry)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORTLUN to al_pa %x failed, retrying\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list->prev = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!delayed_retry && soc_transport(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt, FCAL_NOSLEEP, CQ_REQUEST_1) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* REPORT_LUN failed -- try inquiry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_do_inquiry(sf, privp, target) != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel free_pkt = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->lip_cnt) {
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!REPORTLUN to target 0x%x failed\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[privp->dest_nport_id]);
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_offline_target(sf, target);
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_device_count--;
193974072f41a843678abf5f61979c748687e66bSherry Moore ASSERT(sf->sf_device_count >= 0);
193974072f41a843678abf5f61979c748687e66bSherry Moore if (sf->sf_device_count == 0)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, privp->lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (free_pkt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_do_inquiry(struct sf *sf, struct sf_els_hdr *privp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_cookie_t pcookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_handle_t inq_dma_handle = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_acc_handle_t inq_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t ccount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel size_t real_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel caddr_t inq_buf = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int handle_bound = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_cmd *inq = (struct fcp_cmd *)privp->cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *msg = "Transport";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &inq_dma_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_alloc_handle()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_mem_alloc(inq_dma_handle, SUN_INQSIZE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &inq_buf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &real_size, &inq_acc_handle) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_mem_alloc()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (real_size < SUN_INQSIZE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "DMA mem < inquiry size";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_dma_addr_bind_handle(inq_dma_handle, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq_buf, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ddi_dma_addr_bind_handle()";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel handle_bound = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ccount != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg = "ccount != 1";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = 0; /* not an ELS command */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->target = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_dma_handle = inq_dma_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_acc_handle = inq_acc_handle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->data_buf = inq_buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_comp = sf_inq_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct fcp_cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (uint32_t)pcookie.dmac_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->r_ctl = R_CTL_COMMAND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->type = TYPE_SCSI_FCP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)inq, sizeof (struct fcp_cmd));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)inq->fcp_cdb)->scc_cmd = SCMD_INQUIRY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((union scsi_cdb *)inq->fcp_cdb)->g0_count0 = SUN_INQSIZE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&target->sft_lun.b, (caddr_t)&inq->fcp_ent_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore FCP_LUN_SIZE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq->fcp_cntl.cntl_read_data = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq->fcp_cntl.cntl_write_data = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq->fcp_data_len = pcookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(inq_dma_handle, (off_t)0, (size_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORDEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(5, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!Sending INQUIRY to al_pa %x lun %" PRIx64 "\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSA_LUN(target)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_els_transport(sf, privp));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s failure for INQUIRY to target 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore msg, sf_alpa_to_switch[privp->dest_nport_id]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (inq_dma_handle != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (handle_bound) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_unbind_handle(inq_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_free_handle(&inq_dma_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (inq_buf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_dma_mem_free(&inq_acc_handle);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called as the pkt_comp routine for INQ packets
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_inq_callback(struct fcal_packet *fpkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_pkt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_inquiry *prt = (struct scsi_inquiry *)privp->data_buf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = privp->sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *tsf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = privp->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_rsp *rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int delayed_retry = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel short ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* use as temporary state variable */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->timeout == SF_INVALID_TIMEOUT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = privp->next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmds = fpkt->fcal_ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(ncmds >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds = ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (size_t)0, DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp = (struct fcp_rsp *)privp->rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!INQUIRY to al_pa %x scsi status %x",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id, rsp->fcp_u.fcp_status.scsi_status));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel !rsp->fcp_u.fcp_status.resid_over &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (!rsp->fcp_u.fcp_status.resid_under ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((SUN_INQSIZE - rsp->fcp_resid) >= SUN_MIN_INQLEN))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_rsp_info *bep;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bep = (struct fcp_rsp_info *)(&rsp->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcp_response_len + 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!rsp->fcp_u.fcp_status.rsp_len_set ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (bep->rsp_code == FCP_NO_FAILURE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!INQUIRY to al_pa %x lun %" PRIx64
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel " succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id, SCSA_LUN(target)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(privp->data_dma_handle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (off_t)0, (size_t)0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_device_type =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prt->inq_dtype;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy(prt, &target->sft_inq,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (*prt));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_device_count >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if ((rsp->fcp_u.fcp_status.scsi_status ==
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATUS_BUSY) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel delayed_retry = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT, "!INQUIRY to al_pa %x fc status %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id, fpkt->fcal_pkt_status));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (++(privp->retries) < sf_els_retries ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status == FCAL_STATUS_MAX_XCHG_EXCEEDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf = sf->sf_sibling;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (tsf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&tsf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf->sf_flag = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tsf->sf_throttle = SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&tsf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel delayed_retry = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (delayed_retry) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->retries--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->delayed_retry = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!delayed_retry) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "INQUIRY to al_pa %x failed, retrying",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list->prev = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* if not delayed call transport to send a pkt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!delayed_retry &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (soc_transport(sf->sf_sochandle, fpkt,
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_NOSLEEP, CQ_REQUEST_1) !=
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_TRANSPORT_SUCCESS)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == privp->lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "INQUIRY to target 0x%x lun %" PRIx64 " failed. "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Retry Count: %d\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_alpa_to_switch[privp->dest_nport_id],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SCSA_LUN(target),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->retries);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_device_count >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, privp->lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_finish_init(struct sf *sf, int lip_cnt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i; /* loop index */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cflag;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target; /* current target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_hp_elem *elem; /* hotplug element created */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN, "!sf_finish_init\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(mutex_owned(&sf->sf_mutex));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* scan all hash queues */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_wwn_lists[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* see if target is not offline */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target->sft_state & SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * target already offline
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto next_entry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * target is not already offline -- see if it has
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * already been marked as ready to go offline
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & SF_TARGET_MARK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * target already marked, so take it offline
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto next_entry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* clear target busy flag */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* is target init not yet done ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cflag = !(target->sft_state & SF_TARGET_INIT_DONE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get pointer to target dip */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dip = target->sft_dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cflag && (dip == NULL)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * target init not yet done &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * devinfo not yet created
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_create_devinfo(sf, target, lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto next_entry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * target init already done || devinfo already created
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(dip != NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf_create_props(dip, target, lip_cnt)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* a problem creating properties */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto next_entry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* create a new element for the hotplug list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((elem = kmem_zalloc(sizeof (struct sf_hp_elem),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel KM_NOSLEEP)) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* fill in the new element */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->dip = dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->target = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->what = SF_ONLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add the new element into the hotplug list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_hp_elem_tail != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail->next = elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail = elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this is the first element in list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_head =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail =
193974072f41a843678abf5f61979c748687e66bSherry Moore elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_signal(&sf->sf_hp_daemon_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* could not allocate memory for element ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_devi_online_async(dip, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelnext_entry:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* ensure no new LIPs have occurred */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt != lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* done scanning all targets in this queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* done with all hash queues */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_ONLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_online_timer = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * create devinfo node
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_create_devinfo(struct sf *sf, struct sf_target *target, int lip_cnt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *cdip = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *nname = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char **compatible = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int ncompatible;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_inquiry *inq = &target->sft_inq;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *scsi_binding_set;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get the 'scsi-binding-set' property */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_prop_lookup_string(DDI_DEV_T_ANY, sf->sf_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &scsi_binding_set) != DDI_PROP_SUCCESS)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_binding_set = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* determine the node name and compatible */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel inq->inq_dtype, NULL, &nname, &compatible, &ncompatible);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (scsi_binding_set)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_prop_free(scsi_binding_set);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* if nodename can't be determined then print a message and skip it */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (nname == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifndef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "%s%d: no driver for device "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel " compatible: %s",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[0], target->sft_port_wwn[1],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[2], target->sft_port_wwn[3],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[4], target->sft_port_wwn[5],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[6], target->sft_port_wwn[7],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_lun.l, *compatible);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "%s%d: no driver for device "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel " compatible: %s",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[0], target->sft_port_wwn[1],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[2], target->sft_port_wwn[3],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[4], target->sft_port_wwn[5],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_port_wwn[6], target->sft_port_wwn[7],
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_raid_lun, *compatible);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate the node */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_devi_alloc(sf->sf_dip, nname,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* decorate the node with compatible */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add addressing properties to the node */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_create_props(cdip, target, lip_cnt) != 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_dip != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_dip = cdip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_devi_online_async(cdip, 0) != DDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto fail;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_nodename_compatible_free(nname, compatible);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelfail:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_hba_nodename_compatible_free(nname, compatible);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cdip != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LIP_CNT_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, TARGET_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LUN_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_devi_free(cdip) != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "ndi_devi_free failed\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cdip == target->sft_dip) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_dip = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * create required properties, returning TRUE iff we succeed, else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_create_props(dev_info_t *cdip, struct sf_target *target, int lip_cnt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id = sf_alpa_to_switch[target->sft_al_pa];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, NODE_WWN_PROP, target->sft_node_wwn, FC_WWN_SIZE) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, PORT_WWN_PROP, target->sft_port_wwn, FC_WWN_SIZE) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_int(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, LIP_CNT_PROP, lip_cnt) != DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_int(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, TARGET_PROP, tgt_id) != DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifndef RAID_LUNS
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_int(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, LUN_PROP, target->sft_lun.l) != DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_prop_update_int(DDI_DEV_T_NONE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip, LUN_PROP, target->sft_raid_lun) != DDI_PROP_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRUE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to offline a target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_offline_target(struct sf *sf, struct sf_target *target)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *next_target = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_hp_elem *elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(mutex_owned(&sf->sf_mutex));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_OFFLINE_TARGET)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!target 0x%x al_pa 0x%x lun %" PRIx64 " offlined\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[target->sft_al_pa],
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa, SCSA_LUN(target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~(SF_TARGET_BUSY|SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* XXXX if this is LUN 0, offline all other LUNs */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (next_target || target->sft_lun.l == 0)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel next_target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* abort all cmds for this target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_abort_all(sf, target, FALSE, sf->sf_lip_cnt, FALSE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & SF_TARGET_INIT_DONE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dip = target->sft_dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_prop_remove(DDI_DEV_T_NONE, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore TARGET_PROP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dip, FCAL_REMOVE_EVENT, &sf_remove_eid,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NDI_EVENT_NOPASS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_run_callbacks(sf->sf_event_hdl,
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_dip, sf_remove_eid, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem = kmem_zalloc(sizeof (struct sf_hp_elem),
193974072f41a843678abf5f61979c748687e66bSherry Moore KM_NOSLEEP);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (elem != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->dip = dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->target = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem->what = SF_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_hp_elem_tail != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail->next = elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail = elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_head =
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_hp_elem_tail =
193974072f41a843678abf5f61979c748687e66bSherry Moore elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_signal(&sf->sf_hp_daemon_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* don't do NDI_DEVI_REMOVE for now */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_devi_offline(dip, 0) != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "target %x lun %" PRIx64 ", "
193974072f41a843678abf5f61979c748687e66bSherry Moore "device offline failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[target->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_al_pa],
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSA_LUN(target)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "target %x, lun %" PRIx64 ", "
193974072f41a843678abf5f61979c748687e66bSherry Moore "device offline succeeded\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[target->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_al_pa],
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSA_LUN(target)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = next_target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * routine to get/set a capability
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * returning:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * 1 (TRUE) boolean capability is true (on get)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * 0 (FALSE) invalid capability, can't set capability (on set),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * or boolean capability is false (on get)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * -1 (UNDEFINED) can't find capability (SCSA) or unsupported capability
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * 3 when getting SCSI version number
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * AL_PA when getting port initiator ID
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_commoncap(struct scsi_address *ap, char *cap,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int val, int tgtonly, int doset)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cidx;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cap == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(3, (sf, CE_WARN, "sf_commoncap: invalid arg"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get index of capability string */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* can't find capability */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (UNDEFINED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (doset) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Process setcap request.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * At present, we can only set binary (0/1) values
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (cidx) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_ARQ: /* can't set this capability */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(3, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_setcap: unsupported %d", cidx));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = UNDEFINED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "set cap: cap=%s,val=0x%x,tgtonly=0x%x"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ",doset=0x%x,rval=%d\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cap, val, tgtonly, doset, rval));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Process getcap request.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (cidx) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_DMA_MAX:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break; /* don't' have this capability */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_INITIATOR_ID:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_ARQ:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = TRUE; /* do have this capability */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_RESET_NOTIFICATION:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_TAGGED_QING:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = TRUE; /* do have this capability */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_SCSI_VERSION:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = 3;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SCSI_CAP_INTERCONNECT_TYPE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = INTERCONNECT_FIBRE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_scsi_getcap: unsupported"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = UNDEFINED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "get cap: cap=%s,val=0x%x,tgtonly=0x%x,"
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "doset=0x%x,rval=%d\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cap, val, tgtonly, doset, rval));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to get a capability
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_getcap(struct scsi_address *ap, char *cap, int whom)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_commoncap(ap, cap, 0, whom, FALSE));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to set a capability
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_setcap(struct scsi_address *ap, char *cap, int value, int whom)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_commoncap(ap, cap, value, whom, TRUE));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to abort a target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd, *ncmd, *pcmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval = 0, t, my_rval = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int old_target_state;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int deferred_destroy;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel deferred_destroy = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt != NULL) {
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth cmd = PKT2CMD(pkt);
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE, "sf_abort packet %p\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void *)fpkt));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmd = sf->sf_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (ncmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ncmd == cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pcmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd->cmd_next = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_head = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel my_rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd = ncmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmd = ncmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ncmd == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state == SF_STATE_ISSUED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to abort command */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (((rval = soc_abort(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp, sf->sf_sochandle->fcal_portno,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt, 1)) == FCAL_ABORTED) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (rval == FCAL_ABORT_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel my_rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (rval == FCAL_BAD_ABORT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel my_rval = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Command Abort failed\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE, "sf_abort target\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt = sf->sf_lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & (SF_TARGET_BUSY |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel old_target_state = target->sft_state;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0, 0, 0, NULL, 0)) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* prepare the packet for transport */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ISSUED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call transport to send a pkt polled
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if that fails call the transport to abort it
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (soc_transport_poll(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_REQUEST_1) == FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_cr_pool->rsp_dma_handle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (off_t)
193974072f41a843678abf5f61979c748687e66bSherry Moore ((caddr_t)cmd->cmd_rsp_block -
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_cr_pool->rsp_base),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCP_MAX_RSP_IU_SIZE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (((struct fcp_rsp_info *)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (&cmd->cmd_rsp_block->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcp_response_len + 1))->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_code == FCP_NO_FAILURE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* abort cmds for this targ */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_abort_all(sf, target, TRUE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt, TRUE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &cmd->cmd_fp_pkt->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_socal_request.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)hp->d_id];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[tgt_id].
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel task_mgmt_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Target %d Abort Task "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Set failed\n", hp->d_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
193974072f41a843678abf5f61979c748687e66bSherry Moore mutex_enter(&cmd->cmd_abort_mutex);
193974072f41a843678abf5f61979c748687e66bSherry Moore if (cmd->cmd_state == SF_STATE_ISSUED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time
193974072f41a843678abf5f61979c748687e66bSherry Moore + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((t = soc_abort(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp, sf->sf_sochandle->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_portno, cmd->cmd_fp_pkt, 1)) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_ABORTED &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (t != FCAL_ABORT_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_abort failed, "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "initiating LIP\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel deferred_destroy = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
193974072f41a843678abf5f61979c748687e66bSherry Moore } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!deferred_destroy) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_scsi_destroy_pkt(ap, pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel my_rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state = old_target_state;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (my_rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport and internally to reset a target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_reset(struct scsi_address *ap, int level)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(ap), *ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval = FALSE, t;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id, ret;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int deferred_destroy;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* We don't support RESET_LUN yet. */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (level == RESET_TARGET) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_reset_list *p;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((p = kmem_alloc(sizeof (struct sf_reset_list), KM_NOSLEEP))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel == NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_NOTE, "sf_reset target\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* All target resets go to LUN 0 */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_lun.l) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf_lookup_target(sf, target->sft_port_wwn, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & (SF_TARGET_BUSY |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(p, sizeof (struct sf_reset_list));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt = sf->sf_lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (ntarget = target->sft_next_lun;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget = ntarget->sft_next_lun) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * XXXX If we supported RESET_LUN we should check here
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * to see if any LUN were being reset and somehow fail
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * that operation.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel deferred_destroy = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel 0, 0, 0, NULL, 0)) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block->fcp_cntl.cntl_reset = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* prepare the packet for transport */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to send a pkt polled */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ISSUED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((ret = soc_transport_poll(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_REQUEST_1)) == FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(cmd->cmd_cr_pool->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_dma_handle, (caddr_t)cmd->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd_rsp_block - cmd->cmd_cr_pool->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_base, FCP_MAX_RSP_IU_SIZE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((fpkt->fcal_pkt_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_STATUS_OK) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (((struct fcp_rsp_info *)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (&cmd->cmd_rsp_block->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcp_response_len + 1))->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_code == FCP_NO_FAILURE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!sf%d: Target 0x%x Reset "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "successful\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(\
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_dip),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &cmd->cmd_fp_pkt->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcal_socal_request.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)hp->d_id];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[tgt_id].
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel task_mgmt_failures++;
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!sf%d: Target 0x%x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Reset failed."
193974072f41a843678abf5f61979c748687e66bSherry Moore "Status code 0x%x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Resp code 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(\
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_dip),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_pkt_status,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct fcp_rsp_info *)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (&cmd->cmd_rsp_block->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcp_response_len + 1))->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp_code);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_NOTE, "!sf%d: Target "
193974072f41a843678abf5f61979c748687e66bSherry Moore "0x%x Reset Failed. Ret=%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(sf->sf_dip),
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa], ret);
193974072f41a843678abf5f61979c748687e66bSherry Moore mutex_enter(&cmd->cmd_abort_mutex);
193974072f41a843678abf5f61979c748687e66bSherry Moore if (cmd->cmd_state == SF_STATE_ISSUED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to abort a cmd */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time
193974072f41a843678abf5f61979c748687e66bSherry Moore + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (((t = soc_abort(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt, 1)) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_ABORTED) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (t != FCAL_ABORT_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!sf%d: Target 0x%x Reset "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "failed. Abort Failed, "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "forcing LIP\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_dip),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel deferred_destroy = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
193974072f41a843678abf5f61979c748687e66bSherry Moore } else {
193974072f41a843678abf5f61979c748687e66bSherry Moore mutex_exit
193974072f41a843678abf5f61979c748687e66bSherry Moore (&cmd->cmd_abort_mutex);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Defer releasing the packet if we abort returned with
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * a BAD_ABORT or timed out, because there is a
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * possibility that the ucode might return it.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * We wait for at least 20s and let it be released
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * by the sf_watch thread
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!deferred_destroy) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_block->fcp_cntl.cntl_reset = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* for cache */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_scsi_destroy_pkt(ap, pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "!sf%d: Target 0x%x Reset Failed. "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Resource allocation error.\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(sf->sf_dip),
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[target->sft_al_pa]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((rval == TRUE) && (lip_cnt == sf->sf_lip_cnt)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel p->target = target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel p->lip_cnt = lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel p->timeout = ddi_get_lbolt() +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel drv_usectohz(SF_TARGET_RESET_DELAY);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel p->next = sf->sf_reset_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_reset_list = p;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_reset_timeout_id == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_reset_timeout_id = timeout(
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_check_reset_delay, NULL,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel drv_usectohz(SF_TARGET_RESET_DELAY));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (ntarget = target->sft_next_lun;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget;
193974072f41a843678abf5f61979c748687e66bSherry Moore ntarget = ntarget->sft_next_lun) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget->sft_state &= ~SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&ntarget->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(p, sizeof (struct sf_reset_list));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_state == SF_STATE_OFFLINE) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sf_watchdog_time < sf->sf_timer)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * We are currently in a lip, so let this one
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * finish before forcing another one.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRUE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "!sf:Target driver initiated lip\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * abort all commands for a target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if try_abort is set then send an abort
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if abort is set then this is abort, else this is a reset
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_abort_all(struct sf *sf, struct sf_target *target, int abort, int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt, int try_abort)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *ntarget;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd, *head = NULL, *tail = NULL, *pcmd = NULL, *tcmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval = FCAL_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * First pull all commands for all LUNs on this target out of the
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * overflow list. We can tell it's the same target by comparing
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the node WWN.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = sf->sf_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ntarget = ADDR2TARGET(&cmd->cmd_pkt->
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ntarget == target) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pcmd != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd->cmd_next = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_head = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_pkt_tail == cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_tail = pcmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pcmd != NULL)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd->cmd_next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tcmd = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (head == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel head = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tail = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tail->cmd_next = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tail = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = tcmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pcmd = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Now complete all the commands on our list. In the process,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the completion routine may take the commands off the target
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * lists.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (abort) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_DEV_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * call the packet completion routine only for
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * non-polled commands. Ignore the polled commands as
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * they timeout and will be handled differently
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((pkt->pkt_comp) && !(pkt->pkt_flags & FLAG_NOINTR))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Finally get all outstanding commands for each LUN, and abort them if
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * they've been issued, and call the completion routine.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * For the case where sf_offline_target is called from sf_watch
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * due to a Offline Timeout, it is quite possible that the soc+
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * ucode is hosed and therefore cannot return the commands.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Clear up all the issued commands as well.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Try_abort will be false only if sf_abort_all is coming from
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * sf_target_offline.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (try_abort || sf->sf_state == SF_STATE_OFFLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = tcmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd->cmd_state == SF_STATE_ISSUED) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (fpkt->fcal_cmd_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore FCAL_CMD_IN_TRANSPORT) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore ((fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE) ==
193974072f41a843678abf5f61979c748687e66bSherry Moore 0) && !(pkt->pkt_flags & FLAG_NOINTR)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_time + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (try_abort) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to abort a pkt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = soc_abort(sf->sf_sochandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_socp,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_sochandle->fcal_portno,
193974072f41a843678abf5f61979c748687e66bSherry Moore fpkt, 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((rval == FCAL_ABORTED) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (rval == FCAL_ABORT_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (abort) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |=
193974072f41a843678abf5f61979c748687e66bSherry Moore STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |=
193974072f41a843678abf5f61979c748687e66bSherry Moore STAT_DEV_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt != sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_forw;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to start a packet
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd = PKT2CMD(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(6, (sf, CE_NOTE, "sf_start\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state == SF_STATE_ISSUED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_PANIC, "sf: issuing packet twice 0x%p\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* prepare the packet for transport */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((rval = sf_prepare_pkt(sf, cmd, target)) != TRAN_ACCEPT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & (SF_TARGET_BUSY|SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & SF_TARGET_OFFLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_FATAL_ERROR);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_flags & FLAG_NOINTR) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_BUSY);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_use_lock = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto enque;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* if no interrupts then do polled I/O */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_flags & FLAG_NOINTR) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_dopoll(sf, cmd));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* regular interrupt-driven I/O */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf->sf_use_lock) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* locking no needed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ISSUED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to send a pkt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_NOSLEEP, CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_BADPKT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_ACCEPT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* regular I/O using locking */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_ncmds >= sf->sf_throttle) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sf->sf_pkt_head != NULL)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelenque:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * either we're throttling back or there are already commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * on the queue, so enqueue this one for later
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags |= CFLAG_IN_QUEUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_pkt_head != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* add to the queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_tail->cmd_next = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_tail = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this is the first entry in the queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_head = sf->sf_pkt_tail = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_ACCEPT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * start this packet now
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* still have cmd mutex */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf_start_internal(sf, cmd));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * internal routine to start a packet from the queue now
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * enter with cmd mutex held and leave with it released
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_start_internal(struct sf *sf, struct sf_pkt *cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* we have the cmd mutex */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(6, (sf, CE_NOTE, "sf_start_internal\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? sf_watchdog_time +
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_time : 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ISSUED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to send the pkt */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt, FCAL_NOSLEEP,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_BADPKT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_ACCEPT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * prepare a packet for transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_prepare_pkt(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_cmd *fcmd = cmd->cmd_block;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* XXXX Need to set the LUN ? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&target->sft_lun.b,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)&fcmd->fcp_ent_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore FCP_LUN_SIZE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_state = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_statistics = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd->cmd_pkt->pkt_comp == NULL) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_BADPKT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* invalidate imp field(s) of rsp block */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_rsp_block->fcp_u.i_fcp_status = SF_BAD_DMA_MAGIC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up amt of I/O to do */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_resid = cmd->cmd_dmacount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_CMDIOPB) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel DDI_DMA_SYNC_FORDEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_pkt->pkt_resid = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* set up the Tagged Queuing type */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Sync the cmd segment
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(cmd->cmd_cr_pool->cmd_dma_handle,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)fcmd - cmd->cmd_cr_pool->cmd_base,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct fcp_cmd), DDI_DMA_SYNC_FORDEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_fill_ids(sf, cmd, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_ACCEPT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * fill in packet hdr source and destination IDs and hdr byte count
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_fill_ids(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->d_id = target->sft_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->s_id = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_dmacookie.dmac_size;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * do polled I/O using transport
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_dopoll(struct sf *sf, struct sf_pkt *cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int timeout;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel timeout = cmd->cmd_pkt->pkt_time ? cmd->cmd_pkt->pkt_time
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel : SF_POLL_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ISSUED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to send a pkt polled */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = soc_transport_poll(sf->sf_sochandle, cmd->cmd_fp_pkt,
193974072f41a843678abf5f61979c748687e66bSherry Moore timeout*1000000, CQ_REQUEST_1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rval != FCAL_TRANSPORT_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rval == FCAL_TRANSPORT_TIMEOUT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sf_target_timeout(sf, cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_BADPKT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_cmd_callback(cmd->cmd_fp_pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (TRAN_ACCEPT);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* a shortcut for defining debug messages below */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_DMSG1(s) msg1 = s
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#define SF_DMSG1(s) /* do nothing */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the pkt_comp callback for command packets
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_cmd_callback(struct fcal_packet *fpkt)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd = (struct sf_pkt *)fpkt->fcal_pkt_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ADDR2SF(&pkt->pkt_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = ADDR2TARGET(&pkt->pkt_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcp_rsp *rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *msg1 = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char *msg2 = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel short ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int good_scsi_status = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state == SF_STATE_IDLE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_PANIC, "sf: completing idle packet 0x%p\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state == SF_STATE_ABORTING) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* cmd already being aborted -- nothing to do */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(cmd->cmd_cr_pool->rsp_dma_handle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)cmd->cmd_rsp_block - cmd->cmd_cr_pool->rsp_base,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCP_MAX_RSP_IU_SIZE, DDI_DMA_SYNC_FORKERNEL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp = (struct fcp_rsp *)cmd->cmd_rsp_block;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp->fcp_u.i_fcp_status == SF_BAD_DMA_MAGIC) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_BAD_DMA)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_INCOMPLETE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state = STATE_GOT_BUS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
193974072f41a843678abf5f61979c748687e66bSherry Moore STATE_SENT_CMD | STATE_GOT_STATUS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_resid = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMAVALID) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state |= STATE_XFERRED_DATA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((pkt->pkt_scbp != NULL) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((*(pkt->pkt_scbp) =
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp->fcp_u.fcp_status.scsi_status)
193974072f41a843678abf5f61979c748687e66bSherry Moore != STATUS_GOOD)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel good_scsi_status = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * The next two checks make sure that if there
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * is no sense data or a valid response and
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the command came back with check condition,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the command should be retried
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!rsp->fcp_u.fcp_status.rsp_len_set &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel !rsp->fcp_u.fcp_status.sense_len_set) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state &= ~STATE_XFERRED_DATA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_resid = cmd->cmd_dmacount;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (pkt->pkt_state & STATE_XFERRED_DATA)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ddi_dma_sync(cmd->cmd_dmahandle, 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint_t)0, DDI_DMA_SYNC_FORCPU);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Update the transfer resid, if appropriate
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp->fcp_u.fcp_status.resid_over ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->fcp_u.fcp_status.resid_under)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_resid = rsp->fcp_resid;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Check to see if the SCSI command failed.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * First see if we got a FCP protocol error.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp->fcp_u.fcp_status.rsp_len_set) {
193974072f41a843678abf5f61979c748687e66bSherry Moore struct fcp_rsp_info *bep;
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore bep = (struct fcp_rsp_info *)
193974072f41a843678abf5f61979c748687e66bSherry Moore (&rsp->fcp_response_len + 1);
193974072f41a843678abf5f61979c748687e66bSherry Moore if (bep->rsp_code != FCP_NO_FAILURE) {
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt->pkt_reason = CMD_TRAN_ERR;
193974072f41a843678abf5f61979c748687e66bSherry Moore tgt_id = pkt->pkt_address.a_target;
193974072f41a843678abf5f61979c748687e66bSherry Moore switch (bep->rsp_code) {
193974072f41a843678abf5f61979c748687e66bSherry Moore case FCP_CMND_INVALID:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP FCP_CMND "
193974072f41a843678abf5f61979c748687e66bSherry Moore "fields invalid");
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore case FCP_TASK_MGMT_NOT_SUPPTD:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP Task"
193974072f41a843678abf5f61979c748687e66bSherry Moore "Management Function"
193974072f41a843678abf5f61979c748687e66bSherry Moore "Not Supported");
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore case FCP_TASK_MGMT_FAILED:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP Task "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Management Function"
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed");
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_stats.tstats[tgt_id].
193974072f41a843678abf5f61979c748687e66bSherry Moore task_mgmt_failures++;
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore case FCP_DATA_RO_MISMATCH:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP FCP_DATA RO "
193974072f41a843678abf5f61979c748687e66bSherry Moore "mismatch with "
193974072f41a843678abf5f61979c748687e66bSherry Moore "FCP_XFER_RDY DATA_RO");
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_stats.tstats[tgt_id].
193974072f41a843678abf5f61979c748687e66bSherry Moore data_ro_mismatches++;
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore case FCP_DL_LEN_MISMATCH:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP FCP_DATA "
193974072f41a843678abf5f61979c748687e66bSherry Moore "length "
193974072f41a843678abf5f61979c748687e66bSherry Moore "different than BURST_LEN");
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_stats.tstats[tgt_id].
193974072f41a843678abf5f61979c748687e66bSherry Moore dl_len_mismatches++;
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore default:
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DMSG1("FCP_RSP invalid "
193974072f41a843678abf5f61979c748687e66bSherry Moore "RSP_CODE");
193974072f41a843678abf5f61979c748687e66bSherry Moore break;
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * See if we got a SCSI error with sense data
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp->fcp_u.fcp_status.sense_len_set) {
193974072f41a843678abf5f61979c748687e66bSherry Moore uchar_t rqlen = min(rsp->fcp_sense_len,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct scsi_extended_sense));
193974072f41a843678abf5f61979c748687e66bSherry Moore caddr_t sense = (caddr_t)rsp +
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct fcp_rsp) +
193974072f41a843678abf5f61979c748687e66bSherry Moore rsp->fcp_response_len;
193974072f41a843678abf5f61979c748687e66bSherry Moore struct scsi_arq_status *arq;
193974072f41a843678abf5f61979c748687e66bSherry Moore struct scsi_extended_sense *sensep =
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct scsi_extended_sense *)sense;
193974072f41a843678abf5f61979c748687e66bSherry Moore
193974072f41a843678abf5f61979c748687e66bSherry Moore if (rsp->fcp_u.fcp_status.scsi_status !=
193974072f41a843678abf5f61979c748687e66bSherry Moore STATUS_GOOD) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rsp->fcp_u.fcp_status.scsi_status
193974072f41a843678abf5f61979c748687e66bSherry Moore == STATUS_CHECK) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sensep->es_key ==
193974072f41a843678abf5f61979c748687e66bSherry Moore KEY_RECOVERABLE_ERROR)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel good_scsi_status = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sensep->es_key ==
193974072f41a843678abf5f61979c748687e66bSherry Moore KEY_UNIT_ATTENTION &&
193974072f41a843678abf5f61979c748687e66bSherry Moore sensep->es_add_code == 0x3f &&
193974072f41a843678abf5f61979c748687e66bSherry Moore sensep->es_qual_code == 0x0e) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* REPORT_LUNS_HAS_CHANGED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!REPORT_LUNS_HAS_CHANGED\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
193974072f41a843678abf5f61979c748687e66bSherry Moore if ((pkt->pkt_scbp != NULL) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (cmd->cmd_scblen >=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct scsi_arq_status))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state |= STATE_ARQ_DONE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel arq = (struct scsi_arq_status *)pkt->pkt_scbp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * copy out sense information
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy(sense, (caddr_t)&arq->sts_sensedata,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rqlen);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel arq->sts_rqpkt_resid =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct scsi_extended_sense) -
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rqlen;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *((uchar_t *)&arq->sts_rqpkt_status) =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATUS_GOOD;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel arq->sts_rqpkt_reason = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel arq->sts_rqpkt_statistics = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel arq->sts_rqpkt_state = STATE_GOT_BUS |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATE_GOT_TARGET | STATE_SENT_CMD |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATE_GOT_STATUS | STATE_ARQ_DONE |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel STATE_XFERRED_DATA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_alive = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * The firmware returns the number of bytes actually
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * xfered into/out of host. Compare this with what
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * we asked and if it is different, we lost frames ?
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((pkt->pkt_reason == 0) && (pkt->pkt_resid == 0) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (good_scsi_status) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (pkt->pkt_state & STATE_XFERRED_DATA) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (!(cmd->cmd_flags & CFLAG_CMDIOPB)) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (target->sft_device_type != DTYPE_ESI)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int byte_cnt =
193974072f41a843678abf5f61979c748687e66bSherry Moore fpkt->fcal_socal_request.
193974072f41a843678abf5f61979c748687e66bSherry Moore sr_soc_hdr.sh_byte_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_flags & CFLAG_DMASEND) {
193974072f41a843678abf5f61979c748687e66bSherry Moore if (byte_cnt != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!sf_cmd_callback: Lost Frame: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(write) received 0x%x expected"
193974072f41a843678abf5f61979c748687e66bSherry Moore " 0x%x target 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore byte_cnt, cmd->cmd_dmacount,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_INCOMPLETE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (byte_cnt < cmd->cmd_dmacount) {
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!sf_cmd_callback: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Lost Frame: (read) "
193974072f41a843678abf5f61979c748687e66bSherry Moore "received 0x%x expected 0x%x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "target 0x%x\n", byte_cnt,
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_dmacount,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_al_pa]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_INCOMPLETE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* pkt status was not ok */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (fpkt->fcal_pkt_status) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_ERR_OFFLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Offline");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= (SF_TARGET_BUSY
193974072f41a843678abf5f61979c748687e66bSherry Moore | SF_TARGET_MARK);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_dip, FCAL_REMOVE_EVENT,
193974072f41a843678abf5f61979c748687e66bSherry Moore &sf_remove_eid, NDI_EVENT_NOPASS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_run_callbacks(sf->sf_event_hdl,
193974072f41a843678abf5f61979c748687e66bSherry Moore target->sft_dip, sf_remove_eid, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_BUS_RESET;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_MAX_XCHG_EXCEEDED:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_throttle(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_use_lock = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state = STATE_GOT_BUS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_TIMEOUT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Timeout");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_ERR_OVERRUN:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("CMD_DATA_OVR");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_DATA_OVR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_UNKNOWN_CQ_TYPE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Unknown CQ type");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_BAD_SEG_CNT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Bad SEG CNT");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_BAD_XID:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Invalid X_ID");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_XCHG_BUSY:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Exchange Busy");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_INSUFFICIENT_CQES:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Insufficient CQEs");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_ALLOC_FAIL:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("ALLOC FAIL");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_BAD_SID:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Invalid S_ID");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_INCOMPLETE_DMA_ERR:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_INCOMPLETE_DMA)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg2 =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "INCOMPLETE DMA XFER due to bad SOC+ card, replace HBA";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_INCOMPLETE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state = STATE_GOT_BUS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_CRC_ERR:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel msg2 = "Fibre Channel CRC Error on frames";
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_INCOMPLETE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_state = STATE_GOT_BUS;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_ABORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_NO_SEQ_INIT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Seq Init Error");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_OPEN_FAIL:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Open Failure");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target->sft_state & (SF_TARGET_BUSY |
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_TARGET_MARK | SF_TARGET_OFFLINE)) == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!Open failure to target 0x%x "
193974072f41a843678abf5f61979c748687e66bSherry Moore "forcing LIP\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[target->sft_al_pa]);
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_STATUS_ONLINE_TIMEOUT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Fibre Channel Online Timeout");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DMSG1("Unknown FC Status");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * msg1 will be non-NULL if we've detected some sort of error
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (msg1 != NULL && sfdebug >= 4) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "!Transport error on cmd=0x%p target=0x%x: %s\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void *)fpkt, pkt->pkt_address.a_target, msg1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (msg2 != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "!Transport error on target=0x%x: %s\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_address.a_target, msg2);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ncmds = fpkt->fcal_ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(ncmds >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ncmds >= (sf->sf_throttle - SF_HI_CMD_DELTA)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf->sf_use_lock) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_NOTE, "use lock flag on\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_use_lock = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds = ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_throttle_start(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!msg1 && !msg2)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(6, (sf, CE_NOTE, "Completing pkt 0x%p\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void *)pkt));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#undef SF_DMSG1
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * start throttling for this instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_throttle_start(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd, *prev_cmd = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(mutex_owned(&sf->sf_cmd_mutex));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = sf->sf_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while ((cmd != NULL) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sf->sf_state == SF_STATE_ONLINE) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sf->sf_ncmds < sf->sf_throttle)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = CMD2PKT(cmd);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = ADDR2TARGET(&pkt->pkt_address);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & SF_TARGET_BUSY) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this command is busy -- go to next */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev_cmd = cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel continue;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this cmd not busy and not issued */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove this packet from the queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_pkt_head == cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this was the first packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_head = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (sf->sf_pkt_tail == cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* this was the last packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_pkt_tail = prev_cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (prev_cmd != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev_cmd->cmd_next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* some packet in the middle of the queue */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(prev_cmd != NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev_cmd->cmd_next = cmd->cmd_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_state & SF_TARGET_OFFLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(cmd->cmd_pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_fill_ids(sf, cmd, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_start_internal(sf, cmd) != TRAN_ACCEPT) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TRAN_ERR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(cmd->cmd_pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = sf->sf_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel prev_cmd = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called when the max exchange value is exceeded to throttle back commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_throttle(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmdmax = sf->sf_sochandle->fcal_cmdmax;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_flag = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ncmds > (cmdmax / 2)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = cmdmax / 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ncmds > SF_DECR_DELTA) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * This case is just a safeguard, should not really
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * happen(ncmds < SF_DECR_DELTA and MAX_EXCHG exceed
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = sf->sf_sibling;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_flag = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ncmds >= (cmdmax / 2)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = cmdmax / 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ncmds > SF_DECR_DELTA) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = SF_DECR_DELTA;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * sf watchdog routine, called for a timeout
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*ARGSUSED*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_watch(void *arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel static int count = 0, pscan_count = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmdmax, i, mescount = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_time += sf_watchdog_timeout;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel count++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pscan_count++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watch_running = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* disable throttling while we're suspended */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state & SF_STATE_SUSPENDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_watch, sf%d:throttle disabled "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "due to DDI_SUSPEND\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel continue;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmdmax = sf->sf_sochandle->fcal_cmdmax;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_take_core) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf->sf_flag) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_throttle < (cmdmax / 2)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = cmdmax / 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if ((sf->sf_throttle += SF_INCR_DELTA) >
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmdmax) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_throttle = cmdmax;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_flag = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds_exp_avg = (sf->sf_ncmds + sf->sf_ncmds_exp_avg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel >> 2;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_ncmds <= (sf->sf_throttle - SF_LO_CMD_DELTA)) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (sf->sf_pkt_head == NULL)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_use_lock) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(4, (sf, CE_NOTE,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "use lock flag off\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_use_lock = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state == SF_STATE_ONLINE && sf->sf_pkt_head &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_ncmds < sf->sf_throttle) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_throttle_start(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_cmd_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pscan_count >= sf_pool_scan_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_ncmds_exp_avg < (sf->sf_cr_pool_cnt <<
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_LOG2_ELEMS_IN_POOL) - SF_FREE_CR_EPSILON) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_crpool_free(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (privp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->timeout < sf_watchdog_time) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* timeout this command */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = sf_els_timeout(sf, privp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if ((privp->timeout == SF_INVALID_TIMEOUT) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (privp->lip_cnt != sf->sf_lip_cnt)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(privp->fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_online_timer && sf->sf_online_timer <
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_time) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!mescount && target->sft_state &
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_TARGET_BUSY) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN, "!Loop "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Unstable: Failed to bring "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Loop Online\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mescount = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_MARK;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, sf->sf_lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_INIT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_online_timer = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state == SF_STATE_ONLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (count >= sf_pkt_scan_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_check_targets(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if ((sf->sf_state == SF_STATE_OFFLINE) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (sf->sf_timer < sf_watchdog_time)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target != NULL) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (target->sft_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_BUSY)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!Offline Timeout\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core &
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_CORE_OFFLINE_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_sochandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf, sf->sf_lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_INIT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (count >= sf_pkt_scan_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel count = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pscan_count >= sf_pool_scan_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pscan_count = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* reset timeout */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watchdog_id = timeout(sf_watch, (caddr_t)0, sf_watchdog_tick);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* signal waiting thread */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_watch_running = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_broadcast(&sf_watch_cv);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called during a timeout to check targets
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_check_targets(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_pkt *cmd;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt = sf->sf_lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* check scan all possible targets */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_alive && target->sft_scan_count !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_target_scan_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_alive = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_scan_count++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_alive = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_scan_count = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cmd->cmd_state == SF_STATE_ISSUED &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((cmd->cmd_timeout && sf_watchdog_time >
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout) || sf_abort_flag)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_abort_flag = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#else
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_timeout))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* prevent reset from getting at this packet */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_ABORTING;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[i].timeouts++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_target_timeout(sf, cmd))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt != sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if the abort and lip fail, a reset will be carried out.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * But the reset will ignore this packet. We have waited at least
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * 20 seconds after the initial timeout. Now, complete it here.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * This also takes care of spurious bad aborts.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if ((cmd->cmd_state ==
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_STATE_ABORTING) && (cmd->cmd_timeout
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel <= sf_watchdog_time)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_DEBUG(1, (sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Command 0x%p to sft 0x%p"
193974072f41a843678abf5f61979c748687e66bSherry Moore " delayed release\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)cmd, (void *)target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (STAT_TIMEOUT|STAT_ABORTED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp) {
9c57abc8d70cb139020be846baec0a9c4d9a73cdsrivijitha dugganapalli scsi_hba_pkt_comp(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* handle deferred_destroy case */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
193974072f41a843678abf5f61979c748687e66bSherry Moore if ((cmd->cmd_block->fcp_cntl.
193974072f41a843678abf5f61979c748687e66bSherry Moore cntl_reset == 1) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (cmd->cmd_block->
193974072f41a843678abf5f61979c748687e66bSherry Moore fcp_cntl.cntl_abort_tsk ==
193974072f41a843678abf5f61979c748687e66bSherry Moore 1)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_block->
193974072f41a843678abf5f61979c748687e66bSherry Moore fcp_cntl.
193974072f41a843678abf5f61979c748687e66bSherry Moore cntl_reset = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_block->
193974072f41a843678abf5f61979c748687e66bSherry Moore fcp_cntl.
193974072f41a843678abf5f61979c748687e66bSherry Moore cntl_abort_tsk = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd->cmd_fp_pkt->
193974072f41a843678abf5f61979c748687e66bSherry Moore fcal_pkt_comp =
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_cmd_callback;
193974072f41a843678abf5f61979c748687e66bSherry Moore /* for cache */
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_scsi_destroy_pkt
193974072f41a843678abf5f61979c748687e66bSherry Moore (&pkt->pkt_address,
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = target->sft_pkt_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&cmd->cmd_abort_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd = cmd->cmd_forw;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_pkt_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * a command to a target has timed out
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * return TRUE iff cmd abort failed or timed out, else return FALSE
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_target_timeout(struct sf *sf, struct sf_pkt *cmd)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_pkt *pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int retval = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "Command 0x%p to target %x timed out\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void *)cmd->cmd_fp_pkt, cmd->cmd_pkt->pkt_address.a_target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth fpkt = cmd->cmd_fp_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_CMD_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to abort a command */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = soc_abort(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, fpkt, 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (rval) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_ABORTED:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "Command Abort succeeded\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= (STAT_TIMEOUT|STAT_ABORTED);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break; /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_ABORT_FAILED:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "Command Abort failed at target\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_state = SF_STATE_IDLE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_reason = CMD_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt->pkt_statistics |= STAT_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = pkt->pkt_address.a_target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[tgt_id].abts_failures++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (pkt->pkt_comp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (*pkt->pkt_comp)(pkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_BAD_ABORT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_BAD_ABORT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "Command Abort bad abort\n"));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmd->cmd_timeout = sf_watchdog_time + cmd->cmd_pkt->pkt_time
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel + 20;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case FCAL_TIMEOUT:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel pkt = cmd->cmd_pkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = pkt->pkt_address.a_target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_WARN,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "Command Abort failed target 0x%x, forcing a LIP\n", tgt_id);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_ABORT_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (retval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * an ELS command has timed out
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * return ???
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_els_hdr *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_els_timeout(struct sf *sf, struct sf_els_hdr *privp)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int rval, dflag, timeout = SF_ELS_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t lip_cnt = privp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uchar_t els_code = privp->els_code;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target = privp->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char what[64];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dflag = privp->delayed_retry;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* use as temporary state variable */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = SF_INVALID_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->fpkt->fcal_pkt_comp == sf_els_callback) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * take socal core if required. Timeouts for IB and hosts
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * are not very interesting, so we take socal core only
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * if the timeout is *not* for a IB or host.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_ELS_TIMEOUT) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore ((sf_alpa_to_switch[privp->dest_nport_id] &
193974072f41a843678abf5f61979c748687e66bSherry Moore 0x0d) != 0x0d) && ((privp->dest_nport_id != 1) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (privp->dest_nport_id != 2) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (privp->dest_nport_id != 4) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (privp->dest_nport_id != 8) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (privp->dest_nport_id != 0xf))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(what, "ELS 0x%x", privp->els_code);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (privp->fpkt->fcal_pkt_comp == sf_reportlun_callback) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_REPORTLUN_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel timeout = SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(what, "REPORT_LUNS");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (privp->fpkt->fcal_pkt_comp == sf_inq_callback) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_INQUIRY_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel timeout = SF_FCP_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(what, "INQUIRY to LUN 0x%lx",
193974072f41a843678abf5f61979c748687e66bSherry Moore (long)SCSA_LUN(target));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sprintf(what, "UNKNOWN OPERATION");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (dflag) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* delayed retry */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(2, (sf, CE_CONT,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!sf%d: %s to target %x delayed retry\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(sf->sf_dip), what,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[privp->dest_nport_id]));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->delayed_retry = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto try_again;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "!%s to target 0x%x alpa 0x%x timed out\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore what, sf_alpa_to_switch[privp->dest_nport_id],
193974072f41a843678abf5f61979c748687e66bSherry Moore privp->dest_nport_id);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rval = soc_abort(sf->sf_sochandle, sf->sf_socp, sf->sf_sochandle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ->fcal_portno, fpkt, 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rval == FCAL_ABORTED || rval == FCAL_ABORT_FAILED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "!%s abort to al_pa %x succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel what, privp->dest_nport_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8steveltry_again:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->prev != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev->next = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_els_list == privp) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_els_list = privp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (privp->next != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->next->prev = privp->prev;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->prev = privp->next = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = sf_watchdog_time + timeout;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((++(privp->retries) < sf_els_retries) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (dflag && (privp->retries < SF_BSY_RETRIES))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!%s to target 0x%x retrying\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore what,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[privp->dest_nport_id]);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_els_transport(sf, privp) == 1) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (sf->sf_els_list); /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((lip_cnt == sf->sf_lip_cnt) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (els_code != LA_ELS_LOGO)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_offline_target(sf, target);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_device_count--;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ASSERT(sf->sf_device_count >= 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_device_count == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_finish_init(sf,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = sf->sf_els_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (fpkt != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_els_free(privp->fpkt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_ELS_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_token = (int *)(uintptr_t)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.\
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sr_soc_hdr.sh_request_token;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "%s abort to target 0x%x failed. "
193974072f41a843678abf5f61979c748687e66bSherry Moore "status=0x%x, forcing LIP\n", what,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_alpa_to_switch[privp->dest_nport_id], rval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lip_cnt == lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (privp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by timeout when a reset times out
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*ARGSUSED*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_check_reset_delay(void *arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_reset_list *rp, *tp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uint_t lip_cnt, reset_timeout_flag = FALSE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel clock_t lb;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lb = ddi_get_lbolt();
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_reset_timeout_id = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* is this type cast needed? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp = (struct sf_reset_list *)&sf->sf_reset_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rp = sf->sf_reset_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (rp != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (((rp->timeout - lb) < 0) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (rp->lip_cnt == sf->sf_lip_cnt)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp->next = rp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = rp->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lip_cnt = rp->lip_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(rp, sizeof (struct sf_reset_list));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* abort all cmds for this target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_abort_all(sf, target, FALSE,
193974072f41a843678abf5f61979c748687e66bSherry Moore lip_cnt, TRUE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (lip_cnt == sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &=
193974072f41a843678abf5f61979c748687e66bSherry Moore ~SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp = (struct sf_reset_list *)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf->sf_reset_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rp = sf->sf_reset_list;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel lb = ddi_get_lbolt();
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else if (rp->lip_cnt != sf->sf_lip_cnt) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp->next = rp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(rp, sizeof (struct sf_reset_list));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rp = tp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel reset_timeout_flag = TRUE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tp = rp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rp = rp->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (reset_timeout_flag && (sf_reset_timeout_id == 0)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_reset_timeout_id = timeout(sf_check_reset_delay,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NULL, drv_usectohz(SF_TARGET_RESET_DELAY));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf_global_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called to "reset the bus", i.e. force loop initialization (and address
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * re-negotiation)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_force_lip(struct sf *sf)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* disable restart of lip if we're suspended */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_state & SF_STATE_SUSPENDED) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_CONT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "sf_force_lip, sf%d: lip restart disabled "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "due to DDI_SUSPEND\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_get_instance(sf->sf_dip)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "Forcing lip\n");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_OFFLINE))
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state |= SF_TARGET_BUSY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next_lun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lip_cnt++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state = SF_STATE_OFFLINE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.lip_count++; /* no mutex for this? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* are we allowing LIPs ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_lip_flag != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call the transport to force loop initialization */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (((i = soc_force_lip(sf->sf_sochandle, sf->sf_socp,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_sochandle->fcal_portno, 1,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel FCAL_FORCE_LIP)) != FCAL_SUCCESS) &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (i != FCAL_TIMEOUT)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* force LIP failed */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_core && (sf_core & SF_CORE_LIP_FAILED)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) soc_take_core(sf->sf_sochandle,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_socp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_core = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* are we allowing reset after LIP failed ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_reset_flag != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* restart socal after resetting it */
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_log(sf, CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "!Force lip failed Status code 0x%x."
193974072f41a843678abf5f61979c748687e66bSherry Moore " Reseting\n", i);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* call transport to force a reset */
193974072f41a843678abf5f61979c748687e66bSherry Moore soc_force_reset(sf->sf_sochandle, sf->sf_socp,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_sochandle->fcal_portno, 1);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#ifdef DEBUG
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel#endif
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport when an unsolicited ELS is received
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_unsol_els_callback(void *arg, soc_response_t *srp, caddr_t payload)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = (struct sf *)arg;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel els_payload_t *els = (els_payload_t *)payload;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct la_els_rjt *rsp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i, tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uchar_t dest_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct fcal_packet *fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fc_frame_header_t *hp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_els_hdr *privp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((els == NULL) || ((i = srp->sr_soc_hdr.sh_byte_cnt) == 0)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore return;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (i > SOC_CQE_PAYLOAD) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel i = SOC_CQE_PAYLOAD;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dest_id = (uchar_t)srp->sr_fc_frame_hdr.s_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = sf_alpa_to_switch[dest_id];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (els->els_cmd.c.ls_command) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case LA_ELS_LOGO:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * logout received -- log the fact
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.tstats[tgt_id].logouts_recvd++;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "!LOGO recvd from target %x, %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore tgt_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_lip_on_plogo ? "Forcing LIP...." : "");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_lip_on_plogo) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default: /* includes LA_ELS_PLOGI */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * something besides a logout received -- we don't handle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * this so send back a reject saying its unsupported
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_log(sf, CE_NOTE, "!ELS 0x%x recvd from target 0x%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore els->els_cmd.c.ls_command, tgt_id);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* allocate room for a response */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct la_els_rjt), sizeof (union sf_els_rsp),
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t *)&privp, (caddr_t *)&rsp) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt = privp->fpkt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* fill in pkt header */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->r_ctl = R_CTL_ELS_RSP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->ox_id = srp->sr_fc_frame_hdr.ox_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel hp->rx_id = srp->sr_fc_frame_hdr.rx_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CQ_TYPE_OUTBOUND;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 1;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* fill in response */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->ls_code = LA_ELS_RJT; /* reject this ELS */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->mbz[0] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->mbz[1] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->mbz[2] = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ((struct la_els_logi *)privp->rsp)->ls_code = LA_ELS_ACC;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel *((int *)&rsp->reserved) = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel rsp->reason_code = RJT_UNSUPPORTED;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->retries = sf_els_retries;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->els_code = LA_ELS_RJT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel privp->timeout = (unsigned)0xffffffff;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) sf_els_transport(sf, privp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Error logging, printing, and debug print routines
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*PRINTFLIKE3*/
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_log(struct sf *sf, int level, const char *fmt, ...)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel char buf[256];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel va_list ap;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dip = sf->sf_dip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dip = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel va_start(ap, fmt);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) vsprintf(buf, fmt, ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel va_end(ap);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel scsi_log(dip, "sf", level, buf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called to get some sf kstats -- return 0 on success else return errno
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_kstat_update(kstat_t *ksp, int rw)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (rw == KSTAT_WRITE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* can't write */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (EACCES);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ksp->ks_private;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.ncmds = sf->sf_ncmds;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.throttle_limit = sf->sf_throttle;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_stats.cr_pool_size = sf->sf_cr_pool_cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0); /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * Unix Entry Points
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * driver entry point for opens on control device
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_t dev = *dev_p;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* just ensure soft state exists for this device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ENXIO);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ++(sf->sf_check_n_close);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * driver entry point for last close on control device
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ENXIO);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!sf->sf_check_n_close) { /* if this flag is zero */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cmn_err(CE_WARN, "sf%d: trying to close unopened instance",
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_MINOR2INST(getminor(dev)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ENODEV);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel --(sf->sf_check_n_close);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * driver entry point for sf ioctl commands
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/* ARGSUSED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_ioctl(dev_t dev,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel uchar_t al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_al_map map;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int cnt, i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int retval; /* return value */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct devctl_iocdata *dcp;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel dev_info_t *cdip;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct scsi_address ap;
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth scsi_hba_tran_t *tran;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ENXIO);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* handle all ioctls */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (cmd) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * We can use the generic implementation for these ioctls
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_DEVICE_GETSTATE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_DEVICE_ONLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_DEVICE_OFFLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_BUS_GETSTATE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_devctl_ioctl(sf->sf_dip, cmd, arg, mode, 0));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * return FC map
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SFIOCGMAP:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((sf->sf_lilp_map->lilp_magic != FCAL_LILP_MAGIC &&
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_magic != FCAL_BADLILP_MAGIC) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_state != SF_STATE_ONLINE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENOENT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i, j = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* Need to generate a fake lilp map */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < sf_max_targets; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_targets[i])
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_alpalist[j++] =
193974072f41a843678abf5f61979c748687e66bSherry Moore sf->sf_targets[i]->
193974072f41a843678abf5f61979c748687e66bSherry Moore sft_hard_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_lilp_map->lilp_length = (uchar_t)j;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cnt = sf->sf_lilp_map->lilp_length;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_count = (short)cnt;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&map.sf_hba_addr.sf_node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&map.sf_hba_addr.sf_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_hba_addr.sf_al_pa = sf->sf_al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_hba_addr.sf_hard_address = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_hba_addr.sf_inq_dtype = DTYPE_UNKNOWN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < cnt; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel al_pa = sf->sf_lilp_map->lilp_alpalist[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].sf_al_pa = al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (al_pa == sf->sf_al_pa) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) bcopy((caddr_t)&sf->sf_sochandle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ->fcal_n_wwn, (caddr_t)&map.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_addr_pair[i].sf_node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) bcopy((caddr_t)&sf->sf_sochandle
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ->fcal_p_wwn, (caddr_t)&map.
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_addr_pair[i].sf_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].sf_hard_address =
193974072f41a843678abf5f61979c748687e66bSherry Moore al_pa;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].sf_inq_dtype =
193974072f41a843678abf5f61979c748687e66bSherry Moore DTYPE_PROCESSOR;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel continue;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_targets[sf_alpa_to_switch[
193974072f41a843678abf5f61979c748687e66bSherry Moore al_pa]];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state &
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (SF_TARGET_OFFLINE |
193974072f41a843678abf5f61979c748687e66bSherry Moore SF_TARGET_BUSY))) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&map.sf_addr_pair
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel [i].sf_node_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bcopy((caddr_t)&target->
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sft_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (caddr_t)&map.sf_addr_pair
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel [i].sf_port_wwn,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_hard_address
193974072f41a843678abf5f61979c748687e66bSherry Moore = target->sft_hard_address;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].
193974072f41a843678abf5f61979c748687e66bSherry Moore sf_inq_dtype
193974072f41a843678abf5f61979c748687e66bSherry Moore = target->sft_device_type;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel continue;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)&map.sf_addr_pair[i].
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_node_wwn, sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel bzero((caddr_t)&map.sf_addr_pair[i].
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_port_wwn, sizeof (la_wwn_t));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel map.sf_addr_pair[i].sf_inq_dtype =
193974072f41a843678abf5f61979c748687e66bSherry Moore DTYPE_UNKNOWN;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ddi_copyout((caddr_t)&map, (caddr_t)arg,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sizeof (struct sf_al_map), mode) != 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = EFAULT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * handle device control ioctls
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_DEVICE_RESET:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = EFAULT;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((ndi_dc_getname(dcp) == NULL) ||
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (ndi_dc_getaddr(dcp) == NULL)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ndi_dc_freehdl(dcp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = EINVAL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cdip = ndi_devi_find(sf->sf_dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ndi_dc_freehdl(dcp);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (cdip == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENXIO;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target = sf_get_target_from_dip(sf, cdip)) == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENXIO;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (!(target->sft_state & SF_TARGET_INIT_DONE)) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENXIO;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth /* This is ugly */
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth tran = kmem_zalloc(scsi_hba_tran_size(), KM_SLEEP);
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth bcopy(target->sft_tran, tran, scsi_hba_tran_size());
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth ap.a_hba_tran = tran;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ap.a_target = sf_alpa_to_switch[target->sft_al_pa];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf_reset(&ap, RESET_TARGET) == FALSE) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = EIO;
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth } else {
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth retval = 0;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth kmem_free(tran, scsi_hba_tran_size());
602ca9ea8f9ce0933f0944601cc5d230e91a950dcth goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_BUS_QUIESCE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_BUS_UNQUIESCE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENOTSUP;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_BUS_RESET:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case DEVCTL_BUS_RESETALL:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf_force_lip(sf);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel default:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = ENOTTY;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel goto dun;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel retval = 0; /* success */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8steveldun:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (retval);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * get the target given a DIP
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic struct sf_target *
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_get_target_from_dip(struct sf *sf, dev_info_t *dip)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int i;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* scan each hash queue for the DIP in question */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = sf->sf_wwn_lists[i];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (target != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (target->sft_dip == dip) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (target); /* success: target found */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = target->sft_next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NULL); /* failure: target not found */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to get an event cookie
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t *event_cookiep)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* can't find instance for this device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_event_retrieve_cookie(sf->sf_event_hdl, rdip, name,
193974072f41a843678abf5f61979c748687e66bSherry Moore event_cookiep, NDI_EVENT_NOPASS));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to add an event callback
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t eventid, void (*callback)(dev_info_t *dip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t event, void *arg, void *impl_data), void *arg,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_callback_id_t *cb_id)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* can't find instance for this device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_event_add_callback(sf->sf_event_hdl, rdip,
193974072f41a843678abf5f61979c748687e66bSherry Moore eventid, callback, arg, NDI_SLEEP, cb_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to remove an event callback
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf = ddi_get_soft_state(sf_state, ddi_get_instance(devi));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* can't find instance for this device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (DDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_event_remove_callback(sf->sf_event_hdl, cb_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * called by the transport to post an event
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic int
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t eventid, void *impldata)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel ddi_eventcookie_t remove_cookie, cookie;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* is this a remove event ?? */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel remove_cookie = ndi_event_tag_to_cookie(sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_EVENT_TAG_REMOVE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (remove_cookie == eventid) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* handle remove event */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf == NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* no sf instance for this device */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* get the target for this event */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if ((target = sf_get_target_from_dip(sf, rdip)) != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * clear device info for this target and mark as
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * not done
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_dip = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_state &= ~SF_TARGET_INIT_DONE;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&target->sft_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NDI_SUCCESS); /* event handled */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* no target for this event */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* an insertion event */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_busop_get_eventcookie(dip, rdip, FCAL_INSERT_EVENT, &cookie)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel != NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (NDI_FAILURE);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel return (ndi_post_event(dip, rdip, cookie, impldata));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel/*
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel * the sf hotplug daemon, one thread per sf instance
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelstatic void
3d19cdae966d9ac4218dd9859640463bd7da19d8stevelsf_hp_daemon(void *arg)
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel{
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf *sf = (struct sf *)arg;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_hp_elem *elem;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel struct sf_target *target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel int tgt_id;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel callb_cpr_t cprinfo;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CALLB_CPR_INIT(&cprinfo, &sf->sf_hp_daemon_mutex,
193974072f41a843678abf5f61979c748687e66bSherry Moore callb_generic_cpr, "sf_hp_daemon");
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel do {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel while (sf->sf_hp_elem_head != NULL) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* save ptr to head of list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel elem = sf->sf_hp_elem_head;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* take element off of list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_hp_elem_head == sf->sf_hp_elem_tail) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* element only one in list -- list now empty */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_head = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_tail = NULL;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* remove element from head of list */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_hp_elem_head = sf->sf_hp_elem_head->next;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_exit(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel switch (elem->what) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SF_ONLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* online this target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = elem->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_devi_online(elem->dip, 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_retrieve_cookie(
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_dip, FCAL_INSERT_EVENT,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel &sf_insert_eid, NDI_EVENT_NOPASS);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel (void) ndi_event_run_callbacks(sf->sf_event_hdl,
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target->sft_dip, sf_insert_eid, NULL);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel case SF_OFFLINE:
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* offline this target */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel target = elem->target;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id = sf_alpa_to_switch[target->sft_al_pa];
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* don't do NDI_DEVI_REMOVE for now */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (ndi_devi_offline(elem->dip, 0) !=
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel NDI_SUCCESS) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_WARN, "target %x, "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "device offline failed", tgt_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } else {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel SF_DEBUG(1, (sf, CE_NOTE, "target %x, "
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel "device offline succeeded\n",
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel tgt_id));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel break;
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel kmem_free(elem, sizeof (struct sf_hp_elem));
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel mutex_enter(&sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* if exit is not already signaled */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel if (sf->sf_hp_exit == 0) {
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* wait to be signaled by work or exit */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CALLB_CPR_SAFE_BEGIN(&cprinfo);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel cv_wait(&sf->sf_hp_daemon_cv, &sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CALLB_CPR_SAFE_END(&cprinfo, &sf->sf_hp_daemon_mutex);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel }
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel } while (sf->sf_hp_exit == 0);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* sf_hp_daemon_mutex is dropped by CALLB_CPR_EXIT */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel CALLB_CPR_EXIT(&cprinfo);
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel thread_exit(); /* no more hotplug thread */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel /* NOTREACHED */
3d19cdae966d9ac4218dd9859640463bd7da19d8stevel}