Date: Fri, 30 Mar 2018 15:28:25 +0000 (UTC) From: "Kenneth D. Merry" <ken@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r331766 - in head: share/man/man4 sys/amd64/conf sys/conf sys/dev/ocs_fc sys/modules sys/modules/ocs_fc Message-ID: <201803301528.w2UFSPpm080924@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ken Date: Fri Mar 30 15:28:25 2018 New Revision: 331766 URL: https://svnweb.freebsd.org/changeset/base/331766 Log: Bring in the Broadcom/Emulex Fibre Channel driver, ocs_fc(4). The ocs_fc(4) driver supports the following hardware: Emulex 16/8G FC GEN 5 HBAS LPe15004 FC Host Bus Adapters LPe160XX FC Host Bus Adapters Emulex 32/16G FC GEN 6 HBAS LPe3100X FC Host Bus Adapters LPe3200X FC Host Bus Adapters The driver supports target and initiator mode, and also supports FC-Tape. Note that the driver only currently works on little endian platforms. It is only included in the module build for amd64 and i386, and in GENERIC on amd64 only. Submitted by: Ram Kishore Vegesna <ram.vegesna@broadcom.com> Reviewed by: mav MFC after: 5 days Relnotes: yes Sponsored by: Broadcom Differential Revision: https://reviews.freebsd.org/D11423 Added: head/share/man/man4/ocs_fc.4 (contents, props changed) head/sys/dev/ocs_fc/ head/sys/dev/ocs_fc/ocs.h (contents, props changed) head/sys/dev/ocs_fc/ocs_cam.c (contents, props changed) head/sys/dev/ocs_fc/ocs_cam.h (contents, props changed) head/sys/dev/ocs_fc/ocs_common.h (contents, props changed) head/sys/dev/ocs_fc/ocs_ddump.c (contents, props changed) head/sys/dev/ocs_fc/ocs_ddump.h (contents, props changed) head/sys/dev/ocs_fc/ocs_device.c (contents, props changed) head/sys/dev/ocs_fc/ocs_device.h (contents, props changed) head/sys/dev/ocs_fc/ocs_domain.c (contents, props changed) head/sys/dev/ocs_fc/ocs_domain.h (contents, props changed) head/sys/dev/ocs_fc/ocs_drv_fc.h (contents, props changed) head/sys/dev/ocs_fc/ocs_els.c (contents, props changed) head/sys/dev/ocs_fc/ocs_els.h (contents, props changed) head/sys/dev/ocs_fc/ocs_fabric.c (contents, props changed) head/sys/dev/ocs_fc/ocs_fabric.h (contents, props changed) head/sys/dev/ocs_fc/ocs_fcp.h (contents, props changed) head/sys/dev/ocs_fc/ocs_hw.c (contents, props changed) head/sys/dev/ocs_fc/ocs_hw.h (contents, props changed) head/sys/dev/ocs_fc/ocs_hw_queues.c (contents, props changed) head/sys/dev/ocs_fc/ocs_hw_queues.h (contents, props changed) head/sys/dev/ocs_fc/ocs_io.c (contents, props changed) head/sys/dev/ocs_fc/ocs_io.h (contents, props changed) head/sys/dev/ocs_fc/ocs_ioctl.c (contents, props changed) head/sys/dev/ocs_fc/ocs_ioctl.h (contents, props changed) head/sys/dev/ocs_fc/ocs_list.h (contents, props changed) head/sys/dev/ocs_fc/ocs_mgmt.c (contents, props changed) head/sys/dev/ocs_fc/ocs_mgmt.h (contents, props changed) head/sys/dev/ocs_fc/ocs_node.c (contents, props changed) head/sys/dev/ocs_fc/ocs_node.h (contents, props changed) head/sys/dev/ocs_fc/ocs_os.c (contents, props changed) head/sys/dev/ocs_fc/ocs_os.h (contents, props changed) head/sys/dev/ocs_fc/ocs_pci.c (contents, props changed) head/sys/dev/ocs_fc/ocs_scsi.c (contents, props changed) head/sys/dev/ocs_fc/ocs_scsi.h (contents, props changed) head/sys/dev/ocs_fc/ocs_sm.c (contents, props changed) head/sys/dev/ocs_fc/ocs_sm.h (contents, props changed) head/sys/dev/ocs_fc/ocs_sport.c (contents, props changed) head/sys/dev/ocs_fc/ocs_sport.h (contents, props changed) head/sys/dev/ocs_fc/ocs_stats.h (contents, props changed) head/sys/dev/ocs_fc/ocs_unsol.c (contents, props changed) head/sys/dev/ocs_fc/ocs_unsol.h (contents, props changed) head/sys/dev/ocs_fc/ocs_utils.c (contents, props changed) head/sys/dev/ocs_fc/ocs_utils.h (contents, props changed) head/sys/dev/ocs_fc/ocs_vpd.h (contents, props changed) head/sys/dev/ocs_fc/ocs_xport.c (contents, props changed) head/sys/dev/ocs_fc/ocs_xport.h (contents, props changed) head/sys/dev/ocs_fc/sli4.c (contents, props changed) head/sys/dev/ocs_fc/sli4.h (contents, props changed) head/sys/dev/ocs_fc/version.h (contents, props changed) head/sys/modules/ocs_fc/ head/sys/modules/ocs_fc/Makefile (contents, props changed) Modified: head/share/man/man4/Makefile head/sys/amd64/conf/GENERIC head/sys/conf/files head/sys/modules/Makefile Modified: head/share/man/man4/Makefile ============================================================================== --- head/share/man/man4/Makefile Fri Mar 30 14:41:16 2018 (r331765) +++ head/share/man/man4/Makefile Fri Mar 30 15:28:25 2018 (r331766) @@ -402,6 +402,7 @@ MAN= aac.4 \ ${_nvram2env.4} \ ${_nxge.4} \ oce.4 \ + ocs_fc.4\ ohci.4 \ orm.4 \ ow.4 \ Added: head/share/man/man4/ocs_fc.4 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/man/man4/ocs_fc.4 Fri Mar 30 15:28:25 2018 (r331766) @@ -0,0 +1,194 @@ +.\" Copyright (c) 2017 Broadcom. All rights reserved. +.\" The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright notice, +.\" this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright notice, +.\" this list of conditions and the following disclaimer in the documentation +.\" and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the copyright holder nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 30, 2018 +.Dt OCS_FC 4 +.Os +.Sh NAME +.Nm ocs_fc +.Nd "Device driver for Emulex Fibre Channel Host Adapters" +.Sh SYNOPSIS +To compile this driver into the kernel, add this line to the +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device ocs_fc" +.Ed +.Pp +To load the driver as a module at boot, add this line to +.Xr loader.conf 5 : +.Bd -literal -offset indent +ocs_fc_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides access to Fibre Channel SCSI devices. +.Pp +The +.Nm +driver supports initiator and target modes. +Support is available for Arbitrated loops, Point-to-Point, +and Fabric connections. +FC-Tape is highly recommended for connections to tape drives that support +it. +FC-Tape includes four elements from the T-10 FCP-4 specification: +.Bl -bullet -offset indent +.It +Precise Delivery of Commands +.It +Confirmed Completion of FCP I/O Operations +.It +Retransmission of Unsuccessfully Transmitted IUs +.It +Task Retry Identification +.El +.Pp +Together these features allow for link level error recovery with tape +devices. +Without link level error recovery, an initiator cannot, for instance, tell whether a tape write +command that has timed out resulted in all, part, or none of the data going to +the tape drive. +FC-Tape is automatically enabled when both the controller and target support it. + +.Sh HARDWARE +The +.Nm +driver supports these Fibre Channel adapters: +.Bl -tag -width xxxxxx -offset indent +.It Emulex 16/8G FC GEN 5 HBAS +.Bd -literal -offset indent +LPe15004 FC Host Bus Adapters +LPe160XX FC Host Bus Adapters +.Ed +.It Emulex 32/16G FC GEN 6 HBAS +.Bd -literal -offset indent +LPe3100X FC Host Bus Adapters +LPe3200X FC Host Bus Adapters +.Ed +.El +.Sh UPDATING FIRMWARE +Adapter firmware updates are persistent. +.Pp +Firmware can be updated by following these steps: +.Bl -enum +.It +Copy this code to a +.Pa Makefile : +.Bd -literal -offset indent +KMOD=ocsflash +FIRMWS=imagename.grp:ocsflash +\&.include <bsd.kmod.mk> +.Ed +.It +Replace +.Pa imagename +with the name of the GRP file. +.It +Copy the +.Pa Makefile +and GRP file to a local directory +.It +Execute +.Cm make +and copy the generated +.Pa ocsflash.ko +file to +.Pa /lib/modules +.It +.Cm sysctl dev.ocs_fc.<N>.fw_upgrade=ocsflash +.It +Check kernel messages regarding status of the operation +.It +Reboot the machine +.El +.Pp +.Sh BOOT OPTIONS +Options are controlled by setting values in +.Pa /boot/device.hints . +.Pp +They are: +.Bl -tag -width indent +.It Va hint.ocs_fc.N.initiator +Enable initiator functionality. +Default 1 (enabled), 0 to disable. +.It Va hint.ocs_fc.N.target +Enable target functionality. +Default 1 (enabled), 0 to disable. +.It Va hint.ocs_fc.N.topology +Topology: 0 for Auto, 1 for NPort only, 2 for Loop only. +.It Va hint.ocs_fc.N.speed +Link speed in megabits per second. +Possible values include: +0 Auto-speed negotiation (default), 4000 (4GFC), 8000 (8GFC), 16000 (16GFC). +.El +.Sh SYSCTL OPTIONS +.Bl -tag -width indent +.It Va dev.ocs_fc.N.port_state +Port state (read/write). +Valid values are +.Li online +and +.Li offline . +.It Va dev.ocs_fc.N.wwpn +World Wide Port Name (read/write). +.It Va dev.ocs_fc.N.wwnn +World Wide Node Name (read/write). +.It Va dev.ocs_fc.N.fwrev +Firmware revision (read-only). +.It Va dev.ocs_fc.N.sn +Adapter serial number (read-only). +.It Va dev.ocs_fc.N.configured_speed +Configured Port Speed (read/write). +Valid values are: +0 Auto-speed negotiation (default), 4000 (4GFC), 8000 (8GFC), 16000 (16GFC). +.It Va dev.ocs_fc.N.configured_topology +Configured Port Topology (read/write). +Valid values are: +0-Auto; 1-NPort; 2-Loop. +.It Va dev.ocs_fc.N.current_speed +Current Port Speed (read-only). +.It Va dev.ocs_fc.N.current_topology +Current Port Topology (read-only). +.El +.Sh SUPPORT +For general information and support, +go to the Broadcom website at: +.Pa http://www.broadcom.com/ +or E-Mail at +.Pa ocs-driver-team.pdl@broadcom.com. +.Sh SEE ALSO +.Xr ifconfig 8 +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Broadcom. Modified: head/sys/amd64/conf/GENERIC ============================================================================== --- head/sys/amd64/conf/GENERIC Fri Mar 30 14:41:16 2018 (r331765) +++ head/sys/amd64/conf/GENERIC Fri Mar 30 15:28:25 2018 (r331766) @@ -141,6 +141,7 @@ device adw # Advansys wide SCSI adapters device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60. device bt # Buslogic/Mylex MultiMaster SCSI adapters device isci # Intel C600 SAS controller +device ocs_fc # Emulex FC adapters # ATA/SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Fri Mar 30 14:41:16 2018 (r331765) +++ head/sys/conf/files Fri Mar 30 15:28:25 2018 (r331766) @@ -2578,6 +2578,27 @@ dev/oce/oce_mbox.c optional oce pci dev/oce/oce_queue.c optional oce pci dev/oce/oce_sysctl.c optional oce pci dev/oce/oce_util.c optional oce pci +dev/ocs_fc/ocs_pci.c optional ocs_fc pci +dev/ocs_fc/ocs_ioctl.c optional ocs_fc pci +dev/ocs_fc/ocs_os.c optional ocs_fc pci +dev/ocs_fc/ocs_utils.c optional ocs_fc pci +dev/ocs_fc/ocs_hw.c optional ocs_fc pci +dev/ocs_fc/ocs_hw_queues.c optional ocs_fc pci +dev/ocs_fc/sli4.c optional ocs_fc pci +dev/ocs_fc/ocs_sm.c optional ocs_fc pci +dev/ocs_fc/ocs_device.c optional ocs_fc pci +dev/ocs_fc/ocs_xport.c optional ocs_fc pci +dev/ocs_fc/ocs_domain.c optional ocs_fc pci +dev/ocs_fc/ocs_sport.c optional ocs_fc pci +dev/ocs_fc/ocs_els.c optional ocs_fc pci +dev/ocs_fc/ocs_fabric.c optional ocs_fc pci +dev/ocs_fc/ocs_io.c optional ocs_fc pci +dev/ocs_fc/ocs_node.c optional ocs_fc pci +dev/ocs_fc/ocs_scsi.c optional ocs_fc pci +dev/ocs_fc/ocs_unsol.c optional ocs_fc pci +dev/ocs_fc/ocs_ddump.c optional ocs_fc pci +dev/ocs_fc/ocs_mgmt.c optional ocs_fc pci +dev/ocs_fc/ocs_cam.c optional ocs_fc pci dev/ofw/ofw_bus_if.m optional fdt dev/ofw/ofw_bus_subr.c optional fdt dev/ofw/ofw_cpu.c optional fdt Added: head/sys/dev/ocs_fc/ocs.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/ocs_fc/ocs.h Fri Mar 30 15:28:25 2018 (r331766) @@ -0,0 +1,261 @@ +/*- + * Copyright (c) 2017 Broadcom. All rights reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/** + * @file + * OCS bsd driver common include file + */ + + +#if !defined(__OCS_H__) +#define __OCS_H__ + +#include "ocs_os.h" +#include "ocs_utils.h" + +#include "ocs_hw.h" +#include "ocs_scsi.h" +#include "ocs_io.h" + +#include "version.h" + +#define DRV_NAME "ocs_fc" +#define DRV_VERSION \ + STR_BE_MAJOR "." STR_BE_MINOR "." STR_BE_BUILD "." STR_BE_BRANCH + +/** + * @brief Interrupt context + */ +typedef struct ocs_intr_ctx_s { + uint32_t vec; /** Zero based interrupt vector */ + void *softc; /** software context for interrupt */ + char name[64]; /** label for this context */ +} ocs_intr_ctx_t; + +typedef struct ocs_fcport_s { + struct cam_sim *sim; + struct cam_path *path; + uint32_t role; + + ocs_tgt_resource_t targ_rsrc_wildcard; + ocs_tgt_resource_t targ_rsrc[OCS_MAX_LUN]; + ocs_vport_spec_t *vport; +} ocs_fcport; + +#define FCPORT(ocs, chan) (&((ocs_fcport *)(ocs)->fcports)[(chan)]) + +/** + * @brief Driver's context + */ + +struct ocs_softc { + + device_t dev; + struct cdev *cdev; + + ocs_pci_reg_t reg[PCI_MAX_BAR]; + + uint32_t instance_index; + const char *desc; + + uint32_t irqid; + struct resource *irq; + void *tag; + + ocs_intr_ctx_t intr_ctx; + uint32_t n_vec; + + bus_dma_tag_t dmat; /** Parent DMA tag */ + bus_dma_tag_t buf_dmat;/** IO buffer DMA tag */ + char display_name[OCS_DISPLAY_NAME_LENGTH]; + uint16_t pci_vendor; + uint16_t pci_device; + uint16_t pci_subsystem_vendor; + uint16_t pci_subsystem_device; + char businfo[16]; + const char *driver_version; + const char *fw_version; + const char *model; + + ocs_hw_t hw; + + ocs_rlock_t lock; /**< device wide lock */ + + ocs_xport_e ocs_xport; + ocs_xport_t *xport; /**< pointer to transport object */ + ocs_domain_t *domain; + ocs_list_t domain_list; + uint32_t domain_instance_count; + void (*domain_list_empty_cb)(ocs_t *ocs, void *arg); + void *domain_list_empty_cb_arg; + + uint8_t enable_ini; + uint8_t enable_tgt; + uint8_t fc_type; + int ctrlmask; + uint8_t explicit_buffer_list; + uint8_t external_loopback; + uint8_t skip_hw_teardown; + int speed; + int topology; + int ethernet_license; + int num_scsi_ios; + uint8_t enable_hlm; + uint32_t hlm_group_size; + uint32_t max_isr_time_msec; /*>> Maximum ISR time */ + uint32_t auto_xfer_rdy_size; /*>> Max sized write to use auto xfer rdy*/ + uint8_t esoc; + int logmask; + char *hw_war_version; + uint32_t num_vports; + uint32_t target_io_timer_sec; + uint32_t hw_bounce; + uint8_t rq_threads; + uint8_t rq_selection_policy; + uint8_t rr_quanta; + char *filter_def; + uint32_t max_remote_nodes; + + /* + * tgt_rscn_delay - delay in kicking off RSCN processing + * (nameserver queries) after receiving an RSCN on the target. + * This prevents thrashing of nameserver requests due to a huge burst of + * RSCNs received in a short period of time. + * Note: this is only valid when target RSCN handling is enabled -- see + * ctrlmask. + */ + time_t tgt_rscn_delay_msec; /*>> minimum target RSCN delay */ + + /* + * tgt_rscn_period - determines maximum frequency when processing + * back-to-back RSCNs; e.g. if this value is 30, there will never be + * any more than 1 RSCN handling per 30s window. This prevents + * initiators on a faulty link generating many RSCN from causing the + * target to continually query the nameserver. + * Note: This is only valid when target RSCN handling is enabled + */ + time_t tgt_rscn_period_msec; /*>> minimum target RSCN period */ + + uint32_t enable_task_set_full; + uint32_t io_in_use; + uint32_t io_high_watermark; /**< used to send task set full */ + struct mtx sim_lock; + uint32_t config_tgt:1, /**< Configured to support target mode */ + config_ini:1; /**< Configured to support initiator mode */ + + + uint32_t nodedb_mask; /**< Node debugging mask */ + + char modeldesc[64]; + char serialnum[64]; + char fwrev[64]; + char sli_intf[9]; + + ocs_ramlog_t *ramlog; + ocs_textbuf_t ddump_saved; + + ocs_mgmt_functions_t *mgmt_functions; + ocs_mgmt_functions_t *tgt_mgmt_functions; + ocs_mgmt_functions_t *ini_mgmt_functions; + + ocs_err_injection_e err_injection; + uint32_t cmd_err_inject; + time_t delay_value_msec; + + bool attached; + struct mtx dbg_lock; + + struct cam_devq *devq; + ocs_fcport *fcports; + + void* tgt_ocs; +}; + +static inline void +ocs_device_lock_init(ocs_t *ocs) +{ + ocs_rlock_init(ocs, &ocs->lock, "ocsdevicelock"); +} + +static inline int32_t +ocs_device_lock_try(ocs_t *ocs) +{ + return ocs_rlock_try(&ocs->lock); +} + +static inline void +ocs_device_lock(ocs_t *ocs) +{ + ocs_rlock_acquire(&ocs->lock); +} + +static inline void +ocs_device_unlock(ocs_t *ocs) +{ + ocs_rlock_release(&ocs->lock); +} + +static inline void +ocs_device_lock_free(ocs_t *ocs) +{ + ocs_rlock_free(&ocs->lock); +} + +extern int32_t ocs_device_detach(ocs_t *ocs); + +extern int32_t ocs_device_attach(ocs_t *ocs); + +#define ocs_is_initiator_enabled() (ocs->enable_ini) +#define ocs_is_target_enabled() (ocs->enable_tgt) + +#include "ocs_xport.h" +#include "ocs_domain.h" +#include "ocs_sport.h" +#include "ocs_node.h" +#include "ocs_unsol.h" +#include "ocs_scsi.h" +#include "ocs_ioctl.h" + +static inline ocs_io_t * +ocs_io_alloc(ocs_t *ocs) +{ + return ocs_io_pool_io_alloc(ocs->xport->io_pool); +} + +static inline void +ocs_io_free(ocs_t *ocs, ocs_io_t *io) +{ + ocs_io_pool_io_free(ocs->xport->io_pool, io); +} + +#endif /* __OCS_H__ */ Added: head/sys/dev/ocs_fc/ocs_cam.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/ocs_fc/ocs_cam.c Fri Mar 30 15:28:25 2018 (r331766) @@ -0,0 +1,2640 @@ +/*- + * Copyright (c) 2017 Broadcom. All rights reserved. + * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/** + * @defgroup scsi_api_target SCSI Target API + * @defgroup scsi_api_initiator SCSI Initiator API + * @defgroup cam_api Common Access Method (CAM) API + * @defgroup cam_io CAM IO + */ + +/** + * @file + * Provides CAM functionality. + */ + +#include "ocs.h" +#include "ocs_scsi.h" +#include "ocs_device.h" + +/* Default IO timeout value for initiators is 30 seconds */ +#define OCS_CAM_IO_TIMEOUT 30 + +typedef struct { + ocs_scsi_sgl_t *sgl; + uint32_t sgl_max; + uint32_t sgl_count; + int32_t rc; +} ocs_dmamap_load_arg_t; + +static void ocs_action(struct cam_sim *, union ccb *); +static void ocs_poll(struct cam_sim *); + +static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *, + struct ccb_hdr *, uint32_t *); +static int32_t ocs_tgt_resource_abort(struct ocs_softc *, ocs_tgt_resource_t *); +static uint32_t ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb); +static void ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb); +static void ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb); +static int32_t ocs_target_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); +static int32_t ocs_io_abort_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); +static int32_t ocs_task_set_full_or_busy(ocs_io_t *io); +static int32_t ocs_initiator_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, + ocs_scsi_cmd_resp_t *, uint32_t, void *); +static uint32_t +ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role); + +static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag) +{ + + return ocs_io_get_instance(ocs, tag); +} + +static inline void ocs_target_io_free(ocs_io_t *io) +{ + io->tgt_io.state = OCS_CAM_IO_FREE; + io->tgt_io.flags = 0; + io->tgt_io.app = NULL; + ocs_scsi_io_complete(io); + if(io->ocs->io_in_use != 0) + atomic_subtract_acq_32(&io->ocs->io_in_use, 1); +} + +static int32_t +ocs_attach_port(ocs_t *ocs, int chan) +{ + + struct cam_sim *sim = NULL; + struct cam_path *path = NULL; + uint32_t max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS); + ocs_fcport *fcp = FCPORT(ocs, chan); + + if (NULL == (sim = cam_sim_alloc(ocs_action, ocs_poll, + device_get_name(ocs->dev), ocs, + device_get_unit(ocs->dev), &ocs->sim_lock, + max_io, max_io, ocs->devq))) { + device_printf(ocs->dev, "Can't allocate SIM\n"); + return 1; + } + + mtx_lock(&ocs->sim_lock); + if (CAM_SUCCESS != xpt_bus_register(sim, ocs->dev, chan)) { + device_printf(ocs->dev, "Can't register bus %d\n", 0); + mtx_unlock(&ocs->sim_lock); + cam_sim_free(sim, FALSE); + return 1; + } + mtx_unlock(&ocs->sim_lock); + + if (CAM_REQ_CMP != xpt_create_path(&path, NULL, cam_sim_path(sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)) { + device_printf(ocs->dev, "Can't create path\n"); + xpt_bus_deregister(cam_sim_path(sim)); + mtx_unlock(&ocs->sim_lock); + cam_sim_free(sim, FALSE); + return 1; + } + + fcp->sim = sim; + fcp->path = path; + + return 0; + +} + +static int32_t +ocs_detach_port(ocs_t *ocs, int32_t chan) +{ + ocs_fcport *fcp = NULL; + struct cam_sim *sim = NULL; + struct cam_path *path = NULL; + fcp = FCPORT(ocs, chan); + + sim = fcp->sim; + path = fcp->path; + + if (fcp->sim) { + mtx_lock(&ocs->sim_lock); + ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard); + if (path) { + xpt_async(AC_LOST_DEVICE, path, NULL); + xpt_free_path(path); + fcp->path = NULL; + } + xpt_bus_deregister(cam_sim_path(sim)); + + cam_sim_free(sim, FALSE); + fcp->sim = NULL; + mtx_unlock(&ocs->sim_lock); + } + + return 0; +} + +int32_t +ocs_cam_attach(ocs_t *ocs) +{ + struct cam_devq *devq = NULL; + int i = 0; + uint32_t max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS); + + if (NULL == (devq = cam_simq_alloc(max_io))) { + device_printf(ocs->dev, "Can't allocate SIMQ\n"); + return -1; + } + + ocs->devq = devq; + + if (mtx_initialized(&ocs->sim_lock) == 0) { + mtx_init(&ocs->sim_lock, "ocs_sim_lock", NULL, MTX_DEF); + } + + for (i = 0; i < (ocs->num_vports + 1); i++) { + if (ocs_attach_port(ocs, i)) { + ocs_log_err(ocs, "Attach port failed for chan: %d\n", i); + goto detach_port; + } + } + + ocs->io_high_watermark = max_io; + ocs->io_in_use = 0; + return 0; + +detach_port: + while (--i >= 0) { + ocs_detach_port(ocs, i); + } + + cam_simq_free(ocs->devq); + + if (mtx_initialized(&ocs->sim_lock)) + mtx_destroy(&ocs->sim_lock); + + return 1; +} + +int32_t +ocs_cam_detach(ocs_t *ocs) +{ + int i = 0; + + for (i = (ocs->num_vports); i >= 0; i--) { + ocs_detach_port(ocs, i); + } + + cam_simq_free(ocs->devq); + + if (mtx_initialized(&ocs->sim_lock)) + mtx_destroy(&ocs->sim_lock); + + return 0; +} + +/*************************************************************************** + * Functions required by SCSI base driver API + */ + +/** + * @ingroup scsi_api_target + * @brief Attach driver to the BSD SCSI layer (a.k.a CAM) + * + * Allocates + initializes CAM related resources and attaches to the CAM + * + * @param ocs the driver instance's software context + * + * @return 0 on success, non-zero otherwise + */ +int32_t +ocs_scsi_tgt_new_device(ocs_t *ocs) +{ + ocs->enable_task_set_full = ocs_scsi_get_property(ocs, + OCS_SCSI_ENABLE_TASK_SET_FULL); + ocs_log_debug(ocs, "task set full processing is %s\n", + ocs->enable_task_set_full ? "enabled" : "disabled"); + + return 0; +} + +/** + * @ingroup scsi_api_target + * @brief Tears down target members of ocs structure. + * + * Called by OS code when device is removed. + * + * @param ocs pointer to ocs + * + * @return returns 0 for success, a negative error code value for failure. + */ +int32_t +ocs_scsi_tgt_del_device(ocs_t *ocs) +{ + + return 0; +} + +/** + * @ingroup scsi_api_target + * @brief accept new domain notification + * + * Called by base drive when new domain is discovered. A target-server + * will use this call to prepare for new remote node notifications + * arising from ocs_scsi_new_initiator(). + * + * The domain context has an element <b>ocs_scsi_tgt_domain_t tgt_domain</b> + * which is declared by the target-server code and is used for target-server + * private data. + * + * This function will only be called if the base-driver has been enabled for + * target capability. + * + * Note that this call is made to target-server backends, + * the ocs_scsi_ini_new_domain() function is called to initiator-client backends. + * + * @param domain pointer to domain + * + * @return returns 0 for success, a negative error code value for failure. + */ +int32_t +ocs_scsi_tgt_new_domain(ocs_domain_t *domain) +{ + return 0; +} + +/** + * @ingroup scsi_api_target + * @brief accept domain lost notification + * + * Called by base-driver when a domain goes away. A target-server will + * use this call to clean up all domain scoped resources. + * + * Note that this call is made to target-server backends, + * the ocs_scsi_ini_del_domain() function is called to initiator-client backends. + * + * @param domain pointer to domain + * + * @return returns 0 for success, a negative error code value for failure. + */ +void +ocs_scsi_tgt_del_domain(ocs_domain_t *domain) +{ +} + + +/** + * @ingroup scsi_api_target + * @brief accept new sli port (sport) notification + * + * Called by base drive when new sport is discovered. A target-server + * will use this call to prepare for new remote node notifications + * arising from ocs_scsi_new_initiator(). + * + * The domain context has an element <b>ocs_scsi_tgt_sport_t tgt_sport</b> + * which is declared by the target-server code and is used for + * target-server private data. + * + * This function will only be called if the base-driver has been enabled for + * target capability. + * + * Note that this call is made to target-server backends, + * the ocs_scsi_tgt_new_domain() is called to initiator-client backends. + * + * @param sport pointer to SLI port + * + * @return returns 0 for success, a negative error code value for failure. + */ +int32_t +ocs_scsi_tgt_new_sport(ocs_sport_t *sport) +{ + ocs_t *ocs = sport->ocs; + + if(!sport->is_vport) { + sport->tgt_data = FCPORT(ocs, 0); + } + + return 0; +} + +/** + * @ingroup scsi_api_target + * @brief accept SLI port gone notification + * + * Called by base-driver when a sport goes away. A target-server will + * use this call to clean up all sport scoped resources. + * + * Note that this call is made to target-server backends, + * the ocs_scsi_ini_del_sport() is called to initiator-client backends. + * + * @param sport pointer to SLI port + * + * @return returns 0 for success, a negative error code value for failure. + */ +void +ocs_scsi_tgt_del_sport(ocs_sport_t *sport) +{ + return; +} + +/** + * @ingroup scsi_api_target + * @brief receive notification of a new SCSI initiator node + * + * Sent by base driver to notify a target-server of the presense of a new + * remote initiator. The target-server may use this call to prepare for + * inbound IO from this node. + * + * The ocs_node_t structure has and elment of type ocs_scsi_tgt_node_t named + * tgt_node that is declared and used by a target-server for private + * information. + * + * This function is only called if the target capability is enabled in driver. + * + * @param node pointer to new remote initiator node + * + * @return returns 0 for success, a negative error code value for failure. + * + * @note + */ +int32_t +ocs_scsi_new_initiator(ocs_node_t *node) +{ + ocs_t *ocs = node->ocs; + struct ac_contract ac; + struct ac_device_changed *adc; + + ocs_fcport *fcp = NULL; + + fcp = node->sport->tgt_data; + if (fcp == NULL) { + ocs_log_err(ocs, "FCP is NULL \n"); + return 1; + } + + /* + * Update the IO watermark by decrementing it by the + * number of IOs reserved for each initiator. + */ + atomic_subtract_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO); + + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = ocs_node_get_wwpn(node); + adc->port = node->rnode.fc_id; + adc->target = node->instance_index; + adc->arrived = 1; + xpt_async(AC_CONTRACT, fcp->path, &ac); + + return 0; +} + +/** + * @ingroup scsi_api_target + * @brief validate new initiator + * + * Sent by base driver to validate a remote initiatiator. The target-server + * returns TRUE if this initiator should be accepted. + * + * This function is only called if the target capability is enabled in driver. + * + * @param node pointer to remote initiator node to validate + * + * @return TRUE if initiator should be accepted, FALSE if it should be rejected + * + * @note + */ + +int32_t +ocs_scsi_validate_initiator(ocs_node_t *node) +{ + return 1; +} + +/** + * @ingroup scsi_api_target + * @brief Delete a SCSI initiator node + * + * Sent by base driver to notify a target-server that a remote initiator + * is now gone. The base driver will have terminated all outstanding IOs + * and the target-server will receive appropriate completions. + * + * This function is only called if the base driver is enabled for + * target capability. + * + * @param node pointer node being deleted + * @param reason Reason why initiator is gone. + * + * @return OCS_SCSI_CALL_COMPLETE to indicate that all work was completed + * + * @note + */ +int32_t +ocs_scsi_del_initiator(ocs_node_t *node, ocs_scsi_del_initiator_reason_e reason) +{ + ocs_t *ocs = node->ocs; + + struct ac_contract ac; + struct ac_device_changed *adc; + ocs_fcport *fcp = NULL; + + fcp = node->sport->tgt_data; + if (fcp == NULL) { + ocs_log_err(ocs, "FCP is NULL \n"); + return 1; + } + + ac.contract_number = AC_CONTRACT_DEV_CHG; + adc = (struct ac_device_changed *) ac.contract_data; + adc->wwpn = ocs_node_get_wwpn(node); + adc->port = node->rnode.fc_id; + adc->target = node->instance_index; + adc->arrived = 0; + xpt_async(AC_CONTRACT, fcp->path, &ac); + + + if (reason == OCS_SCSI_INITIATOR_MISSING) { + return OCS_SCSI_CALL_COMPLETE; + } + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803301528.w2UFSPpm080924>