fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
09409df0fea2444decd38bc1b87ab7a80d3251e5Jeff Biseda * Copyright (c) 2013 by Delphix. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/conf.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/file.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/ddi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/sunddi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/modctl.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/scsi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/impl/scsi_reset_notify.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/generic/mode.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/disp.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/byteorder.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/atomic.h>
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto#include <sys/sdt.h>
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto#include <sys/dkio.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/stmf.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/lpif.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/portif.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/stmf_ioctl.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/stmf_sbd_ioctl.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include "stmf_sbd.h"
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include "sbd_impl.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto#define SCSI2_CONFLICT_FREE_CMDS(cdb) ( \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Refer Both */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SPC-2 (rev 20) Table 10 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SPC-3 (rev 23) Table 31 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_INQUIRY) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_LOG_SENSE_G1) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_RELEASE) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_RELEASE_G1) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_REPORT_LUNS) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_REQUEST_SENSE) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0))) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[0]) == SCMD_SVC_ACTION_IN_G5) && ( \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[1]) & 0x1F) == 0x01)) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* REPORT DEVICE IDENTIFIER (0x05) REPORT PRIORITY (0x0Eh) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[0]) == SCMD_MAINTENANCE_IN) && ( \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[1]) & 0x1F) == 0x0B) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[1]) & 0x1F) == 0x05) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[1]) & 0x1F) == 0x0E) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[1]) & 0x1F) == 0x0A) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[1]) & 0x1F) == 0x0F))) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* SBC-3 (rev 17) Table 3 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* ----------------------- */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* READ CAPACITY(10) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[0]) == SCMD_READ_CAPACITY) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* READ CAPACITY(16) */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[0]) == SCMD_SVC_ACTION_IN_G4) && ( \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb[1]) & 0x1F) == 0x10)) || \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* START STOP UNIT with START bit 0 and POWER CONDITION 0 */ \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[0]) == SCMD_START_STOP) && ( \
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto/* End of SCSI2_CONFLICT_FREE_CMDS */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t sbd_lu_reset_state(stmf_lu_t *lu);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void sbd_handle_sync_cache(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid sbd_handle_read_xfer_completion(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd, struct stmf_data_buf *dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_short_write_xfer_completion(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_data_buf_t *dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_short_write_transfers(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t buflen);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Fortevoid sbd_handle_identifying_info(scsi_task_t *task, stmf_data_buf_t *dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldstatic void sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint32_t buflen);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldstatic void sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyanextern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern int sbd_pgr_reservation_conflict(scsi_task_t *);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forteextern void sbd_pgr_reset(sbd_lu_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_pgr_remove_it_handle(sbd_lu_t *, sbd_it_data_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoextern void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorevoid sbd_do_sgl_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int first_xfer);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic void sbd_handle_write_same(scsi_task_t *task,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald struct stmf_data_buf *initial_dbuf);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic void sbd_do_write_same_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald struct stmf_data_buf *dbuf, uint8_t dbuf_reusable);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic void sbd_handle_write_same_xfer_completion(struct scsi_task *task,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_cmd_t *scmd, struct stmf_data_buf *dbuf, uint8_t dbuf_reusable);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IMPORTANT NOTE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * =================
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The whole world here is based on the assumption that everything within
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * a scsi task executes in a single threaded manner, even the aborts.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Dont ever change that. There wont be any performance gain but there
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will be tons of race conditions.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len, buflen, iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int bufs_to_take;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufs_to_take = ((task->task_max_nbufs > 2) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_max_nbufs;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size : scmd->len;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto laddr = scmd->addr + scmd->current_ro;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (buflen = 0, ndx = 0; (buflen < len) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (ndx < dbuf->db_sglist_length); ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iolen = min(len - buflen, dbuf->db_sglist[ndx].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (iolen == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
427fcaf873956aad428be801380a44e59d38b8b5tim szeto if (sbd_data_read(sl, task, laddr, (uint64_t)iolen,
8e326937258295218b5a1f9a63fa6bb760376bbeZhong Wang dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Do not need to do xfer anymore, just complete it */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte buflen += iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte laddr += (uint64_t)iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = scmd->current_ro;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len -= buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro += buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len && (scmd->nbufs < bufs_to_take)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * A bad port implementation can keep on failing the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the request but keep on sending us a false
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * minsize.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore/*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * sbd_zcopy: Bail-out switch for reduced copy path.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * 0 - read & write off
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * 1 - read & write on
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * 2 - only read on
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * 4 - only write on
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooreint sbd_zcopy = 1; /* enable zcopy read & write path */
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooreuint32_t sbd_max_xfer_len = 0; /* Valid if non-zero */
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooreuint32_t sbd_1st_xfer_len = 0; /* Valid if non-zero */
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooreuint32_t sbd_copy_threshold = 0; /* Valid if non-zero */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorestatic void
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_do_sgl_read_xfer(struct scsi_task *task, sbd_cmd_t *scmd, int first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_io_t *zvio;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int ret, final_xfer;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t xfer_len, max_len, first_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_status_t xstat;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_data_buf_t *dbuf;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint_t nblks;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t blksize = sl->sl_blksize;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore size_t db_private_sz;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uintptr_t pad;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(rw_read_held(&sl->sl_access_state_lock));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT((sl->sl_flags & SL_MEDIA_LOADED) != 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Calculate the limits on xfer_len to the minimum of :
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - task limit
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - lun limit
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - sbd global limit if set
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - first xfer limit if set
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * First, protect against silly over-ride value
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_max_xfer_len && ((sbd_max_xfer_len % DEV_BSIZE) != 0)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_WARN, "sbd_max_xfer_len invalid %d, resetting\n",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_max_xfer_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_1st_xfer_len && ((sbd_1st_xfer_len % DEV_BSIZE) != 0)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_WARN, "sbd_1st_xfer_len invalid %d, resetting\n",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_1st_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_1st_xfer_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore max_len = MIN(task->task_max_xfer_len, sl->sl_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_max_xfer_len)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore max_len = MIN(max_len, sbd_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Special case the first xfer if hints are set.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer && (sbd_1st_xfer_len || task->task_1st_xfer_len)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* global over-ride has precedence */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_1st_xfer_len)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = sbd_1st_xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = task->task_1st_xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore while (scmd->len && scmd->nbufs < task->task_max_nbufs) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = MIN(max_len, scmd->len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_len) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = MIN(xfer_len, first_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->len == xfer_len) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore final_xfer = 1;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Attempt to end xfer on a block boundary.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The only way this does not happen is if the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * xfer_len is small enough to stay contained
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * within the same block.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t xfer_offset, xfer_aligned_end;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore final_xfer = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_offset = scmd->addr + scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_aligned_end =
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore P2ALIGN(xfer_offset+xfer_len, blksize);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (xfer_aligned_end > xfer_offset)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = xfer_aligned_end - xfer_offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Allocate object to track the read and reserve
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * enough space for scatter/gather list.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore offset = scmd->addr + scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore nblks = sbd_zvol_numsegs(sl, offset, xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore db_private_sz = sizeof (*zvio) + sizeof (uintptr_t) /* PAD */ +
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (nblks * sizeof (stmf_sglist_ent_t));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, db_private_sz,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore AF_DONTZERO);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Setup the dbuf
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * XXX Framework does not handle variable length sglists
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * properly, so setup db_lu_private and db_port_private
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * fields here. db_stmf_private is properly set for
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * calls to stmf_free.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (dbuf->db_port_private == NULL) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * XXX Framework assigns space to PP after db_sglist[0]
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_PANIC, "db_port_private == NULL");
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore pad = (uintptr_t)&dbuf->db_sglist[nblks];
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_lu_private = (void *)P2ROUNDUP(pad, sizeof (pad));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_port_private = NULL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_buf_size = xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_data_size = xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_relative_offset = scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_sglist_length = (uint16_t)nblks;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_xfer_status = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_handle = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_flags = (DB_DONT_CACHE | DB_DONT_REUSE |
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DB_DIRECTION_TO_RPORT | DB_LU_DATA_BUF);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (final_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_flags |= DB_SEND_STATUS_GOOD;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio = dbuf->db_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Need absolute offset for zvol access */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio->zvio_offset = offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio->zvio_flags = ZVIO_SYNC;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Accounting for start of read.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Note there is no buffer address for the probe yet.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, xfer_len,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, offset, scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_zvol_alloc_read_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, xfer_len,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, offset, int, ret, scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (ret != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Read failure from the backend.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* nothing queued, just finish */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* process failure when other dbufs finish */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Allow PP to do setup
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xstat = stmf_setup_dbuf(task, dbuf, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (xstat != STMF_SUCCESS) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This could happen if the driver cannot get the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * DDI resources it needs for this request.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If other dbufs are queued, try again when the next
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * one completes, otherwise give up.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_read_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs > 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* completion of previous dbuf will retry */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Done with this command.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_QFULL, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * dbuf is now queued on task
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs++;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* XXX leave this in for FW? */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE4(sbd__xfer, struct scsi_task *, task,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct stmf_data_buf *, dbuf, uint64_t, offset,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t, xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Do not pass STMF_IOF_LU_DONE so that the zvol
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * state can be released in the completion callback.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xstat = stmf_xfer_data(task, dbuf, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore switch (xstat) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_SUCCESS:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_BUSY:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The dbuf is queued on the task, but unknown
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * to the PP, thus no completion will occur.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_read_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_teardown_dbuf(task, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs--;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs > 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* completion of previous dbuf will retry */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Done with this command.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_QFULL, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_ABORTED:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Completion from task_done will cleanup
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Update the xfer progress.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(scmd->len >= xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->len -= xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->current_ro += xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred += dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs--;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->nbufs)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_READ_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte else
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang if (dbuf->db_flags & DB_DONT_REUSE) {
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang /* allocate new dbuf */
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang uint32_t maxsize, minsize, old_minsize;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang stmf_free_dbuf(task, dbuf);
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang maxsize = (scmd->len > (128*1024)) ? 128*1024 : scmd->len;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang minsize = maxsize >> 2;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang do {
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang old_minsize = minsize;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang } while ((dbuf == NULL) && (old_minsize > minsize) &&
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang (minsize >= 512));
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang if (dbuf == NULL) {
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang scmd->nbufs --;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang if (scmd->nbufs == 0) {
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang stmf_abort(STMF_QUEUE_TASK_ABORT, task,
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang STMF_ALLOC_FAILURE, NULL);
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang }
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang return;
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang }
2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41Zhong Wang }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore/*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This routine must release the DMU resources and free the dbuf
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * in all cases. If this is the final dbuf of the task, then drop
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * the reader lock on the LU state. If there are no errors and more
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * work to do, then queue more xfer operations.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorevoid
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_handle_sgl_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct stmf_data_buf *dbuf)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_status_t xfer_status;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int scmd_err;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(dbuf->db_lu_private);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(scmd->cmd_type == SBD_CMD_SCSI_READ);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs--; /* account for this dbuf */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Release the DMU resources.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_read_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Release the dbuf after retrieving needed fields.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_status = dbuf->db_xfer_status;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore data_size = dbuf->db_data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_teardown_dbuf(task, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Release the state lock if this is the last completion.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If this is the last dbuf on task and all data has been
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * transferred or an error encountered, then no more dbufs
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * will be queued.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd_err = (((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0) ||
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) ||
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (xfer_status != STMF_SUCCESS));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0 && (scmd->len == 0 || scmd_err)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* all DMU state has been released */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If there have been no errors, either complete the task
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * or issue more data xfer operations.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (!scmd_err) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This chunk completed successfully
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore task->task_nbytes_transferred += data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0 && scmd->len == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This command completed successfully
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Status was sent along with data, so no status
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * completion will occur. Tell stmf we are done.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_task_lu_done(task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Start more xfers
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_do_sgl_read_xfer(task, scmd, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Sort out the failure
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If a previous error occurred, leave the command active
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * and wait for the last completion to send the status check.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Must have been a failure on current dbuf
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(xfer_status != STMF_SUCCESS);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_abort(STMF_QUEUE_TASK_ABORT, task, xfer_status, NULL);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorevoid
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_handle_sgl_write_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct stmf_data_buf *dbuf)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_io_t *zvio = dbuf->db_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int ret;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int scmd_err, scmd_xfer_done;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_status_t xfer_status = dbuf->db_xfer_status;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t data_size = dbuf->db_data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(zvio);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Allow PP to free up resources before releasing the write bufs
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * as writing to the backend could take some time.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_teardown_dbuf(task, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs--; /* account for this dbuf */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * All data was queued and this is the last completion,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * but there could still be an error.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd_xfer_done = (scmd->len == 0 && scmd->nbufs == 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd_err = (((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0) ||
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) ||
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (xfer_status != STMF_SUCCESS));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, data_size,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, zvio->zvio_offset, scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd_err) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* just return the write buffers */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_write_bufs_abort(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd_xfer_done)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio->zvio_flags = ZVIO_COMMIT;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio->zvio_flags = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* write the data */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_zvol_rele_write_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, data_size,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, zvio->zvio_offset, int, ret, scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (ret != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* update the error flag */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd_err = 1;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Release the dbuf */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Release the state lock if this is the last completion.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If this is the last dbuf on task and all data has been
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * transferred or an error encountered, then no more dbufs
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * will be queued.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0 && (scmd->len == 0 || scmd_err)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* all DMU state has been released */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If there have been no errors, either complete the task
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * or issue more data xfer operations.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (!scmd_err) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* This chunk completed successfully */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore task->task_nbytes_transferred += data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd_xfer_done) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* This command completed successfully */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if ((scmd->flags & SBD_SCSI_CMD_SYNC_WRITE) &&
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (sbd_flush_data_cache(sl, 0) != SBD_SUCCESS)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_WRITE_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_GOOD, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Start more xfers
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_do_sgl_write_xfer(task, scmd, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Sort out the failure
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_WRITE_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Leave the command active until last dbuf completes.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(xfer_status != STMF_SUCCESS);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_abort(STMF_QUEUE_TASK_ABORT, task, xfer_status, NULL);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore/*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Handle a copy operation using the zvol interface.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Similar to the sbd_data_read/write path, except it goes directly through
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * the zvol interfaces. It can pass a port provider sglist in the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * form of uio which is lost through the vn_rdwr path.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Returns:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * STMF_SUCCESS - request handled
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * STMF_FAILURE - request not handled, caller must deal with error
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorestatic stmf_status_t
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_copy_rdwr(scsi_task_t *task, uint64_t laddr, stmf_data_buf_t *dbuf,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int cmd, int commit)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct uio uio;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct iovec *iov, *tiov, iov1[8];
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t len, resid;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int ret, i, iovcnt, flags;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore boolean_t is_read;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(cmd == SBD_CMD_SCSI_READ || cmd == SBD_CMD_SCSI_WRITE);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore is_read = (cmd == SBD_CMD_SCSI_READ) ? B_TRUE : B_FALSE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore iovcnt = dbuf->db_sglist_length;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* use the stack for small iovecs */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (iovcnt > 8) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore iov = kmem_alloc(iovcnt * sizeof (*iov), KM_SLEEP);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore iov = &iov1[0];
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Convert dbuf sglist to iovec format */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore len = dbuf->db_data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore resid = len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore tiov = iov;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore for (i = 0; i < iovcnt; i++) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore tiov->iov_base = (caddr_t)dbuf->db_sglist[i].seg_addr;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore tiov->iov_len = MIN(resid, dbuf->db_sglist[i].seg_length);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore resid -= tiov->iov_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore tiov++;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (resid != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_WARN, "inconsistant sglist rem %d", resid);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (iov != &iov1[0])
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore kmem_free(iov, iovcnt * sizeof (*iov));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (STMF_FAILURE);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Setup the uio struct */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_iov = iov;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_iovcnt = iovcnt;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_loffset = laddr;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_segflg = (short)UIO_SYSSPACE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_resid = (uint64_t)len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_llimit = RLIM64_INFINITY;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (is_read == B_TRUE) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_fmode = FREAD;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_extflg = UIO_COPY_CACHED;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, len, uint64_t, laddr,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Fetch the data */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_zvol_copy_read(sl, &uio);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, len, uint64_t, laddr, int, ret,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_fmode = FWRITE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uio.uio_extflg = UIO_COPY_DEFAULT;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, len, uint64_t, laddr,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore flags = (commit) ? ZVIO_COMMIT : 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Write the data */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_zvol_copy_write(sl, &uio, flags);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint8_t *, NULL, uint64_t, len, uint64_t, laddr, int, ret,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scsi_task_t *, task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (iov != &iov1[0])
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore kmem_free(iov, iovcnt * sizeof (*iov));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (ret != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* Backend I/O error */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (STMF_FAILURE);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (STMF_SUCCESS);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t op = task->task_cdb[0];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_data_buf_t *dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int fast_path;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (op == SCMD_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (uint32_t)task->task_cdb[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = 256;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G5) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[6], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_READ_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto laddr = lba << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto len <<= sl->sl_data_blocksize_shift;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len != task->task_expected_xfer_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fast_path = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (len > task->task_expected_xfer_length) ?
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto task->task_expected_xfer_length : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte fast_path = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Determine if this read can directly use DMU buffers.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_zcopy & (2|1) && /* Debug switch */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore initial_dbuf == NULL && /* No PP buffer passed in */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sl->sl_flags & SL_CALL_ZVOL && /* zvol backing store */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (task->task_additional_flags &
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore TASK_AF_ACCEPT_LU_DBUF)) /* PP allows it */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Reduced copy path
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t copy_threshold, minsize;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int ret;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The sl_access_state_lock will be held shared
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * for the entire request and released when all
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * dbufs have completed.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_enter(&sl->sl_access_state_lock, RW_READER);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Check if setup is more expensive than copying the data.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Use the global over-ride sbd_zcopy_threshold if set.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore copy_threshold = (sbd_copy_threshold > 0) ?
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_copy_threshold : task->task_copy_threshold;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore minsize = len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (len < copy_threshold &&
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (dbuf = stmf_alloc_dbuf(task, len, &minsize, 0)) != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_copy_rdwr(task, laddr, dbuf,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore SBD_CMD_SCSI_READ, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* done with the backend */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (ret != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* backend error */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* send along good data */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_relative_offset = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_data_size = len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_flags = DB_SEND_STATUS_GOOD |
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DB_DIRECTION_TO_RPORT;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* XXX keep for FW? */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE4(sbd__xfer,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct scsi_task *, task,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct stmf_data_buf *, dbuf,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, laddr, uint32_t, len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (void) stmf_xfer_data(task, dbuf,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_IOF_LU_DONE);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* committed to reduced copy */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (task->task_lu_private) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd = (sbd_cmd_t *)task->task_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t),
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore KM_SLEEP);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore task->task_lu_private = scmd;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Setup scmd to track read progress.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags = SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->cmd_type = SBD_CMD_SCSI_READ;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->addr = laddr;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->len = len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->current_ro = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Kick-off the read.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_do_sgl_read_xfer(task, scmd, 1);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte maxsize = (len > (128*1024)) ? 128*1024 : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte initial_dbuf = stmf_alloc_dbuf(task, maxsize,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((initial_dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf == NULL) {
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto stmf_scsilib_send_status(task, STATUS_QFULL, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = initial_dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((dbuf->db_buf_size >= len) && fast_path &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (dbuf->db_sglist_length == 1)) {
427fcaf873956aad428be801380a44e59d38b8b5tim szeto if (sbd_data_read(sl, task, laddr, (uint64_t)len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[0].seg_addr) == STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_SEND_STATUS_GOOD |
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DB_DIRECTION_TO_RPORT;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* XXX keep for FW? */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DTRACE_PROBE4(sbd__xfer, struct scsi_task *, task,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore struct stmf_data_buf *, dbuf,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t, laddr, uint32_t, len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, STMF_IOF_LU_DONE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_READ_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private = scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SCSI_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->nbufs = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->addr = laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_do_read_xfer(task, scmd, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_do_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int bufs_to_take;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (scmd->len == 0) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting goto DO_WRITE_XFER_DONE;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Lets try not to hog all the buffers the port has. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufs_to_take = ((task->task_max_nbufs > 2) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cmd_xfer_length < (32 * 1024))) ? 2 :
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_max_nbufs;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if ((dbuf != NULL) &&
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting ((dbuf->db_flags & DB_DONT_REUSE) || (dbuf_reusable == 0))) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting /* free current dbuf and allocate a new one */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting stmf_free_dbuf(task, dbuf);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting dbuf = NULL;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (scmd->nbufs >= bufs_to_take) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting goto DO_WRITE_XFER_DONE;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t maxsize, minsize, old_minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting maxsize = (scmd->len > (128*1024)) ? 128*1024 :
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte minsize = maxsize >> 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte old_minsize = minsize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } while ((dbuf == NULL) && (old_minsize > minsize) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (minsize >= 512));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (scmd->nbufs == 0) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting stmf_abort(STMF_QUEUE_TASK_ABORT, task,
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting STMF_ALLOC_FAILURE, NULL);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size :
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->len;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting dbuf->db_relative_offset = scmd->current_ro;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting dbuf->db_data_size = len;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting (void) stmf_xfer_data(task, dbuf, 0);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->nbufs++; /* outstanding port xfers and bufs used */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->len -= len;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->current_ro += len;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if ((scmd->len != 0) && (scmd->nbufs < bufs_to_take)) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting sbd_do_write_xfer(task, scmd, NULL, 0);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting return;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles TingDO_WRITE_XFER_DONE:
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (dbuf != NULL) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorevoid
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_do_sgl_write_xfer(struct scsi_task *task, sbd_cmd_t *scmd, int first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_io_t *zvio;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int ret;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint32_t xfer_len, max_len, first_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_status_t xstat;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_data_buf_t *dbuf;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint_t nblks;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t blksize = sl->sl_blksize;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore size_t db_private_sz;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uintptr_t pad;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(rw_read_held(&sl->sl_access_state_lock));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT((sl->sl_flags & SL_MEDIA_LOADED) != 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Calculate the limits on xfer_len to the minimum of :
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - task limit
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - lun limit
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - sbd global limit if set
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * - first xfer limit if set
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * First, protect against silly over-ride value
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_max_xfer_len && ((sbd_max_xfer_len % DEV_BSIZE) != 0)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_WARN, "sbd_max_xfer_len invalid %d, resetting\n",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_max_xfer_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_1st_xfer_len && ((sbd_1st_xfer_len % DEV_BSIZE) != 0)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_WARN, "sbd_1st_xfer_len invalid %d, resetting\n",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_1st_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_1st_xfer_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore max_len = MIN(task->task_max_xfer_len, sl->sl_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_max_xfer_len)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore max_len = MIN(max_len, sbd_max_xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Special case the first xfer if hints are set.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer && (sbd_1st_xfer_len || task->task_1st_xfer_len)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* global over-ride has precedence */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_1st_xfer_len)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = sbd_1st_xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = task->task_1st_xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore while (scmd->len && scmd->nbufs < task->task_max_nbufs) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = MIN(max_len, scmd->len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_len) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = MIN(xfer_len, first_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore first_len = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (xfer_len < scmd->len) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Attempt to end xfer on a block boundary.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The only way this does not happen is if the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * xfer_len is small enough to stay contained
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * within the same block.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t xfer_offset, xfer_aligned_end;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_offset = scmd->addr + scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_aligned_end =
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore P2ALIGN(xfer_offset+xfer_len, blksize);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (xfer_aligned_end > xfer_offset)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xfer_len = xfer_aligned_end - xfer_offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Allocate object to track the write and reserve
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * enough space for scatter/gather list.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore offset = scmd->addr + scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore nblks = sbd_zvol_numsegs(sl, offset, xfer_len);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore db_private_sz = sizeof (*zvio) + sizeof (uintptr_t) /* PAD */ +
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (nblks * sizeof (stmf_sglist_ent_t));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf = stmf_alloc(STMF_STRUCT_DATA_BUF, db_private_sz,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore AF_DONTZERO);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Setup the dbuf
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore *
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * XXX Framework does not handle variable length sglists
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * properly, so setup db_lu_private and db_port_private
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * fields here. db_stmf_private is properly set for
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * calls to stmf_free.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (dbuf->db_port_private == NULL) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * XXX Framework assigns space to PP after db_sglist[0]
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_PANIC, "db_port_private == NULL");
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore pad = (uintptr_t)&dbuf->db_sglist[nblks];
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_lu_private = (void *)P2ROUNDUP(pad, sizeof (pad));
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_port_private = NULL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_buf_size = xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_data_size = xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_relative_offset = scmd->current_ro;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_sglist_length = (uint16_t)nblks;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_xfer_status = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_handle = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_flags = (DB_DONT_CACHE | DB_DONT_REUSE |
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore DB_DIRECTION_FROM_RPORT | DB_LU_DATA_BUF);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio = dbuf->db_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore zvio->zvio_offset = offset;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* get the buffers */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ret = sbd_zvol_alloc_write_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (ret != 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Could not allocate buffers from the backend;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * treat it like an IO error.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Nothing queued, so no completions coming
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_WRITE_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Completions of previous buffers will cleanup.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Allow PP to do setup
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xstat = stmf_setup_dbuf(task, dbuf, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (xstat != STMF_SUCCESS) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This could happen if the driver cannot get the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * DDI resources it needs for this request.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If other dbufs are queued, try again when the next
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * one completes, otherwise give up.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_write_bufs_abort(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs > 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* completion of previous dbuf will retry */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Done with this command.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_QFULL, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_WRITE_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * dbuf is now queued on task
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs++;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore xstat = stmf_xfer_data(task, dbuf, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore switch (xstat) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_SUCCESS:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_BUSY:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The dbuf is queued on the task, but unknown
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * to the PP, thus no completion will occur.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_write_bufs_abort(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_teardown_dbuf(task, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs--;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->nbufs > 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* completion of previous dbuf will retry */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Done with this command.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (first_xfer)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_QFULL, 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore else
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_WRITE_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case STMF_ABORTED:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Completion code will cleanup.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Update the xfer progress.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->len -= xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->current_ro += xfer_len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_write_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t buflen, iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (scmd->nbufs > 0) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting /*
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * Decrement the count to indicate the port xfer
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * into the dbuf has completed even though the buf is
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * still in use here in the LU provider.
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->nbufs--;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte goto WRITE_XFER_DONE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if (scmd->len != 0) {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting /*
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * Initiate the next port xfer to occur in parallel
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting * with writing this buf.
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting */
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting sbd_do_write_xfer(task, scmd, NULL, 0);
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto laddr = scmd->addr + dbuf->db_relative_offset;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If this is going to a zvol, use the direct call to
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * sbd_zvol_copy_{read,write}. The direct call interface is
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * restricted to PPs that accept sglists, but that is not required.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sl->sl_flags & SL_CALL_ZVOL &&
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF) &&
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (sbd_zcopy & (4|1))) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore int commit;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore commit = (scmd->len == 0 && scmd->nbufs == 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_copy_rdwr(task, laddr, dbuf, SBD_CMD_SCSI_WRITE,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore commit) != STMF_SUCCESS)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore buflen = dbuf->db_data_size;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (ndx < dbuf->db_sglist_length); ndx++) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore iolen = min(dbuf->db_data_size - buflen,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_sglist[ndx].seg_length);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (iolen == 0)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_data_write(sl, task, laddr, (uint64_t)iolen,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore dbuf->db_sglist[ndx].seg_addr) != STMF_SUCCESS) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags |= SBD_SCSI_CMD_XFER_FAIL;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore buflen += iolen;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore laddr += (uint64_t)iolen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred += buflen;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn ForteWRITE_XFER_DONE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_free_dbuf(task, dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->nbufs)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return; /* wait for all buffers to complete */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_WRITE_ERROR);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita /*
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * If SYNC_WRITE flag is on then we need to flush
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * cache before sending status.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Note: this may be a no-op because of how
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * SL_WRITEBACK_CACHE_DISABLE and
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * SL_FLUSH_ON_DISABLED_WRITECACHE are set, but not
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * worth code complexity of checking those in this code
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * path, SBD_SCSI_CMD_SYNC_WRITE is rarely set.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita */
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if ((scmd->flags & SBD_SCSI_CMD_SYNC_WRITE) &&
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita (sbd_flush_data_cache(sl, 0) != SBD_SUCCESS)) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita stmf_scsilib_send_status(task, STATUS_CHECK,
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita STMF_SAA_WRITE_ERROR);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita stmf_scsilib_send_status(task, STATUS_GOOD, 0);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita }
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting sbd_do_write_xfer(task, scmd, dbuf, dbuf_reusable);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore/*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Return true if copy avoidance is beneficial.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorestatic int
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_zcopy_write_useful(scsi_task_t *task, uint64_t laddr, uint32_t len,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t blksize)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * If there is a global copy threshold over-ride, use it.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Otherwise use the PP value with the caveat that at least
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * 1/2 the data must avoid being copied to be useful.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_copy_threshold > 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (len >= sbd_copy_threshold);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore uint64_t no_copy_span;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /* sub-blocksize writes always copy */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (len < task->task_copy_threshold || len < blksize)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Calculate amount of data that will avoid the copy path.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * The calculation is only valid if len >= blksize.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore no_copy_span = P2ALIGN(laddr+len, blksize) -
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore P2ROUNDUP(laddr, blksize);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return (no_copy_span >= len/2);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_write(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t op = task->task_cdb[0], do_immediate_data = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_data_buf_t *dbuf;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita uint8_t sync_wr_flag = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_WRITE_PROTECTED) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_WRITE_PROTECTED);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (op == SCMD_WRITE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI21(&task->task_cdb[1], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (uint32_t)task->task_cdb[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = 256;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G1) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G5) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[6], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (op == SCMD_WRITE_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI16(&task->task_cdb[7], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY_G5) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI32(&task->task_cdb[6], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita } else if (op == SCMD_WRITE_VERIFY_G4) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita len = READ_SCSI32(&task->task_cdb[10], uint32_t);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sync_wr_flag = SBD_SCSI_CMD_SYNC_WRITE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto laddr = lba << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto len <<= sl->sl_data_blocksize_shift;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = (len > task->task_expected_xfer_length) ?
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length : len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (sbd_zcopy & (4|1) && /* Debug switch */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore initial_dbuf == NULL && /* No PP buf passed in */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sl->sl_flags & SL_CALL_ZVOL && /* zvol backing store */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (task->task_additional_flags &
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore TASK_AF_ACCEPT_LU_DBUF) && /* PP allows it */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zcopy_write_useful(task, laddr, len, sl->sl_blksize)) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * XXX Note that disallowing initial_dbuf will eliminate
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * iSCSI from participating. For small writes, that is
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * probably ok. For large writes, it may be best to just
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * copy the data from the initial dbuf and use zcopy for
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * the rest.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_enter(&sl->sl_access_state_lock, RW_READER);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_scsilib_send_status(task, STATUS_CHECK,
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore STMF_SAA_READ_ERROR);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Setup scmd to track the write progress.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (task->task_lu_private) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd = (sbd_cmd_t *)task->task_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t),
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore KM_SLEEP);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore task->task_lu_private = scmd;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->flags = SBD_SCSI_CMD_ACTIVE | sync_wr_flag;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->cmd_type = SBD_CMD_SCSI_WRITE;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->nbufs = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->addr = laddr;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->len = len;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->current_ro = 0;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_do_sgl_write_xfer(task, scmd, 1);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting if ((initial_dbuf != NULL) && (task->task_flags & TF_INITIAL_BURST)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf->db_data_size > len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (initial_dbuf->db_data_size >
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* protocol error */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_INVALID_ARG, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte initial_dbuf->db_data_size = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte do_immediate_data = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = initial_dbuf;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private = scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita scmd->flags = SBD_SCSI_CMD_ACTIVE | sync_wr_flag;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SCSI_WRITE;
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting scmd->nbufs = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->addr = laddr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len = len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (do_immediate_data) {
427fcaf873956aad428be801380a44e59d38b8b5tim szeto /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Account for data passed in this write command
427fcaf873956aad428be801380a44e59d38b8b5tim szeto */
427fcaf873956aad428be801380a44e59d38b8b5tim szeto (void) stmf_xfer_data(task, dbuf, STMF_IOF_STATS_ONLY);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->len -= dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->current_ro += dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write_xfer_completion(task, scmd, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
79a8ba49772f168c36ec9d6271894fecbb3ad690Charles Ting sbd_do_write_xfer(task, scmd, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Utility routine to handle small non performance data transfers to the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * initiators. dbuf is an initial data buf (if any), 'p' points to a data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * buffer which is source of data for transfer, cdb_xfer_size is the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * transfer size based on CDB, cmd_xfer_size is the actual amount of data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * which this command would transfer (the size of data pointed to by 'p').
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_short_read_transfers(scsi_task_t *task, stmf_data_buf_t *dbuf,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *p, uint32_t cdb_xfer_size, uint32_t cmd_xfer_size)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t bufsize, ndx;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_xfer_size = min(cmd_xfer_size, cdb_xfer_size);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmd_xfer_size = min(cmd_xfer_size,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd_xfer_size == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t minsize = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf = stmf_alloc_dbuf(task, cmd_xfer_size, &minsize, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf == NULL) {
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto stmf_scsilib_send_status(task, STATUS_QFULL, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (bufsize = 0, ndx = 0; bufsize < cmd_xfer_size; ndx++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *d;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t s;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte d = dbuf->db_sglist[ndx].seg_addr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s = min((cmd_xfer_size - bufsize),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_sglist[ndx].seg_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(p+bufsize, d, s);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bufsize += s;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_relative_offset = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_data_size = cmd_xfer_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_flags = DB_DIRECTION_TO_RPORT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_private =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->cmd_type = SBD_CMD_SMALL_READ;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_xfer_data(task, dbuf, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_short_read_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (dbuf->db_xfer_status != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_abort(STMF_QUEUE_TASK_ABORT, task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte dbuf->db_xfer_status, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_nbytes_transferred = dbuf->db_data_size;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_short_write_transfers(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_cmd_t *scmd;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_cmd_xfer_length = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_additional_flags & TASK_AF_NO_EXPECTED_XFER_LENGTH) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_expected_xfer_length = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cdb_xfer_size = min(cdb_xfer_size,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_expected_xfer_length);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb_xfer_size == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_lu_private == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_lu_private = kmem_zalloc(sizeof (sbd_cmd_t),
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto KM_SLEEP);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bzero(task->task_lu_private, sizeof (sbd_cmd_t));
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd = (sbd_cmd_t *)task->task_lu_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd->cmd_type = SBD_CMD_SMALL_WRITE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd->flags = SBD_SCSI_CMD_ACTIVE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd->len = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (dbuf == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t minsize = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf = stmf_alloc_dbuf(task, cdb_xfer_size, &minsize, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (dbuf == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_abort(STMF_QUEUE_TASK_ABORT, task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_ALLOC_FAILURE, NULL);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf->db_data_size = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf->db_relative_offset = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
c1374a13e412c4ec42cba867e57347a0e049a822Surya Prakki (void) stmf_xfer_data(task, dbuf, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (dbuf->db_data_size < cdb_xfer_size) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_abort(STMF_QUEUE_TASK_ABORT, task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_ABORTED, NULL);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf->db_data_size = cdb_xfer_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_xfer_completion(task, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_short_write_xfer_completion(scsi_task_t *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_data_buf_t *dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_cmd_t *scmd;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_status_t st_ret;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /*
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * For now lets assume we will get only one sglist element
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * for short writes. If that ever changes, we should allocate
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * a local buffer and copy all the sg elements to one linear space.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((dbuf->db_xfer_status != STMF_SUCCESS) ||
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (dbuf->db_sglist_length > 1)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_abort(STMF_QUEUE_TASK_ABORT, task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dbuf->db_xfer_status, NULL);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_nbytes_transferred = dbuf->db_data_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd = (sbd_cmd_t *)task->task_lu_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Lets find out who to call */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto switch (task->task_cdb[0]) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case SCMD_MODE_SELECT:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case SCMD_MODE_SELECT_G1:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_STANDBY) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte st_ret = stmf_proxy_scsi_cmd(task, dbuf);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (st_ret != STMF_SUCCESS) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STMF_SAA_LU_NO_ACCESS_UNAVAIL);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_handle_mode_select_xfer(task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald case SCMD_UNMAP:
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald sbd_handle_unmap_xfer(task,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald dbuf->db_sglist[0].seg_addr, dbuf->db_data_size);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case SCMD_PERSISTENT_RESERVE_OUT:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_STANDBY) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte st_ret = stmf_proxy_scsi_cmd(task, dbuf);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (st_ret != STMF_SUCCESS) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STMF_SAA_LU_NO_ACCESS_UNAVAIL);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_handle_pgr_out_data(task, dbuf);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto default:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* This should never happen */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_abort(STMF_QUEUE_TASK_ABORT, task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_ABORTED, NULL);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_read_capacity(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t cdb_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t p[32];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t s;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint16_t blksize;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte s--;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (task->task_cdb[0]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCMD_READ_CAPACITY:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (s & 0xffffffff00000000ull) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = p[1] = p[2] = p[3] = 0xFF;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = (s >> 24) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = (s >> 16) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[2] = (s >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = s & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[4] = 0; p[5] = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[6] = (blksize >> 8) & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[7] = blksize & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, 8, 8);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case SCMD_SVC_ACTION_IN_G4:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb_len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(p, 32);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[0] = (s >> 56) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = (s >> 48) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[2] = (s >> 40) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = (s >> 32) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[4] = (s >> 24) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[5] = (s >> 16) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[6] = (s >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[7] = s & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[10] = (blksize >> 8) & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[11] = blksize & 0xff;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (sl->sl_flags & SL_UNMAP_ENABLED) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[14] = 0x80;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb_len, 32);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_calc_geometry(uint64_t s, uint16_t blksize, uint8_t *nsectors,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t *nheads, uint32_t *ncyl)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (s < (4ull * 1024ull * 1024ull * 1024ull)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *nsectors = 32;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *nheads = 8;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *nsectors = 254;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *nheads = 254;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto *ncyl = s / ((uint64_t)blksize * (uint64_t)(*nsectors) *
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (uint64_t)(*nheads));
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_mode_sense(struct scsi_task *task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto struct stmf_data_buf *initial_dbuf, uint8_t *buf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t cmd_size, n;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t *cdb;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t ncyl;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t nsectors, nheads;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t page, ctrl, header_size, pc_valid;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint16_t nbytes;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t *p;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint64_t s = sl->sl_lu_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t dev_spec_param_offset;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p = buf; /* buf is assumed to be zeroed out and large enough */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cdb = &task->task_cdb[0];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto page = cdb[2] & 0x3F;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ctrl = (cdb[2] >> 6) & 3;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cmd_size = (cdb[0] == SCMD_MODE_SENSE) ? cdb[4] :
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto READ_SCSI16(&cdb[7], uint32_t);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb[0] == SCMD_MODE_SENSE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto header_size = 4;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dev_spec_param_offset = 2;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto header_size = 8;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto dev_spec_param_offset = 3;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Now validate the command */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb[2] == 0) || (page == MODEPAGE_ALLPAGES) || (page == 0x08) ||
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto (page == 0x0A) || (page == 0x03) || (page == 0x04)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto pc_valid = 1;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto pc_valid = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cmd_size < header_size) || (pc_valid == 0)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* We will update the length in the mode header at the end */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Block dev device specific param in mode param header has wp bit */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_WRITE_PROTECTED) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + dev_spec_param_offset] = BIT_7;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += header_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* We are not going to return any block descriptor */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto nbytes = ((uint16_t)1) << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_calc_geometry(s, nbytes, &nsectors, &nheads, &ncyl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == 0x03) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n] = 0x03;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n+1] = 0x16;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (ctrl != 1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 11] = nsectors;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 12] = nbytes >> 8;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 13] = nbytes & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 20] = 0x80;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += 24;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == 0x04) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n] = 0x04;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 1] = 0x16;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (ctrl != 1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 2] = ncyl >> 16;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 3] = ncyl >> 8;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 4] = ncyl & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 5] = nheads;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 20] = 0x15;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[n + 21] = 0x18;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += 24;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == MODEPAGE_CACHING) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto struct mode_caching *mode_caching_page;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page = (struct mode_caching *)&p[n];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.code = MODEPAGE_CACHING;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.ps = 1; /* A saveable page */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.length = 0x12;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto switch (ctrl) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (0):
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Current */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->wce = 1;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (1):
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Changeable */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags &
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto SL_WRITEBACK_CACHE_SET_UNSUPPORTED) == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->wce = 1;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto default:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags &
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto SL_SAVED_WRITE_CACHE_DISABLE) == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->wce = 1;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += (sizeof (struct mode_page) +
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_caching_page->mode_page.length);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((page == MODEPAGE_CTRL_MODE) || (page == MODEPAGE_ALLPAGES)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto struct mode_control_scsi3 *mode_control_page;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page = (struct mode_control_scsi3 *)&p[n];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->mode_page.code = MODEPAGE_CTRL_MODE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->mode_page.length =
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto PAGELENGTH_MODE_CONTROL_SCSI3;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (ctrl != 1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not looking for changeable values, report this. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->que_mod = CTRL_QMOD_UNRESTRICT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto n += (sizeof (struct mode_page) +
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mode_control_page->mode_page.length);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb[0] == SCMD_MODE_SENSE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (n > 255) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /*
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Mode parameter header length doesn't include the number
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * of bytes in the length field, so adjust the count.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Byte count minus header length field size.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto buf[0] = (n - 1) & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Byte count minus header length field size. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto buf[1] = (n - 2) & 0xff;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto buf[0] = ((n - 2) >> 8) & 0xff;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_read_transfers(task, initial_dbuf, buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cmd_size, n);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t cmd_xfer_len;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_cdb[0] == SCMD_MODE_SELECT) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cmd_xfer_len = (uint32_t)task->task_cdb[4];
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((task->task_cdb[1] & 0xFE) != 0x10) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cmd_xfer_len == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* zero byte mode selects are allowed */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetovoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_handle_mode_select_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_it_data_t *it;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto int hdr_len, bd_len;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_status_t sret;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto int i;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_cdb[0] == SCMD_MODE_SELECT) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto hdr_len = 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto hdr_len = 8;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buflen < hdr_len)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto mode_sel_param_len_err;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bd_len = hdr_len == 4 ? buf[3] : READ_SCSI16(&buf[6], int);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buflen < (hdr_len + bd_len + 2))
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto mode_sel_param_len_err;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto buf += hdr_len + bd_len;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto buflen -= hdr_len + bd_len;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((buf[0] != 8) || (buflen != ((uint32_t)buf[1] + 2))) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto mode_sel_param_len_err;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buf[2] & 0xFB) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto mode_sel_param_field_err;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (i = 3; i < (buf[1] + 2); i++) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buf[i]) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto mode_sel_param_field_err;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sret = SBD_SUCCESS;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* All good. Lets handle the write cache change, if any */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buf[2] & BIT_2) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sret = sbd_wcd_set(0, sl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sret = sbd_wcd_set(1, sl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sret != SBD_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_WRITE_ERROR);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* set on the device passed, now set the flags */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buf[2] & BIT_2) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it == task->task_lu_itl_handle)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto continue;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_ua_conditions |= SBD_UA_MODE_PARAMETERS_CHANGED;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_cdb[1] & 1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (buf[2] & BIT_2) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sret = sbd_write_lu_info(sl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sret == SBD_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_WRITE_ERROR);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetomode_sel_param_len_err:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_PARAM_LIST_LENGTH_ERROR);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetomode_sel_param_field_err:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte/*
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte * Command support added from SPC-4 r24
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte * Supports info type 0, 2, 127
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Fortevoid
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Fortesbd_handle_identifying_info(struct scsi_task *task,
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte stmf_data_buf_t *initial_dbuf)
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte{
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint8_t *cdb;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint32_t cmd_size;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint32_t param_len;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint32_t xfer_size;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint8_t info_type;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte uint8_t *buf, *p;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte cdb = &task->task_cdb[0];
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte cmd_size = READ_SCSI32(&cdb[6], uint32_t);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte info_type = cdb[10]>>1;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte /* Validate the command */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte if (cmd_size < 4) {
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte STMF_SAA_INVALID_FIELD_IN_CDB);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte return;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte }
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte p = buf = kmem_zalloc(260, KM_SLEEP);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte switch (info_type) {
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte case 0:
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte /*
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte * No value is supplied but this info type
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte * is mandatory.
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte xfer_size = 4;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte break;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte case 2:
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte mutex_enter(&sl->sl_lock);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte param_len = strlcpy((char *)(p+4), sl->sl_alias, 256);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte mutex_exit(&sl->sl_lock);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte /* text info must be null terminated */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte if (++param_len > 256)
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte param_len = 256;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte SCSI_WRITE16(p+2, param_len);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte xfer_size = param_len + 4;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte break;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte case 127:
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte /* 0 and 2 descriptor supported */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte SCSI_WRITE16(p+2, 8); /* set param length */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte p += 8;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte *p = 4; /* set type to 2 (7 hi bits) */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte p += 2;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte SCSI_WRITE16(p, 256); /* 256 max length */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte xfer_size = 12;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte break;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte default:
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte stmf_scsilib_send_status(task, STATUS_CHECK,
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte STMF_SAA_INVALID_FIELD_IN_CDB);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte kmem_free(buf, 260);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte return;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte }
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte sbd_handle_short_read_transfers(task, initial_dbuf, buf,
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte cmd_size, xfer_size);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte kmem_free(buf, 260);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte}
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan/*
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * This function parse through a string, passed to it as a pointer to a string,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * by adjusting the pointer to the first non-space character and returns
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * the count/length of the first bunch of non-space characters. Multiple
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * Management URLs are stored as a space delimited string in sl_mgmt_url
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * field of sbd_lu_t. This function is used to retrieve one url at a time.
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan *
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * i/p : pointer to pointer to a url string
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * o/p : Adjust the pointer to the url to the first non white character
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * and returns the length of the URL
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyanuint16_t
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyansbd_parse_mgmt_url(char **url_addr) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint16_t url_length = 0;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan char *url;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url = *url_addr;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan while (*url != '\0') {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (*url == ' ' || *url == '\t' || *url == '\n') {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan (*url_addr)++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url = *url_addr;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan } else {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan while (*url != '\0') {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (*url == ' ' || *url == '\t' ||
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan *url == '\n' || *url == '\0') {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url_length++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan return (url_length);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan}
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald/* Try to make this the size of a kmem allocation cache. */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic uint_t sbd_write_same_optimal_chunk = 128 * 1024;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic sbd_status_t
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldsbd_write_same_data(struct scsi_task *task, sbd_cmd_t *scmd)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald{
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint64_t addr, len, sz_done;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint32_t big_buf_size, xfer_size, off;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint8_t *big_buf;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_status_t ret;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (task->task_cdb[0] == SCMD_WRITE_SAME_G1) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald addr = READ_SCSI32(&task->task_cdb[2], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = READ_SCSI16(&task->task_cdb[7], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald addr = READ_SCSI64(&task->task_cdb[2], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = READ_SCSI32(&task->task_cdb[10], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald addr <<= sl->sl_data_blocksize_shift;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len <<= sl->sl_data_blocksize_shift;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Reminders:
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * "len" is total size of what we wish to "write same".
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald *
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * xfer_size will be scmd->trans_data_len, which is the length
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * of the pattern we wish to replicate over "len". We replicate
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * "xfer_size" of pattern over "len".
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald *
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * big_buf_size is set to an ideal actual-write size for an output
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * operation. It may be the same as "len". If it's not, it should
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * be an exact multiple of "xfer_size" so we don't get pattern
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * breakage until the very end of "len".
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald big_buf_size = len > sbd_write_same_optimal_chunk ?
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_write_same_optimal_chunk : (uint32_t)len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald xfer_size = scmd->trans_data_len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * All transfers should be an integral multiple of the sector size.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald ASSERT((big_buf_size % xfer_size) == 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Don't sleep for the allocation, and don't make the system
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * reclaim memory. Trade higher I/Os if in a low-memory situation.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald big_buf = kmem_alloc(big_buf_size, KM_NOSLEEP | KM_NORMALPRI);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (big_buf == NULL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Just send it in terms of of the transmitted data. This
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * will be very slow.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald DTRACE_PROBE1(write__same__low__memory, uint64_t, big_buf_size);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald big_buf = scmd->trans_data;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald big_buf_size = scmd->trans_data_len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * We already ASSERT()ed big_buf_size is an integral multiple
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * of xfer_size.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald for (off = 0; off < big_buf_size; off += xfer_size)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald bcopy(scmd->trans_data, big_buf + off, xfer_size);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* Do the actual I/O. Recycle xfer_size now to be write size. */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald DTRACE_PROBE1(write__same__io__begin, uint64_t, len);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald for (sz_done = 0; sz_done < len; sz_done += (uint64_t)xfer_size) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald xfer_size = ((big_buf_size + sz_done) <= len) ? big_buf_size :
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len - sz_done;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald ret = sbd_data_write(sl, task, addr + sz_done,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (uint64_t)xfer_size, big_buf);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (ret != SBD_SUCCESS)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald break;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald DTRACE_PROBE2(write__same__io__end, uint64_t, len, uint64_t, sz_done);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (big_buf != scmd->trans_data)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald kmem_free(big_buf, big_buf_size);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return (ret);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald}
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic void
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldsbd_handle_write_same_xfer_completion(struct scsi_task *task, sbd_cmd_t *scmd,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald{
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint64_t laddr;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint32_t buflen, iolen;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald int ndx, ret;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (dbuf->db_xfer_status != STMF_SUCCESS) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_xfer_status, NULL);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald goto write_same_xfer_done;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->len != 0) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Initiate the next port xfer to occur in parallel
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * with writing this buf.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_do_write_same_xfer(task, scmd, NULL, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald laddr = dbuf->db_relative_offset;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald for (buflen = 0, ndx = 0; (buflen < dbuf->db_data_size) &&
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (ndx < dbuf->db_sglist_length); ndx++) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald iolen = min(dbuf->db_data_size - buflen,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_sglist[ndx].seg_length);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (iolen == 0)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald break;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald bcopy(dbuf->db_sglist[ndx].seg_addr, &scmd->trans_data[laddr],
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald iolen);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald buflen += iolen;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald laddr += (uint64_t)iolen;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald task->task_nbytes_transferred += buflen;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldwrite_same_xfer_done:
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->len == 0 || scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_free_dbuf(task, dbuf);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->flags & SBD_SCSI_CMD_XFER_FAIL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_WRITE_ERROR);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald ret = sbd_write_same_data(task, scmd);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (ret != SBD_SUCCESS) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_WRITE_ERROR);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Only way we should get here is via handle_write_same(),
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * and that should make the following assertion always pass.
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald ASSERT((scmd->flags & SBD_SCSI_CMD_TRANS_DATA) &&
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->trans_data != NULL);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald kmem_free(scmd->trans_data, scmd->trans_data_len);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->flags &= ~SBD_SCSI_CMD_TRANS_DATA;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_do_write_same_xfer(task, scmd, dbuf, dbuf_reusable);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald}
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldstatic void
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldsbd_do_write_same_xfer(struct scsi_task *task, sbd_cmd_t *scmd,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald struct stmf_data_buf *dbuf, uint8_t dbuf_reusable)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald{
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint32_t len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->len == 0) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (dbuf != NULL)
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_free_dbuf(task, dbuf);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((dbuf != NULL) &&
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald ((dbuf->db_flags & DB_DONT_REUSE) || (dbuf_reusable == 0))) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* free current dbuf and allocate a new one */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_free_dbuf(task, dbuf);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf = NULL;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (dbuf == NULL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint32_t maxsize, minsize, old_minsize;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald maxsize = (scmd->len > (128*1024)) ? 128*1024 :
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald minsize = maxsize >> 2;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald do {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald old_minsize = minsize;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf = stmf_alloc_dbuf(task, maxsize, &minsize, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } while ((dbuf == NULL) && (old_minsize > minsize) &&
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (minsize >= 512));
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (dbuf == NULL) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->nbufs == 0) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_ALLOC_FAILURE, NULL);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = scmd->len > dbuf->db_buf_size ? dbuf->db_buf_size :
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_relative_offset = scmd->current_ro;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_data_size = len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_flags = DB_DIRECTION_FROM_RPORT;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (void) stmf_xfer_data(task, dbuf, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->nbufs++; /* outstanding port xfers and bufs used */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->len -= len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->current_ro += len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald}
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldstatic void
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonaldsbd_handle_write_same(scsi_task_t *task, struct stmf_data_buf *initial_dbuf)
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald{
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint64_t addr, len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_cmd_t *scmd;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_data_buf_t *dbuf;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint8_t unmap;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald uint8_t do_immediate_data = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald task->task_cmd_xfer_length = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (task->task_additional_flags &
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald TASK_AF_NO_EXPECTED_XFER_LENGTH) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald task->task_expected_xfer_length = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (sl->sl_flags & SL_WRITE_PROTECTED) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_WRITE_PROTECTED);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (task->task_cdb[1] & 0xF7) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald unmap = task->task_cdb[1] & 0x08;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (unmap && ((sl->sl_flags & SL_UNMAP_ENABLED) == 0)) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (task->task_cdb[0] == SCMD_WRITE_SAME_G1) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald addr = READ_SCSI32(&task->task_cdb[2], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = READ_SCSI16(&task->task_cdb[7], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald addr = READ_SCSI64(&task->task_cdb[2], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = READ_SCSI32(&task->task_cdb[10], uint64_t);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (len == 0) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald addr <<= sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald len <<= sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* Check if the command is for the unmap function */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (unmap) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (sbd_unmap(sl, addr, len) != 0) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_LBA_OUT_OF_RANGE);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_GOOD, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* Write same function */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald task->task_cmd_xfer_length = 1 << sl->sl_data_blocksize_shift;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (task->task_additional_flags &
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald TASK_AF_NO_EXPECTED_XFER_LENGTH) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald task->task_expected_xfer_length = task->task_cmd_xfer_length;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((addr + len) > sl->sl_lu_size) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_LBA_OUT_OF_RANGE);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* For rest of this I/O the transfer length is 1 block */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald len = ((uint64_t)1) << sl->sl_data_blocksize_shift;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* Some basic checks */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((len == 0) || (len != task->task_expected_xfer_length)) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((initial_dbuf != NULL) && (task->task_flags & TF_INITIAL_BURST)) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (initial_dbuf->db_data_size > len) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (initial_dbuf->db_data_size >
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald task->task_expected_xfer_length) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /* protocol error */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald stmf_abort(STMF_QUEUE_TASK_ABORT, task,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald STMF_INVALID_ARG, NULL);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald return;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald initial_dbuf->db_data_size = (uint32_t)len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald do_immediate_data = 1;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf = initial_dbuf;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (task->task_lu_private) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd = (sbd_cmd_t *)task->task_lu_private;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd = (sbd_cmd_t *)kmem_alloc(sizeof (sbd_cmd_t), KM_SLEEP);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald task->task_lu_private = scmd;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->flags = SBD_SCSI_CMD_ACTIVE | SBD_SCSI_CMD_TRANS_DATA;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->cmd_type = SBD_CMD_SCSI_WRITE;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->nbufs = 0;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->len = (uint32_t)len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->trans_data_len = (uint32_t)len;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->trans_data = kmem_alloc((size_t)len, KM_SLEEP);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->current_ro = 0;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (do_immediate_data) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald /*
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald * Account for data passed in this write command
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald */
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (void) stmf_xfer_data(task, dbuf, STMF_IOF_STATS_ONLY);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->len -= dbuf->db_data_size;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->current_ro += dbuf->db_data_size;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald dbuf->db_xfer_status = STMF_SUCCESS;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_handle_write_same_xfer_completion(task, scmd, dbuf, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_do_write_same_xfer(task, scmd, dbuf, 0);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald}
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldstatic void
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldsbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf)
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald{
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint32_t cmd_xfer_len;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (task->task_cdb[1] & 1) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (cmd_xfer_len == 0) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald task->task_cmd_xfer_length = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (task->task_additional_flags &
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald TASK_AF_NO_EXPECTED_XFER_LENGTH) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald task->task_expected_xfer_length = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_GOOD, 0);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald}
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldstatic void
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldsbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen)
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald{
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint32_t ulen, dlen, num_desc;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint64_t addr, len;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint8_t *p;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald int ret;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (buflen < 24) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald ulen = READ_SCSI16(buf, uint32_t);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald dlen = READ_SCSI16(buf + 2, uint32_t);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald num_desc = dlen >> 4;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (((ulen + 2) != buflen) || ((dlen + 8) != buflen) || (dlen & 0xf) ||
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald (num_desc == 0)) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald for (p = buf + 8; num_desc; num_desc--, p += 16) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald addr = READ_SCSI64(p, uint64_t);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald addr <<= sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald len = READ_SCSI32(p+8, uint64_t);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald len <<= sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald ret = sbd_unmap(sl, addr, len);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (ret != 0) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_LBA_OUT_OF_RANGE);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonaldunmap_done:
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_GOOD, 0);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald}
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyansbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint8_t *p;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t byte0;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint8_t page_length;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint16_t bsize = 512;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint16_t cmd_size;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint32_t xfer_size = 4;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint32_t mgmt_url_size = 0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint8_t exp;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald uint64_t s;
7beff157537d14493d525a42d33f0621b0b26217John Forte char *mgmt_url = NULL;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto byte0 = DTYPE_DIRECT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Basic protocol checks.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((((cdbp[1] & 1) == 0) && cdbp[2]) || cdbp[5]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Zero byte allocation length is not an error. Just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return success.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan cmd_size = (((uint16_t)cdbp[3]) << 8) | cdbp[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cmd_size == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags &
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte TASK_AF_NO_EXPECTED_XFER_LENGTH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_expected_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Standard inquiry
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdbp[1] & 1) == 0) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan int i;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan struct scsi_inquiry *inq;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq = (struct scsi_inquiry *)p;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan page_length = 69;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = page_length + 5;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto inq->inq_dtype = DTYPE_DIRECT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_ansi = 5; /* SPC-3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_hisup = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_rdf = 2; /* Response data format for SPC-3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_len = page_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_tpgs = TPGS_FAILOVER_IMPLICIT;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte inq->inq_cmdque = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_VID_VALID) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sl->sl_vendor_id, inq->inq_vid, 8);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sbd_vendor_id, inq->inq_vid, 8);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_PID_VALID) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sl->sl_product_id, inq->inq_pid, 16);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sbd_product_id, inq->inq_pid, 16);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_REV_VALID) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sl->sl_revision, inq->inq_revision, 4);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sbd_revision, inq->inq_revision, 4);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Adding Version Descriptors */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i = 0;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SAM-3 no version */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x00;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x60;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* transport */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan switch (task->task_lport->lport_id->protocol_id) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_FIBRE_CHANNEL:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x09;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x00;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_PARALLEL_SCSI:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_SSA:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_IEEE_1394:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Currently no claims of conformance */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_SRP:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x09;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x40;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_iSCSI:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x09;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x60;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_SAS:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_ADT:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case PROTOCOL_ATAPI:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan default:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Currently no claims of conformance */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SPC-3 no version */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x03;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x00;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan i++;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* SBC-2 no version */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_msb = 0x03;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan inq->inq_vd[i].inq_vd_lsb = 0x20;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan min(cmd_size, xfer_size));
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan kmem_free(p, bsize);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
7beff157537d14493d525a42d33f0621b0b26217John Forte rw_enter(&sbd_global_prop_lock, RW_READER);
7beff157537d14493d525a42d33f0621b0b26217John Forte if (sl->sl_mgmt_url) {
7beff157537d14493d525a42d33f0621b0b26217John Forte mgmt_url_size = strlen(sl->sl_mgmt_url);
7beff157537d14493d525a42d33f0621b0b26217John Forte mgmt_url = sl->sl_mgmt_url;
7beff157537d14493d525a42d33f0621b0b26217John Forte } else if (sbd_mgmt_url) {
7beff157537d14493d525a42d33f0621b0b26217John Forte mgmt_url_size = strlen(sbd_mgmt_url);
7beff157537d14493d525a42d33f0621b0b26217John Forte mgmt_url = sbd_mgmt_url;
7beff157537d14493d525a42d33f0621b0b26217John Forte }
7beff157537d14493d525a42d33f0621b0b26217John Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * EVPD handling
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Default 512 bytes may not be enough, increase bsize if necessary */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (cdbp[2] == 0x83 || cdbp[2] == 0x85) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (bsize < cmd_size)
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan bsize = cmd_size;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cdbp[2]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x00:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan page_length = 4 + (mgmt_url_size ? 1 : 0);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (sl->sl_flags & SL_UNMAP_ENABLED)
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald page_length += 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[0] = byte0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[3] = page_length;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Supported VPD pages in ascending order */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint8_t i = 5;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x80;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x83;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (mgmt_url_size != 0)
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x85;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[i++] = 0x86;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if (sl->sl_flags & SL_UNMAP_ENABLED) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[i++] = 0xb0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[i++] = 0xb2;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = page_length + 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case 0x80:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_serial_no_size) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto page_length = sl->sl_serial_no_size;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(sl->sl_serial_no, p + 4, sl->sl_serial_no_size);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* if no serial num is specified set 4 spaces */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan page_length = 4;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bcopy(" ", p + 4, 4);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[0] = byte0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[1] = 0x80;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[3] = page_length;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = page_length + 4;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x83:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = stmf_scsilib_prepare_vpd_page83(task, p,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto bsize, byte0, STMF_VPD_LU_ID|STMF_VPD_TARGET_ID|
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan case 0x85:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (mgmt_url_size == 0) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan stmf_scsilib_send_status(task, STATUS_CHECK,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan STMF_SAA_INVALID_FIELD_IN_CDB);
7beff157537d14493d525a42d33f0621b0b26217John Forte goto err_done;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan uint16_t idx, newidx, sz, url_size;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan char *url;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[0] = byte0;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[1] = 0x85;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan idx = 4;
7beff157537d14493d525a42d33f0621b0b26217John Forte url = mgmt_url;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url_size = sbd_parse_mgmt_url(&url);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Creating Network Service Descriptors */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan while (url_size != 0) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Null terminated and 4 Byte aligned */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan sz = url_size + 1;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan sz += (sz % 4) ? 4 - (sz % 4) : 0;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan newidx = idx + sz + 4;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan if (newidx < bsize) {
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /*
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * SPC-3r23 : Table 320 (Sec 7.6.5)
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * (Network service descriptor format
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan *
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * Note: Hard coding service type as
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan * "Storage Configuration Service".
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan p[idx] = 1;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan SCSI_WRITE16(p + idx + 2, sz);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan bcopy(url, p + idx + 4, url_size);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = newidx + 4;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan idx = newidx;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* skip to next mgmt url if any */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url += url_size;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan url_size = sbd_parse_mgmt_url(&url);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan /* Total descriptor length */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan SCSI_WRITE16(p + 2, idx - 4);
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan break;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan }
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case 0x86:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte page_length = 0x3c;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p[0] = byte0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[1] = 0x86; /* Page 86 response */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[3] = page_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Bits 0, 1, and 2 will need to be updated
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to reflect the queue tag handling if/when
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that is implemented. For now, we're going
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * to claim support only for Simple TA.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p[5] = 1;
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan xfer_size = page_length + 4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald case 0xb0:
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald goto err_done;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald page_length = 0x3c;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[0] = byte0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[1] = 0xb0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[3] = page_length;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[20] = p[21] = p[22] = p[23] = 0xFF;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[24] = p[25] = p[26] = p[27] = 0xFF;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald xfer_size = page_length + 4;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald break;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald case 0xb2:
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald stmf_scsilib_send_status(task, STATUS_CHECK,
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald STMF_SAA_INVALID_FIELD_IN_CDB);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald goto err_done;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald page_length = 4;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[0] = byte0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[1] = 0xb2;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[3] = page_length;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald exp = (uint8_t)sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald s = sl->sl_lu_size >> sl->sl_data_blocksize_shift;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald while (s & ((uint64_t)0xFFFFFFFF80000000ull)) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald s >>= 1;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald exp++;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[4] = exp;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald p[5] = 0xc0;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald xfer_size = page_length + 4;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald break;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
7beff157537d14493d525a42d33f0621b0b26217John Forte goto err_done;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan min(cmd_size, xfer_size));
7beff157537d14493d525a42d33f0621b0b26217John Forteerr_done:
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan kmem_free(p, bsize);
7beff157537d14493d525a42d33f0621b0b26217John Forte rw_exit(&sbd_global_prop_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_task_alloc(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_lu_private =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_alloc(sizeof (sbd_cmd_t), KM_NOSLEEP)) != NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_ALLOC_FAILURE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_it_data_t **ppit;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_pgr_remove_it_handle(sl, it);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (ppit = &sl->sl_it_list; *ppit != NULL;
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto ppit = &((*ppit)->sbd_it_next)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((*ppit) == it) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ppit = it->sbd_it_next;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto DTRACE_PROBE2(itl__nexus__end, stmf_lu_t *, sl->sl_lu,
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto sbd_it_data_t *, it);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(it, sizeof (*it));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_check_and_clear_scsi2_reservation(sbd_lu_t *sl, sbd_it_data_t *it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If we dont have any reservations, just get out. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it == NULL) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Find the I_T nexus which is holding the reservation. */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(it->sbd_it_session_id ==
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_rs_owner_session_id);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(it != NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We were passed an I_T nexus. If this nexus does not hold
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the reservation, do nothing. This is why this function is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * called "check_and_clear".
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_new_task(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_it_data_t *it;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t cdb0, cdb1;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_status_t st_ret;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it = task->task_lu_itl_handle) == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it->sbd_it_session_id ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_session->ss_session_id) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it = (sbd_it_data_t *)kmem_zalloc(sizeof (*it), KM_NOSLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (it == NULL) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_session_id = task->task_session->ss_session_id;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(task->task_lun_no, it->sbd_it_lun, 8);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_next = sl->sl_it_list;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_it_list = it;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto DTRACE_PROBE1(itl__nexus__start, scsi_task *, task);
e17f3b2227c590f1d761b9ec4613cfb05982e6abtim szeto
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyan sbd_pgr_initialize_it(task, it);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_register_itl_handle(task->task_lu, task->task_lun_no,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_session, it->sbd_it_session_id, it)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte != STMF_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_remove_it_handle(sl, it);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_BUSY, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_lu_itl_handle = it;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state != SBD_LU_STANDBY) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte it->sbd_it_ua_conditions = SBD_UA_POR;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else if (it->sbd_it_flags & SBD_IT_PGR_CHECK_FLAG) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_flags &= ~SBD_IT_PGR_CHECK_FLAG;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
716c180559045549271833327182dc6a266134f1Nattuvetty Bhavyan sbd_pgr_initialize_it(task, it);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_mgmt_function) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_handle_task_mgmt(task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /*
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if we're transitioning between access
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * states, return NOT READY
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_TRANSITION_TO_STANDBY ||
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sl->sl_access_state == SBD_LU_TRANSITION_TO_ACTIVE) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STMF_SAA_LU_NO_ACCESS_UNAVAIL);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte return;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Checking ua conditions as per SAM3R14 5.3.2 specified order */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t saa = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it->sbd_it_ua_conditions & SBD_UA_POR) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_ua_conditions &= ~SBD_UA_POR;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto saa = STMF_SAA_POR;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (saa) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK, saa);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Reservation conflict checks */
f4e76ddf09a338dc23da0904866290ac36274a5bNattuvetty Bhavyan if (sl->sl_access_state == SBD_LU_ACTIVE) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (SBD_PGR_RSVD(sl->sl_pgr)) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sbd_pgr_reservation_conflict(task)) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STATUS_RESERVATION_CONFLICT, 0);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte return;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else if ((sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte ((it->sbd_it_flags & SBD_IT_HAS_SCSI2_RESERVATION) == 0)) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (!(SCSI2_CONFLICT_FREE_CMDS(task->task_cdb))) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STATUS_RESERVATION_CONFLICT, 0);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte return;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Rest of the ua conndition checks */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((it->sbd_it_ua_conditions) && (task->task_cdb[0] != SCMD_INQUIRY)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it->sbd_it_ua_conditions & SBD_UA_CAPACITY_CHANGED) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions &= ~SBD_UA_CAPACITY_CHANGED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[0] == SCMD_READ_CAPACITY) ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ((task->task_cdb[0] == SCMD_SVC_ACTION_IN_G4) &&
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (task->task_cdb[1] ==
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte SSVC_ACTION_READ_CAPACITY_G4))) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = STMF_SAA_CAPACITY_DATA_HAS_CHANGED;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else if (it->sbd_it_ua_conditions &
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto SBD_UA_MODE_PARAMETERS_CHANGED) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_ua_conditions &=
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ~SBD_UA_MODE_PARAMETERS_CHANGED;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto saa = STMF_SAA_MODE_PARAMETERS_CHANGED;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else if (it->sbd_it_ua_conditions &
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte SBD_UA_ASYMMETRIC_ACCESS_CHANGED) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte it->sbd_it_ua_conditions &=
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte ~SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte saa = STMF_SAA_ASYMMETRIC_ACCESS_CHANGED;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else if (it->sbd_it_ua_conditions &
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte SBD_UA_ACCESS_STATE_TRANSITION) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte it->sbd_it_ua_conditions &=
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte ~SBD_UA_ACCESS_STATE_TRANSITION;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte saa = STMF_SAA_LU_NO_ACCESS_TRANSITION;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte it->sbd_it_ua_conditions = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte saa = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (saa) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, saa);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 = task->task_cdb[0];
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb1 = task->task_cdb[1];
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_STANDBY) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (cdb0 != SCMD_INQUIRY &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_MODE_SENSE &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_MODE_SENSE_G1 &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_MODE_SELECT &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_MODE_SELECT_G1 &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_RESERVE &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_RELEASE &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_PERSISTENT_RESERVE_OUT &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_PERSISTENT_RESERVE_IN &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte cdb0 != SCMD_REQUEST_SENSE &&
8b4eb90786a57fdbd4d997b62d0dba680b3310bfJohn Forte cdb0 != SCMD_READ_CAPACITY &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_TEST_UNIT_READY &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_START_STOP &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_READ &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_READ_G1 &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_READ_G4 &&
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte cdb0 != SCMD_READ_G5 &&
8b4eb90786a57fdbd4d997b62d0dba680b3310bfJohn Forte !(cdb0 == SCMD_SVC_ACTION_IN_G4 &&
8b4eb90786a57fdbd4d997b62d0dba680b3310bfJohn Forte cdb1 == SSVC_ACTION_READ_CAPACITY_G4) &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte !(cdb0 == SCMD_MAINTENANCE_IN &&
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte (cdb1 & 0x1F) == 0x05) &&
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte !(cdb0 == SCMD_MAINTENANCE_IN &&
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (cdb1 & 0x1F) == 0x0A)) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STMF_SAA_LU_NO_ACCESS_STANDBY);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte return;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /*
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * is this a short write?
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if so, we'll need to wait until we have the buffer
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * before proxying the command
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte switch (cdb0) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte case SCMD_MODE_SELECT:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte case SCMD_MODE_SELECT_G1:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte case SCMD_PERSISTENT_RESERVE_OUT:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte break;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte default:
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte st_ret = stmf_proxy_scsi_cmd(task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte initial_dbuf);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (st_ret != STMF_SUCCESS) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_scsilib_send_status(task,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STATUS_CHECK,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte STMF_SAA_LU_NO_ACCESS_UNAVAIL);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte return;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 = task->task_cdb[0] & 0x1F;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb0 == SCMD_READ) || (cdb0 == SCMD_WRITE)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_additional_flags & TASK_AF_PORT_LOAD_HIGH) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_QFULL, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_READ) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_write(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 = task->task_cdb[0];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb1 = task->task_cdb[1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_INQUIRY) { /* Inquiry */
2f624233c43c1f4fe0d930648d6ece6fffe7aa49Nattuvetty Bhavyan sbd_handle_inquiry(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_PERSISTENT_RESERVE_OUT) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_pgr_out_cmd(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_PERSISTENT_RESERVE_IN) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_pgr_in_cmd(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_RELEASE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not owner don't release it, just return good */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it->sbd_it_session_id !=
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_rs_owner_session_id) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_flags &= ~SBD_IT_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_RESERVE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb1) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_LU_HAS_SCSI2_RESERVATION) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* If not owner, return conflict status */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (it->sbd_it_session_id !=
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_rs_owner_session_id) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STATUS_RESERVATION_CONFLICT, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags |= SL_LU_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto it->sbd_it_flags |= SBD_IT_HAS_SCSI2_RESERVATION;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_rs_owner_session_id = it->sbd_it_session_id;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_REQUEST_SENSE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * LU provider needs to store unretrieved sense data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (e.g. after power-on/reset). For now, we'll just
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * return good status with no sense.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((cdb1 & ~1) || task->task_cdb[2] || task->task_cdb[3] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[5]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /* Report Target Port Groups */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb0 == SCMD_MAINTENANCE_IN) &&
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((cdb1 & 0x1F) == 0x0A)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_handle_report_tpgs(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte /* Report Identifying Information */
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte if ((cdb0 == SCMD_MAINTENANCE_IN) &&
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte ((cdb1 & 0x1F) == 0x05)) {
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte sbd_handle_identifying_info(task, initial_dbuf);
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte return;
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte }
6e4cf8b7f9c18709d8eae64c8185a09664a43ef2John Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_START_STOP) { /* Start stop */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_cmd_xfer_length = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_cdb[4] & 0xFC) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (task->task_cdb[4] & 2) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_CHECK,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto STMF_SAA_INVALID_FIELD_IN_CDB);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb0 == SCMD_MODE_SENSE) || (cdb0 == SCMD_MODE_SENSE_G1)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint8_t *p;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto p = kmem_zalloc(512, KM_SLEEP);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_mode_sense(task, initial_dbuf, p);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto kmem_free(p, 512);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((cdb0 == SCMD_MODE_SELECT) || (cdb0 == SCMD_MODE_SELECT_G1)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_mode_select(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald if ((cdb0 == SCMD_UNMAP) && (sl->sl_flags & SL_UNMAP_ENABLED)) {
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald sbd_handle_unmap(task, initial_dbuf);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((cdb0 == SCMD_WRITE_SAME_G4) || (cdb0 == SCMD_WRITE_SAME_G1)) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_handle_write_same(task, initial_dbuf);
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald return;
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald }
b77b9231da168bb31490f65bf2697f6031b7f601Dan McDonald
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_TEST_UNIT_READY) { /* Test unit ready */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_READ_CAPACITY) { /* Read Capacity */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_read_capacity(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (cdb0 == SCMD_SVC_ACTION_IN_G4) { /* Read Capacity or read long */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb1 == SSVC_ACTION_READ_CAPACITY_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_read_capacity(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /*
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * } else if (cdb1 == SSVC_ACTION_READ_LONG_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * sbd_handle_read(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /*
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * if (cdb0 == SCMD_SVC_ACTION_OUT_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * if (cdb1 == SSVC_ACTION_WRITE_LONG_G4) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * sbd_handle_write(task, initial_dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * return;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (cdb0 == SCMD_VERIFY) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto /*
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto * Something more likely needs to be done here.
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto */
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (cdb0 == SCMD_SYNCHRONIZE_CACHE ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cdb0 == SCMD_SYNCHRONIZE_CACHE_G4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_sync_cache(task, initial_dbuf);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita /*
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Write and Verify use the same path as write, but don't clutter the
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * performance path above with checking for write_verify opcodes. We
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * rely on zfs's integrity checks for the "Verify" part of Write &
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Verify. (Even if we did a read to "verify" we'd merely be reading
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * cache, not actual media.)
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * Therefore we
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * a) only support this if sbd_is_zvol, and
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * b) run the IO through the normal write path with a forced
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita * sbd_flush_data_cache at the end.
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita */
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita if ((sl->sl_flags & SL_ZFS_META) && (
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY ||
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY_G4 ||
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita cdb0 == SCMD_WRITE_VERIFY_G5)) {
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita sbd_handle_write(task, initial_dbuf);
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita return;
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita }
309bed43992ade65fbe1f15ef7a5e800545915f2Charles Binford - Sun Microsystems - Wichita
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_OPCODE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_dbuf_xfer_done(struct scsi_task *task, struct stmf_data_buf *dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (dbuf->db_flags & DB_LU_DATA_BUF) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore /*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * Buffers passed in from the LU always complete
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * even if the task is no longer active.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(scmd);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore switch (scmd->cmd_type) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case (SBD_CMD_SCSI_READ):
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_handle_sgl_read_xfer_completion(task, scmd, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore case (SBD_CMD_SCSI_WRITE):
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_handle_sgl_write_xfer_completion(task, scmd, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore default:
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_PANIC, "Unknown cmd type, task = %p",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore (void *)task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore break;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore return;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((scmd == NULL) || ((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0))
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto switch (scmd->cmd_type) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (SBD_CMD_SCSI_READ):
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_read_xfer_completion(task, scmd, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (SBD_CMD_SCSI_WRITE):
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if ((task->task_cdb[0] == SCMD_WRITE_SAME_G1) ||
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald (task->task_cdb[0] == SCMD_WRITE_SAME_G4)) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_handle_write_same_xfer_completion(task, scmd, dbuf,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald 1);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald } else {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald sbd_handle_write_xfer_completion(task, scmd, dbuf, 1);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (SBD_CMD_SMALL_READ):
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_handle_short_read_xfer_completion(task, scmd, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto case (SBD_CMD_SMALL_WRITE):
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_handle_short_write_xfer_completion(task, dbuf);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto default:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "Unknown cmd type, task = %p", (void *)task);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_send_status_done(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC,
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto "sbd_send_status_done: this should not have been called");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_task_free(struct scsi_task *task)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_PANIC, "cmd is active, task = %p",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void *)task);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(scmd, sizeof (sbd_cmd_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Aborts are synchronus w.r.t. I/O AND
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * All the I/O which SBD does is synchronous AND
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Everything within a task is single threaded.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IT MEANS
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If this function is called, we are doing nothing with this task
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * inside of sbd module.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_abort(struct stmf_lu *lu, int abort_cmd, void *arg, uint32_t flags)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scsi_task_t *task;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (abort_cmd == STMF_LU_RESET_STATE) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (sbd_lu_reset_state(lu));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (abort_cmd == STMF_LU_ITL_HANDLE_REMOVED) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_check_and_clear_scsi2_reservation(sl, (sbd_it_data_t *)arg);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_remove_it_handle(sl, (sbd_it_data_t *)arg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT(abort_cmd == STMF_LU_ABORT_TASK);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task = (scsi_task_t *)arg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_lu_private) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (scmd->flags & SBD_SCSI_CMD_ACTIVE) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald if (scmd->flags & SBD_SCSI_CMD_TRANS_DATA) {
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald kmem_free(scmd->trans_data,
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->trans_data_len);
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald scmd->flags &= ~SBD_SCSI_CMD_TRANS_DATA;
6140ef003e4253c1c1f0b9c100687487e4f1954bDan McDonald }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte scmd->flags &= ~SBD_SCSI_CMD_ACTIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_ABORT_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_NOT_FOUND);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore/*
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * This function is called during task clean-up if the
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * DB_LU_FLAG is set on the dbuf. This should only be called for
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore * abort processing after sbd_abort has been called for the task.
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore */
3fb517f786391b507780c78aabb8d98bfea9efe9James Moorevoid
3fb517f786391b507780c78aabb8d98bfea9efe9James Mooresbd_dbuf_free(struct scsi_task *task, struct stmf_data_buf *dbuf)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore{
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_cmd_t *scmd = (sbd_cmd_t *)task->task_lu_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(dbuf->db_lu_private);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(scmd && scmd->nbufs > 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT((scmd->flags & SBD_SCSI_CMD_ACTIVE) == 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(dbuf->db_flags & DB_LU_DATA_BUF);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT(task->task_additional_flags & TASK_AF_ACCEPT_LU_DBUF);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore ASSERT((curthread->t_flag & T_INTR_THREAD) == 0);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (scmd->cmd_type == SBD_CMD_SCSI_READ) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_read_bufs(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else if (scmd->cmd_type == SBD_CMD_SCSI_WRITE) {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore sbd_zvol_rele_write_bufs_abort(sl, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore } else {
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore cmn_err(CE_PANIC, "Unknown cmd type %d, task = %p",
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore scmd->cmd_type, (void *)task);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore }
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore if (--scmd->nbufs == 0)
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore rw_exit(&sl->sl_access_state_lock);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_teardown_dbuf(task, dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore stmf_free(dbuf);
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore}
3fb517f786391b507780c78aabb8d98bfea9efe9James Moore
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortevoid
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_ctl(struct stmf_lu *lu, int cmd, void *arg)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_change_status_t st;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ASSERT((cmd == STMF_CMD_LU_ONLINE) ||
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto (cmd == STMF_CMD_LU_OFFLINE) ||
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto (cmd == STMF_ACK_LU_ONLINE_COMPLETE) ||
1b7fc709228029b3f29f1c3de6d817a476f7c583tim szeto (cmd == STMF_ACK_LU_OFFLINE_COMPLETE));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_SUCCESS;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_additional_info = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte switch (cmd) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_CMD_LU_ONLINE:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_state == STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_ALREADY;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto else if (sl->sl_state != STMF_STATE_OFFLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_FAILURE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status == STMF_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_state = STMF_STATE_ONLINE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_state_not_acked = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_ONLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_CMD_LU_OFFLINE:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_state == STMF_STATE_OFFLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_ALREADY;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto else if (sl->sl_state != STMF_STATE_ONLINE)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte st.st_completion_status = STMF_FAILURE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (st.st_completion_status == STMF_SUCCESS) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~(SL_MEDIUM_REMOVAL_PREVENTED |
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto SL_LU_HAS_SCSI2_RESERVATION);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_state = STMF_STATE_OFFLINE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_state_not_acked = 1;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_pgr_reset(sl);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) stmf_ctl(STMF_CMD_LU_OFFLINE_COMPLETE, lu, &st);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_ACK_LU_ONLINE_COMPLETE:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Fallthrough */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte case STMF_ACK_LU_OFFLINE_COMPLETE:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_state_not_acked = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte break;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_info(uint32_t cmd, stmf_lu_t *lu, void *arg, uint8_t *buf,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto uint32_t *bufsizep)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_NOT_SUPPORTED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestmf_status_t
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_lu_reset_state(stmf_lu_t *lu)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_ACTIVE) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (void) sbd_wcd_set(1, sl);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (sl->sl_access_state == SBD_LU_ACTIVE) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (void) sbd_wcd_set(0, sl);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte sbd_pgr_reset(sl);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_check_and_clear_scsi2_reservation(sl, NULL);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (stmf_deregister_all_lu_itl_handles(lu) != STMF_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_FAILURE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (STMF_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_status_t
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetosbd_flush_data_cache(sbd_lu_t *sl, int fsync_done)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto int r = 0;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto int ret;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (fsync_done)
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto goto over_fsync;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((sl->sl_data_vtype == VREG) || (sl->sl_data_vtype == VBLK)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (VOP_FSYNC(sl->sl_data_vp, FSYNC, kcred, NULL))
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return (SBD_FAILURE);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szetoover_fsync:
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (((sl->sl_data_vtype == VCHR) || (sl->sl_data_vtype == VBLK)) &&
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ((sl->sl_flags & SL_NO_DATA_DKIOFLUSH) == 0)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto ret = VOP_IOCTL(sl->sl_data_vp, DKIOCFLUSHWRITECACHE, NULL,
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto FKIOCTL, kcred, &r, NULL);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((ret == ENOTTY) || (ret == ENOTSUP)) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_enter(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sl->sl_flags |= SL_NO_DATA_DKIOFLUSH;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto mutex_exit(&sl->sl_lock);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto } else if (ret != 0) {
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return (SBD_FAILURE);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto }
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto return (SBD_SUCCESS);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto}
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/* ARGSUSED */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesbd_handle_sync_cache(struct scsi_task *task,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct stmf_data_buf *initial_dbuf)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint64_t lba, laddr;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sbd_status_t sret;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int is_g4 = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int immed;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto task->task_cmd_xfer_length = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine if this is a 10 or 16 byte CDB
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (task->task_cdb[0] == SCMD_SYNCHRONIZE_CACHE_G4)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte is_g4 = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determine other requested parameters
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * We don't have a non-volatile cache, so don't care about SYNC_NV.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Do not support the IMMED bit.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte immed = (task->task_cdb[1] & 0x02);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (immed) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check to be sure we're not being asked to sync an LBA
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * that is out of range. While checking, verify reserved fields.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (is_g4) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[14] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[15]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI64(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI32(&task->task_cdb[10], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((task->task_cdb[1] & 0xf9) || task->task_cdb[6] ||
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte task->task_cdb[9]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_INVALID_FIELD_IN_CDB);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lba = READ_SCSI32(&task->task_cdb[2], uint64_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = READ_SCSI16(&task->task_cdb[7], uint32_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto laddr = lba << sl->sl_data_blocksize_shift;
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto len <<= sl->sl_data_blocksize_shift;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if ((laddr + (uint64_t)len) > sl->sl_lu_size) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_LBA_OUT_OF_RANGE);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto sret = sbd_flush_data_cache(sl, 0);
8fe960854f0d52e2e8a80ba68e8621a5ac6a866dtim szeto if (sret != SBD_SUCCESS) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_CHECK,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte STMF_SAA_WRITE_ERROR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte stmf_scsilib_send_status(task, STATUS_GOOD, 0);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}