Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bced1373 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (32 commits)
  [SCSI] aacraid: prevent panic on adapter resource failure
  [SCSI] aha152x: use data accessors and !use_sg cleanup
  [SCSI] aha152x: Fix check_condition code-path
  [SCSI] aha152x: Clean Reset path
  [SCSI] aha152x: preliminary fixes and some comments
  [SCSI] aha152x: use bounce buffer
  [SCSI] aha152x: fix debug mode symbol conflict
  [SCSI] sd: disentangle barriers in SCSI
  [SCSI] lpfc : scsi command accessor fix for 8.2.2
  [SCSI] qlogicpti: Some cosmetic changes
  [SCSI] lpfc 8.2.2 : Change version number to 8.2.2
  [SCSI] lpfc 8.2.2 : Style cleanups
  [SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
  [SCSI] lpfc 8.2.2 : Miscellaneous management and logging mods
  [SCSI] lpfc 8.2.2 : Rework the lpfc_printf_log() macro
  [SCSI] lpfc 8.2.2 : Attribute and Parameter splits for vport and physical port
  [SCSI] lpfc 8.2.2 : Fix locking around HBA's port_list
  [SCSI] lpfc 8.2.2 : Error messages and debugfs updates
  [SCSI] initialize shost_data to zero
  [SCSI] mptsas: add SMP passthrough support via bsg
  ...
parents 21f16289 2b053729
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
/*
 * bsg.c - block layer implementation of the sg v3 interface
 * bsg.c - block layer implementation of the sg v4 interface
 *
 * Copyright (C) 2004 Jens Axboe <axboe@suse.de> SUSE Labs
 * Copyright (C) 2004 Peter M. Jones <pjones@redhat.com>
@@ -421,7 +421,6 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
	hdr->info = 0;
	if (hdr->device_status || hdr->transport_status || hdr->driver_status)
		hdr->info |= SG_INFO_CHECK;
	hdr->din_resid = rq->data_len;
	hdr->response_len = 0;

	if (rq->sense_len && hdr->response) {
@@ -437,9 +436,14 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
	}

	if (rq->next_rq) {
		hdr->dout_resid = rq->data_len;
		hdr->din_resid = rq->next_rq->data_len;
		blk_rq_unmap_user(bidi_bio);
		blk_put_request(rq->next_rq);
	}
	} else if (rq_data_dir(rq) == READ)
		hdr->din_resid = rq->data_len;
	else
		hdr->dout_resid = rq->data_len;

	blk_rq_unmap_user(bio);
	blk_put_request(rq);
+16 −1
Original line number Diff line number Diff line
@@ -88,7 +88,9 @@ module_param(mpt_channel_mapping, int, 0);
MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");

static int mpt_debug_level;
module_param(mpt_debug_level, int, 0);
static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
		  &mpt_debug_level, 0600);
MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");

#ifdef MFCNT
@@ -220,6 +222,19 @@ pci_enable_io_access(struct pci_dev *pdev)
	pci_write_config_word(pdev, PCI_COMMAND, command_reg);
}

static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
{
	int ret = param_set_int(val, kp);
	MPT_ADAPTER *ioc;

	if (ret)
		return ret;

	list_for_each_entry(ioc, &ioc_list, list)
		ioc->debug_level = mpt_debug_level;
	return 0;
}

/*
 *  Process turbo (context) reply...
 */
+126 −0
Original line number Diff line number Diff line
@@ -1312,11 +1312,137 @@ mptsas_get_bay_identifier(struct sas_rphy *rphy)
	return rc;
}

static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
			      struct request *req)
{
	MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
	MPT_FRAME_HDR *mf;
	SmpPassthroughRequest_t *smpreq;
	struct request *rsp = req->next_rq;
	int ret;
	int flagsLength;
	unsigned long timeleft;
	char *psge;
	dma_addr_t dma_addr_in = 0;
	dma_addr_t dma_addr_out = 0;
	u64 sas_address = 0;

	if (!rsp) {
		printk(KERN_ERR "%s: the smp response space is missing\n",
		       __FUNCTION__);
		return -EINVAL;
	}

	/* do we need to support multiple segments? */
	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
		printk(KERN_ERR "%s: multiple segments req %u %u, rsp %u %u\n",
		       __FUNCTION__, req->bio->bi_vcnt, req->data_len,
		       rsp->bio->bi_vcnt, rsp->data_len);
		return -EINVAL;
	}

	ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
	if (ret)
		goto out;

	mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
	if (!mf) {
		ret = -ENOMEM;
		goto out_unlock;
	}

	smpreq = (SmpPassthroughRequest_t *)mf;
	memset(smpreq, 0, sizeof(*smpreq));

	smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
	smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;

	if (rphy)
		sas_address = rphy->identify.sas_address;
	else {
		struct mptsas_portinfo *port_info;

		mutex_lock(&ioc->sas_topology_mutex);
		port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
		if (port_info && port_info->phy_info)
			sas_address =
				port_info->phy_info[0].phy->identify.sas_address;
		mutex_unlock(&ioc->sas_topology_mutex);
	}

	*((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);

	psge = (char *)
		(((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));

	/* request */
	flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
		       MPI_SGE_FLAGS_END_OF_BUFFER |
		       MPI_SGE_FLAGS_DIRECTION |
		       mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
	flagsLength |= (req->data_len - 4);

	dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
				      req->data_len, PCI_DMA_BIDIRECTIONAL);
	if (!dma_addr_out)
		goto put_mf;
	mpt_add_sge(psge, flagsLength, dma_addr_out);
	psge += (sizeof(u32) + sizeof(dma_addr_t));

	/* response */
	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
	flagsLength |= rsp->data_len + 4;
	dma_addr_in =  pci_map_single(ioc->pcidev, bio_data(rsp->bio),
				      rsp->data_len, PCI_DMA_BIDIRECTIONAL);
	if (!dma_addr_in)
		goto unmap;
	mpt_add_sge(psge, flagsLength, dma_addr_in);

	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);

	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
	if (!timeleft) {
		printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__);
		/* On timeout reset the board */
		mpt_HardResetHandler(ioc, CAN_SLEEP);
		ret = -ETIMEDOUT;
		goto unmap;
	}
	mf = NULL;

	if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
		SmpPassthroughReply_t *smprep;

		smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
		memcpy(req->sense, smprep, sizeof(*smprep));
		req->sense_len = sizeof(*smprep);
	} else {
		printk(KERN_ERR "%s: smp passthru reply failed to be returned\n",
		       __FUNCTION__);
		ret = -ENXIO;
	}
unmap:
	if (dma_addr_out)
		pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
				 PCI_DMA_BIDIRECTIONAL);
	if (dma_addr_in)
		pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
				 PCI_DMA_BIDIRECTIONAL);
put_mf:
	if (mf)
		mpt_free_msg_frame(ioc, mf);
out_unlock:
	mutex_unlock(&ioc->sas_mgmt.mutex);
out:
	return ret;
}

static struct sas_function_template mptsas_transport_functions = {
	.get_linkerrors		= mptsas_get_linkerrors,
	.get_enclosure_identifier = mptsas_get_enclosure_identifier,
	.get_bay_identifier	= mptsas_get_bay_identifier,
	.phy_reset		= mptsas_phy_reset,
	.smp_handler		= mptsas_smp_handler,
};

static struct scsi_transport_template *mptsas_transport_template;
+3 −2
Original line number Diff line number Diff line
@@ -4154,8 +4154,9 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
			      fcp_rsp_iu->fcp_resid,
			      (int) zfcp_get_fcp_dl(fcp_cmnd_iu));

		scpnt->resid = fcp_rsp_iu->fcp_resid;
		if (scpnt->request_bufflen - scpnt->resid < scpnt->underflow)
		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
		    scpnt->underflow)
			set_host_byte(&scpnt->result, DID_ERROR);
	}

+6 −35
Original line number Diff line number Diff line
@@ -36,8 +36,6 @@ static void zfcp_qdio_sbale_fill
	(struct zfcp_fsf_req *, unsigned long, void *, int);
static int zfcp_qdio_sbals_from_segment
	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long);
static int zfcp_qdio_sbals_from_buffer
	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int);

static qdio_handler_t zfcp_qdio_request_handler;
static qdio_handler_t zfcp_qdio_response_handler;
@@ -631,28 +629,6 @@ zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
}


/**
 * zfcp_qdio_sbals_from_buffer - fill SBALs from buffer
 * @fsf_req: request to be processed
 * @sbtype: SBALE flags
 * @buffer: data buffer
 * @length: length of buffer
 * @max_sbals: upper bound for number of SBALs to be used
 */
static int
zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
			    void *buffer, unsigned long length, int max_sbals)
{
	struct scatterlist sg_segment;

	zfcp_address_to_sg(buffer, &sg_segment);
	sg_segment.length = length;

	return zfcp_qdio_sbals_from_sg(fsf_req, sbtype, &sg_segment, 1,
                                       max_sbals);
}


/**
 * zfcp_qdio_sbals_from_scsicmnd - fill SBALs from scsi command
 * @fsf_req: request to be processed
@@ -664,18 +640,13 @@ int
zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
			      unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
{
	if (scsi_cmnd->use_sg) {
	if (scsi_sg_count(scsi_cmnd))
		return zfcp_qdio_sbals_from_sg(fsf_req,	sbtype,
                                               (struct scatterlist *)
                                               scsi_cmnd->request_buffer,
                                               scsi_cmnd->use_sg,
					       scsi_sglist(scsi_cmnd),
					       scsi_sg_count(scsi_cmnd),
					       ZFCP_MAX_SBALS_PER_REQ);
	} else {
                return zfcp_qdio_sbals_from_buffer(fsf_req, sbtype,
                                                   scsi_cmnd->request_buffer,
                                                   scsi_cmnd->request_bufflen,
                                                   ZFCP_MAX_SBALS_PER_REQ);
	}
	else
		return 0;
}

/**
Loading