GIT 5181afc2c437331a07d3763e5058209b6bf1f444 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git commit Author: FUJITA Tomonori Date: Wed Jul 11 15:08:24 2007 +0900 [SCSI] tgt: convert ibmvstgt to use transport tsk_mgmt_response callback This converts ibmvstgt to use transport tsk_mgmt_response callback. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 65838969101e18e90e206e3c334248b063c63e7a Author: FUJITA Tomonori Date: Wed Jul 11 15:08:22 2007 +0900 [SCSI] tgt: move tsk_mgmt_response callback to transport class This moves tsk_mgmt_response callback in struct scsi_host_template to struct scsi_transport_template since struct scsi_transport_template is more suitable for the task management stuff. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 405026f19ae0ba815d6518570b58320e3f4efbab Author: FUJITA Tomonori Date: Wed Jul 11 15:08:21 2007 +0900 [SCSI] tgt: convert libsrp and ibmvstgt to use srp_transport This converts libsrp and ibmvstgt to use srp transport. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Acked-by: Brian King Signed-off-by: James Bottomley commit c4cf89926d437c1889e113c406c276b147c00288 Author: FUJITA Tomonori Date: Wed Jul 11 15:08:19 2007 +0900 [SCSI] srp_transport: add target driver support This adds minimum target driver support: - srp_rport_{add,del} calls scsi_tgt_it_nexus_{create,destroy} for target drivers. - add a callback to notify target drivers of the nexus operation results to srp_function_template. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit a95b1b6b5364da73651d907d24a2e7bebc2f9f10 Author: FUJITA Tomonori Date: Wed Jul 11 15:08:17 2007 +0900 [SCSI] tgt: add I_T nexus support tgt uses scsi_host as I_T nexus. This works for ibmvstgt because it creates one scsi_host for one initiator. However, other target drivers don't work like that. This adds I_T nexus support, which enable one scsi_host to handle multiple initiators. New scsi_tgt_it_nexus_create/destroy functions are expected be called transport classes. For example, ibmvstgt creates an initiator remote port, then the srp transport calls tgt_it_nexus_create. tgt doesn't manages I_T nexus, instead it tells tgtd, user-space daemon, to create a new I_T nexus. On the receiving the response from tgtd, tgt calls shost->transportt->it_nexus_response. transports should notify a lld. The srp transport uses it_nexus_response callback in srp_function_template to do that. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit a6d82a7828371b40c9c15e6f11c19e43582a7548 Author: FUJITA Tomonori Date: Wed Jul 11 15:08:15 2007 +0900 [SCSI] transport_srp: add rport roles attribute This adds a 'roles' attribute to rport like transport_fc. The role can be initiator or target. That is, the initiator driver creates target remote ports and the target driver creates initiator remote ports. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit a9a86b427807407ba1eb5d81e9ed36e64d2fe9b1 Author: FUJITA Tomonori Date: Wed Jun 27 16:33:12 2007 +0900 [SCSI] ib_srp: convert to use the srp transport class This converts ib_srp to use the srp transport class. I don't have ib hardware so I've not tested this patch. Signed-off-by: FUJITA Tomonori Cc: Roland Dreier Signed-off-by: James Bottomley commit 92366011049afdb5a2b7f432c896a82144fe534f Author: FUJITA Tomonori Date: Wed Jun 27 16:32:50 2007 +0900 [SCSI] ibmvscsi: convert to use the srp transport class This converts ibmvscsi to use the srp transport class. Signed-off-by: FUJITA Tomonori Acked-by: Brian King Signed-off-by: James Bottomley commit 0de0bf68c19e50f60c9d0bc31fca3eb423e84ee9 Author: FUJITA Tomonori Date: Wed Jun 27 16:32:39 2007 +0900 [SCSI] add srp transport class This adds srp transport class that works with ib_srp and ibmvscsi. It creates only /sys/class/{srp_host,srp_remote_ports} and srp_remote_ports has only "port_id" attribute. viola:/sys/class/srp_remote_ports/port-0:1# ls device port_id subsystem uevent viola:/sys/class/srp_remote_ports/port-0:1# cat port_id 4c:49:4e:55:58:20:56:49:4f:00:00:00:00:00:00:00 Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley commit 4385eea6c09dcc157c5de86f8ff7866566b82b1d Author: Moore, Eric Date: Mon Jul 30 11:10:07 2007 -0600 [SCSI] mptsas: add SMP passthrough support via bsg This patch adds support for SAS Management Protocol (SMP) passthrough support via bsg. Signed-off-by: FUJITA Tomonori Acked-by: Eric Moore Signed-off-by: James Bottomley commit 96d32215d433c38f258159b8735f98158f6a2575 Author: David Miller Date: Mon Jul 30 16:19:20 2007 -0700 [SCSI] ESP: Revert ESP_BUS_TIMEOUT back down to 250 This reverts d73f5222a618a91452d41c29f5996ce3d9c63673 The bug that made us increase ESP_BUS_TIMEOUT to 275 turned out to be a memset bug on 32-bit sparc. It is better to put this back at the correct timeout value than to leave it increased when there is no reason for doing so. Signed-off-by: David S. Miller Signed-off-by: James Bottomley commit 55d9fcf57ba5ec427544fca7abc335cf3da78160 Author: Matthew Wilcox Date: Mon Jul 30 15:19:18 2007 -0600 [SCSI] dpt_i2o: convert to SCSI hotplug model - Delete refereces to HOSTS_C - Switch to module_init/module_exit instead of detect/release - Don't pass around the host template and rename it to adpt_template - Switch from scsi_register/scsi_unregister to scsi_host_alloc, scsi_add_host, scsi_scan_host and scsi_host_put. Signed-off-by: Matthew Wilcox Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley commit 53772a2cb40748ea0b26db8101d632ddb3875b51 Author: Seokmann Ju Date: Mon Jul 30 11:01:07 2007 -0700 [SCSI] qla2xxx: fix panic caused by previous patch - this patch will fix a panic caused by omitted memory allocation for the nvram. Signed-off-by: Seokmann Ju Signed-off-by: James Bottomley commit 142009a3df39ecd4e96601d8bdabbe0c5f6e2f4e Author: James Bottomley Date: Mon Jul 30 09:52:25 2007 -0500 [SCSI] aic7xxx: cap maxsync according to correct card limits Not doing this can cause cards less than u160 capable to send out PPR offers to devices they can't then deliver on ... causing some devices to get a bit confused. Fix by capping the start syncrate at the appropriate level according to the card capabilities. Signed-off-by: James Bottomley commit 28f85009e0cf6a5232cd285131eac3dfe26d9e3a Author: Matthias Kaehlcke Date: Sun Jul 29 23:38:15 2007 +0200 [SCSI] st: Use mutex instead of semaphore The SCSI Tape driver uses a semaphore as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Acked-by: Kai Makisara Signed-off-by: James Bottomley commit 0c6a89ba640d28e1dcd7fd1a217d2cfb92ae4953 Author: FUJITA Tomonori Date: Sun Jul 29 23:00:46 2007 +0900 [SCSI] bsg: update sg_io_v4 structure This updates sg_io_v4 structure (based on Doug's RFC, release 1.3). The major changes are: - add dout_resid field - increase tag size to 64 bits to comply with SAM-4 and SRP - add dout_iovec_count and din_iovec_count dout_iovec_count and din_iovec_count aren't supported now. I'm not sure whether they will be supported or not but they were added for the possible future changes. Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley commit db47c2d8d98a76083a88ec53f44cc74c48dfd1e8 Author: James Bottomley Date: Sat Jul 28 13:40:21 2007 -0400 [SCSI] mpt fusion: make logging a global sysfs parameter Wire up the mpt_debug_level module parameter so you can write to the /sys/module/mptbase/parameters/mpt_debug_level and have it take effect in every ioc. Acked-by: "Moore, Eric" Signed-off-by: James Bottomley commit 15617ff66c777b008e170f9c5b0e8a9854937648 Author: James Bottomley Date: Sat Jul 28 11:07:36 2007 -0400 [SCSI] libsas: fix build dependencies on libata If you have the libsas with ATA support, it needs libata to function. The problem is that if you compile in libsas, you can't build libata as a module (however, vice versa you can). Signed-off-by: James Bottomley commit 8e9a8a0d56c5d9d87adbefbbc8c8728c529fd95a Author: Jeff Garzik Date: Tue Jul 17 05:25:17 2007 -0400 [SCSI] gdth: remove redundant PCI stuff This patch * removes struct members that duplicate pci_dev members * replaces ha->stype usage with ha->pdev->device usage where feasible Signed-off-by: Jeff Garzik Acked-by: Christoph Hellwig Acked-by: Achim Leubner Signed-off-by: James Bottomley commit 7603e02eac309626c0153ebddf277253ea7fe0e0 Author: FUJITA Tomonori Date: Mon Jul 23 09:28:40 2007 +0900 [SCSI] ibmvscsi: use shost_priv Signed-off-by: FUJITA Tomonori Acked-by: Brian King Signed-off-by: James Bottomley commit ed3a3633b798a15281f9c9a89a7e74d4bdd02ebe Author: FUJITA Tomonori Date: Mon Jul 23 09:28:39 2007 +0900 [SCSI] ibmvscsi: remove unnecessary map_sg check No need to check use_sg since sg_tablesize is set appropriately in the scsi host template. Brian King's patch (2a7309372fe56ae46c499b772d811ad31c501dd9) did this cleanup but the data buffer accessors patch (written before the patch and merged after it) restored the check. Signed-off-by: FUJITA Tomonori Acked-by: Brian King Signed-off-by: James Bottomley commit 7936a892e72498a05b9a7fb1fec6506d65c8e435 Author: FUJITA Tomonori Date: Sun Jul 29 16:46:28 2007 +0900 [SCSI] zfcp: convert to use the data buffer accessors - remove the unnecessary map_single path. - convert to use the new accessors for the sg lists and the parameters. Signed-off-by: FUJITA Tomonori Acked-by: Swen Schillig Signed-off-by: James Bottomley block/bsg.c | 10 + drivers/infiniband/ulp/srp/Kconfig | 1 drivers/infiniband/ulp/srp/ib_srp.c | 28 +++ drivers/message/fusion/mptbase.c | 17 +- drivers/message/fusion/mptsas.c | 126 ++++++++++++ drivers/s390/scsi/zfcp_fsf.c | 5 drivers/s390/scsi/zfcp_qdio.c | 41 +--- drivers/scsi/Kconfig | 10 + drivers/scsi/Makefile | 1 drivers/scsi/aic7xxx/aic7xxx_core.c | 22 ++ drivers/scsi/dpt_i2o.c | 132 +++++++----- drivers/scsi/dpti.h | 9 - drivers/scsi/esp_scsi.h | 2 drivers/scsi/gdth.c | 48 ++-- drivers/scsi/gdth.h | 6 - drivers/scsi/ibmvscsi/ibmvscsi.c | 74 ++++--- drivers/scsi/ibmvscsi/ibmvstgt.c | 60 +++++- drivers/scsi/libsas/Kconfig | 3 drivers/scsi/libsrp.c | 5 drivers/scsi/qla2xxx/qla_os.c | 14 + drivers/scsi/scsi_tgt_if.c | 42 ++++ drivers/scsi/scsi_tgt_lib.c | 83 ++++++-- drivers/scsi/scsi_tgt_priv.h | 22 +- drivers/scsi/scsi_transport_srp.c | 379 +++++++++++++++++++++++++++++++++++ drivers/scsi/st.c | 16 + drivers/scsi/st.h | 3 include/linux/bsg.h | 13 + include/scsi/libsrp.h | 2 include/scsi/scsi_host.h | 3 include/scsi/scsi_tgt.h | 8 - include/scsi/scsi_tgt_if.h | 35 ++- include/scsi/scsi_transport.h | 12 + include/scsi/scsi_transport_srp.h | 39 ++++ 33 files changed, 1034 insertions(+), 237 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index d60eee5..ed26468 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -1,5 +1,5 @@ /* - * 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 SUSE Labs * Copyright (C) 2004 Peter M. Jones @@ -421,7 +421,6 @@ static int blk_complete_sgv4_hdr_rq(stru 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(stru } 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); diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig index 3432dce..c74ee96 100644 --- a/drivers/infiniband/ulp/srp/Kconfig +++ b/drivers/infiniband/ulp/srp/Kconfig @@ -1,6 +1,7 @@ config INFINIBAND_SRP tristate "InfiniBand SCSI RDMA Protocol" depends on SCSI + select SCSI_SRP_ATTRS ---help--- Support for the SCSI RDMA Protocol over InfiniBand. This allows you to access storage devices that speak SRP over diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index f01ca18..e616c4f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -47,6 +47,7 @@ #include #include #include #include +#include #include @@ -90,6 +91,8 @@ static void srp_remove_one(struct ib_dev static void srp_completion(struct ib_cq *cq, void *target_ptr); static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event); +static struct scsi_transport_template *ib_srp_transport_template; + static struct ib_client srp_client = { .name = "srp", .add = srp_add_one, @@ -405,6 +408,7 @@ static void srp_remove_work(struct work_ list_del(&target->list); spin_unlock(&target->srp_host->target_lock); + srp_remove_host(target->scsi_host); scsi_remove_host(target->scsi_host); ib_destroy_cm_id(target->cm_id); srp_free_target_ib(target); @@ -1530,12 +1534,24 @@ static struct scsi_host_template srp_tem static int srp_add_target(struct srp_host *host, struct srp_target_port *target) { + struct srp_rport_identifiers ids; + struct srp_rport *rport; + sprintf(target->target_name, "SRP.T10:%016llX", (unsigned long long) be64_to_cpu(target->id_ext)); if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device)) return -ENODEV; + memcpy(ids.port_id, &target->id_ext, 8); + memcpy(ids.port_id + 8, &target->ioc_guid, 8); + ids.roles = SRP_RPORT_ROLE_TARGET; + rport = srp_rport_add(target->scsi_host, &ids); + if (IS_ERR(rport)) { + scsi_remove_host(target->scsi_host); + return PTR_ERR(rport); + } + spin_lock(&host->target_lock); list_add_tail(&target->list, &host->target_list); spin_unlock(&host->target_lock); @@ -1760,6 +1776,7 @@ static ssize_t srp_create_target(struct if (!target_host) return -ENOMEM; + target_host->transportt = ib_srp_transport_template; target_host->max_lun = SRP_MAX_LUN; target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; @@ -2039,10 +2056,18 @@ static void srp_remove_one(struct ib_dev kfree(srp_dev); } +static struct srp_function_template ib_srp_transport_functions = { +}; + static int __init srp_init_module(void) { int ret; + ib_srp_transport_template = + srp_attach_transport(&ib_srp_transport_functions); + if (!ib_srp_transport_template) + return -ENOMEM; + srp_template.sg_tablesize = srp_sg_tablesize; srp_max_iu_len = (sizeof (struct srp_cmd) + sizeof (struct srp_indirect_buf) + @@ -2051,6 +2076,7 @@ static int __init srp_init_module(void) ret = class_register(&srp_class); if (ret) { printk(KERN_ERR PFX "couldn't register class infiniband_srp\n"); + srp_release_transport(ib_srp_transport_template); return ret; } @@ -2059,6 +2085,7 @@ static int __init srp_init_module(void) ret = ib_register_client(&srp_client); if (ret) { printk(KERN_ERR PFX "couldn't register IB client\n"); + srp_release_transport(ib_srp_transport_template); ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); return ret; @@ -2072,6 +2099,7 @@ static void __exit srp_cleanup_module(vo ib_unregister_client(&srp_client); ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); + srp_release_transport(ib_srp_transport_template); } module_init(srp_init_module); diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index e866dac..414c109 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -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 *pde 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... */ diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 29add83..b9c69bf 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1312,11 +1312,137 @@ mptsas_get_bay_identifier(struct sas_rph 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; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b240800..9929997 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4154,8 +4154,9 @@ zfcp_fsf_send_fcp_command_task_handler(s 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); } diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index c408bad..81daa82 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -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; @@ -632,28 +630,6 @@ out: /** - * 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 * @sbtype: SBALE flags @@ -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, - 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); - } + scsi_sglist(scsi_cmnd), + scsi_sg_count(scsi_cmnd), + ZFCP_MAX_SBALS_PER_REQ); + else + return 0; } /** diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d2b3898..4562273 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -289,6 +289,13 @@ config SCSI_SAS_ATTRS source "drivers/scsi/libsas/Kconfig" +config SCSI_SRP_ATTRS + tristate "SRP Transport Attributes" + depends on SCSI && SCSI_TGT + help + If you wish to export transport-specific information about + each attached SRP device to sysfs, say Y. + endmenu menuconfig SCSI_LOWLEVEL @@ -832,6 +839,7 @@ config SCSI_IPS config SCSI_IBMVSCSI tristate "IBM Virtual SCSI support" depends on PPC_PSERIES || PPC_ISERIES + select SCSI_SRP_ATTRS help This is the IBM POWER Virtual SCSI Client @@ -840,7 +848,7 @@ config SCSI_IBMVSCSI config SCSI_IBMVSCSIS tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP + depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP && SCSI_SRP_ATTRS help This is the SRP target driver for IBM pSeries virtual environments. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 86a7ba7..6141389 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_tra obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ +obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 75733b0..f350b5e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -1701,7 +1701,16 @@ ahc_find_syncrate(struct ahc_softc *ahc, if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 && maxsync < AHC_SYNCRATE_ULTRA2) maxsync = AHC_SYNCRATE_ULTRA2; - + + /* Now set the maxsync based on the card capabilities + * DT is already done above */ + if ((ahc->features & (AHC_DT | AHC_ULTRA2)) == 0 + && maxsync < AHC_SYNCRATE_ULTRA) + maxsync = AHC_SYNCRATE_ULTRA; + if ((ahc->features & (AHC_DT | AHC_ULTRA2 | AHC_ULTRA)) == 0 + && maxsync < AHC_SYNCRATE_FAST) + maxsync = AHC_SYNCRATE_FAST; + for (syncrate = &ahc_syncrates[maxsync]; syncrate->rate != NULL; syncrate++) { @@ -1765,6 +1774,17 @@ ahc_find_period(struct ahc_softc *ahc, u else scsirate &= SXFR; + /* now set maxsync based on card capabilities */ + if ((ahc->features & AHC_DT) == 0 && maxsync < AHC_SYNCRATE_ULTRA2) + maxsync = AHC_SYNCRATE_ULTRA2; + if ((ahc->features & (AHC_DT | AHC_ULTRA2)) == 0 + && maxsync < AHC_SYNCRATE_ULTRA) + maxsync = AHC_SYNCRATE_ULTRA; + if ((ahc->features & (AHC_DT | AHC_ULTRA2 | AHC_ULTRA)) == 0 + && maxsync < AHC_SYNCRATE_FAST) + maxsync = AHC_SYNCRATE_FAST; + + syncrate = &ahc_syncrates[maxsync]; while (syncrate->rate != NULL) { diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 2e2362d..502732a 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -173,20 +173,20 @@ static struct pci_device_id dptids[] = { }; MODULE_DEVICE_TABLE(pci,dptids); -static int adpt_detect(struct scsi_host_template* sht) +static void adpt_exit(void); + +static int adpt_detect(void) { struct pci_dev *pDev = NULL; adpt_hba* pHba; - adpt_init(); - PINFO("Detecting Adaptec I2O RAID controllers...\n"); /* search for all Adatpec I2O RAID cards */ while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { if(pDev->device == PCI_DPT_DEVICE_ID || pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ - if(adpt_install_hba(sht, pDev) ){ + if(adpt_install_hba(pDev) ){ PERROR("Could not Init an I2O RAID device\n"); PERROR("Will not try to detect others.\n"); return hba_count-1; @@ -248,34 +248,33 @@ rebuild_sys_tab: } for (pHba = hba_chain; pHba; pHba = pHba->next) { - if( adpt_scsi_register(pHba,sht) < 0){ + if (adpt_scsi_register(pHba) < 0) { adpt_i2o_delete_hba(pHba); continue; } pHba->initialized = TRUE; pHba->state &= ~DPTI_STATE_RESET; + scsi_scan_host(pHba->host); } // Register our control device node // nodes will need to be created in /dev to access this // the nodes can not be created from within the driver if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { - adpt_i2o_sys_shutdown(); + adpt_exit(); return 0; } return hba_count; } -/* - * scsi_unregister will be called AFTER we return. - */ -static int adpt_release(struct Scsi_Host *host) +static int adpt_release(adpt_hba *pHba) { - adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; + struct Scsi_Host *shost = pHba->host; + scsi_remove_host(shost); // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); - scsi_unregister(host); + scsi_host_put(shost); return 0; } @@ -882,7 +881,7 @@ static int adpt_reboot_event(struct noti #endif -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) +static int adpt_install_hba(struct pci_dev* pDev) { adpt_hba* pHba = NULL; @@ -1031,8 +1030,6 @@ static void adpt_i2o_delete_hba(adpt_hba mutex_lock(&adpt_configuration_lock); - // scsi_unregister calls our adpt_release which - // does a quiese if(pHba->host){ free_irq(pHba->host->irq, pHba); } @@ -1084,17 +1081,6 @@ static void adpt_i2o_delete_hba(adpt_hba } -static int adpt_init(void) -{ - printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); -#ifdef REBOOT_NOTIFIER - register_reboot_notifier(&adpt_reboot_notifier); -#endif - - return 0; -} - - static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) { struct adpt_device* d; @@ -2180,37 +2166,6 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pH } -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) -{ - struct Scsi_Host *host = NULL; - - host = scsi_register(sht, sizeof(adpt_hba*)); - if (host == NULL) { - printk ("%s: scsi_register returned NULL\n",pHba->name); - return -1; - } - host->hostdata[0] = (unsigned long)pHba; - pHba->host = host; - - host->irq = pHba->pDev->irq; - /* no IO ports, so don't have to set host->io_port and - * host->n_io_port - */ - host->io_port = 0; - host->n_io_port = 0; - /* see comments in scsi_host.h */ - host->max_id = 16; - host->max_lun = 256; - host->max_channel = pHba->top_scsi_channel + 1; - host->cmd_per_lun = 1; - host->unique_id = (uint) pHba; - host->sg_tablesize = pHba->sg_tablesize; - host->can_queue = pHba->post_fifo_size; - - return 0; -} - - static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) { adpt_hba* pHba; @@ -3329,12 +3284,10 @@ static static void adpt_delay(int millis #endif -static struct scsi_host_template driver_template = { +static struct scsi_host_template adpt_template = { .name = "dpt_i2o", .proc_name = "dpt_i2o", .proc_info = adpt_proc_info, - .detect = adpt_detect, - .release = adpt_release, .info = adpt_info, .queuecommand = adpt_queue, .eh_abort_handler = adpt_abort, @@ -3348,5 +3301,62 @@ static struct scsi_host_template driver_ .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, }; -#include "scsi_module.c" + +static s32 adpt_scsi_register(adpt_hba* pHba) +{ + struct Scsi_Host *host; + + host = scsi_host_alloc(&adpt_template, sizeof(adpt_hba*)); + if (host == NULL) { + printk ("%s: scsi_host_alloc returned NULL\n",pHba->name); + return -1; + } + host->hostdata[0] = (unsigned long)pHba; + pHba->host = host; + + host->irq = pHba->pDev->irq; + /* no IO ports, so don't have to set host->io_port and + * host->n_io_port + */ + host->io_port = 0; + host->n_io_port = 0; + /* see comments in scsi_host.h */ + host->max_id = 16; + host->max_lun = 256; + host->max_channel = pHba->top_scsi_channel + 1; + host->cmd_per_lun = 1; + host->unique_id = (uint) pHba; + host->sg_tablesize = pHba->sg_tablesize; + host->can_queue = pHba->post_fifo_size; + + if (scsi_add_host(host, &pHba->pDev->dev)) { + scsi_host_put(host); + return -1; + } + + return 0; +} + +static int __init adpt_init(void) +{ + int count; + + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); +#ifdef REBOOT_NOTIFIER + register_reboot_notifier(&adpt_reboot_notifier); +#endif + + count = adpt_detect(); + + return count > 0 ? 0 : -ENODEV; +} + +static void __exit adpt_exit(void) +{ + while (hba_chain) + adpt_release(hba_chain); +} + +module_init(adpt_init); +module_exit(adpt_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index fd79068..0892f6c 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -28,11 +28,9 @@ #define MAX_FROM_IOP_MESSAGES (255) * SCSI interface function Prototypes */ -static int adpt_detect(struct scsi_host_template * sht); static int adpt_queue(struct scsi_cmnd * cmd, void (*cmdcomplete) (struct scsi_cmnd *)); static int adpt_abort(struct scsi_cmnd * cmd); static int adpt_reset(struct scsi_cmnd* cmd); -static int adpt_release(struct Scsi_Host *host); static int adpt_slave_configure(struct scsi_device *); static const char *adpt_info(struct Scsi_Host *pSHost); @@ -49,8 +47,6 @@ static int adpt_device_reset(struct scsi #define DPT_DRIVER_NAME "Adaptec I2O RAID" -#ifndef HOSTS_C - #include "dpt/sys_info.h" #include #include "dpt/dpti_i2o.h" @@ -289,7 +285,7 @@ static s32 adpt_i2o_init_outbound_q(adpt static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht); +static s32 adpt_scsi_register(adpt_hba* pHba); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); static s32 adpt_rescan(adpt_hba* pHba); @@ -299,7 +295,7 @@ static void adpt_i2o_delete_hba(adpt_hba static void adpt_inquiry(adpt_hba* pHba); static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; +static int adpt_install_hba(struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); static void adpt_i2o_post_wait_complete(u32, int); static int adpt_i2o_systab_send(adpt_hba* pHba); @@ -343,5 +339,4 @@ #define FW_DEBUG_FLAGS_OFFSET 4 #define FW_DEBUG_BLED_OFFSET 8 #define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01 -#endif /* !HOSTS_C */ #endif /* _DPT_H */ diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index 856e38b..d5576d5 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h @@ -220,7 +220,7 @@ #define ESP_CCF_F7 0x07 / #define ESP_BUSID_RESELID 0x10 #define ESP_BUSID_CTR32BIT 0x40 -#define ESP_BUS_TIMEOUT 275 /* In milli-seconds */ +#define ESP_BUS_TIMEOUT 250 /* In milli-seconds */ #define ESP_TIMEO_CONST 8192 #define ESP_NEG_DEFP(mhz, cfact) \ ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact))) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index d0b95ce..55e4d2d 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -902,11 +902,6 @@ static void __init gdth_search_dev(gdth_ return; /* GDT PCI controller found, resources are already in pdev */ pcistr[*cnt].pdev = pdev; - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - pcistr[*cnt].subdevice_id = pdev->subsystem_device; - pcistr[*cnt].bus = pdev->bus->number; - pcistr[*cnt].device_fn = pdev->devfn; pcistr[*cnt].irq = pdev->irq; base0 = pci_resource_flags(pdev, 0); base1 = pci_resource_flags(pdev, 1); @@ -926,7 +921,8 @@ static void __init gdth_search_dev(gdth_ pcistr[*cnt].io = pci_resource_start(pdev, 1); } TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), + pcistr[*cnt].pdev->bus->number, + PCI_SLOT(pcistr[*cnt].pdev->devfn), pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } @@ -946,20 +942,20 @@ static void __init gdth_sort_pci(gdth_pc changed = FALSE; for (i = 0; i < cnt-1; ++i) { if (!reverse_scan) { - if ((pcistr[i].bus > pcistr[i+1].bus) || - (pcistr[i].bus == pcistr[i+1].bus && - PCI_SLOT(pcistr[i].device_fn) > - PCI_SLOT(pcistr[i+1].device_fn))) { + if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) || + (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && + PCI_SLOT(pcistr[i].pdev->devfn) > + PCI_SLOT(pcistr[i+1].pdev->devfn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; changed = TRUE; } } else { - if ((pcistr[i].bus < pcistr[i+1].bus) || - (pcistr[i].bus == pcistr[i+1].bus && - PCI_SLOT(pcistr[i].device_fn) < - PCI_SLOT(pcistr[i+1].device_fn))) { + if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) || + (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && + PCI_SLOT(pcistr[i].pdev->devfn) < + PCI_SLOT(pcistr[i+1].pdev->devfn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; @@ -1176,17 +1172,16 @@ static int __init gdth_init_pci(gdth_pci TRACE(("gdth_init_pci()\n")); - if (pcistr->vendor_id == PCI_VENDOR_ID_INTEL) + if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL) ha->oem_id = OEM_ID_INTEL; else ha->oem_id = OEM_ID_ICP; - ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8); - ha->stype = (ulong32)pcistr->device_id; - ha->subdevice_id = pcistr->subdevice_id; + ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8); + ha->stype = (ulong32)pcistr->pdev->device; ha->irq = pcistr->irq; ha->pdev = pcistr->pdev; - if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ + if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { @@ -1293,7 +1288,7 @@ static int __init gdth_init_pci(gdth_pci ha->dma64_support = 0; - } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ + } else if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ ha->plx = (gdt6c_plx_regs *)pcistr->io; TRACE2(("init_pci_new() dpmem %lx irq %d\n", pcistr->dpmem,ha->irq)); @@ -4601,7 +4596,8 @@ #endif } /* controller found and initialized */ printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); + pcistr[ctr].pdev->bus->number, + PCI_SLOT(pcistr[ctr].pdev->devfn), ha->irq); if (request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED|IRQF_SHARED, "gdth", ha)) @@ -4637,7 +4633,7 @@ #ifdef INT_COAL #endif ha->scratch_busy = FALSE; ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i=0; itype == GDT_ISA) { return("GDT2000/2020"); } else if (ha->type == GDT_PCI) { - switch (ha->stype) { + switch (ha->pdev->device) { case PCI_DEVICE_ID_VORTEX_GDT60x0: return("GDT6000/6020/6050"); case PCI_DEVICE_ID_VORTEX_GDT6000B: @@ -5448,12 +5444,12 @@ static int gdth_ioctl(struct inode *inod ctrt.type = (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); if (ha->stype >= 0x300) - ctrt.ext_type = 0x6000 | ha->subdevice_id; + ctrt.ext_type = 0x6000 | ha->pdev->subsystem_device; else ctrt.ext_type = 0x6000 | ha->stype; } - ctrt.device_id = ha->stype; - ctrt.sub_device_id = ha->subdevice_id; + ctrt.device_id = ha->pdev->device; + ctrt.sub_device_id = ha->pdev->subsystem_device; } ctrt.info = ha->brd_phys; ctrt.oem_id = ha->oem_id; diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 8c29eaf..3742330 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -845,11 +845,6 @@ typedef struct { /* PCI resources */ typedef struct { struct pci_dev *pdev; - ushort vendor_id; /* vendor (ICP, Intel, ..) */ - ushort device_id; /* device ID (0,..,9) */ - ushort subdevice_id; /* sub device ID */ - unchar bus; /* PCI bus */ - unchar device_fn; /* PCI device/function no. */ ulong dpmem; /* DPRAM address */ ulong io; /* IO address */ ulong io_mm; /* IO address mem. mapped */ @@ -862,7 +857,6 @@ typedef struct { ushort oem_id; /* OEM */ ushort type; /* controller class */ ulong32 stype; /* subtype (PCI: device ID) */ - ushort subdevice_id; /* sub device ID (PCI) */ ushort fw_vers; /* firmware version */ ushort cache_feat; /* feat. cache serv. (s/g,..)*/ ushort raw_feat; /* feat. raw service (s/g,..)*/ diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5870866..93bd01b 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -75,6 +75,7 @@ #include #include #include #include +#include #include "ibmvscsi.h" /* The values below are somewhat arbitrary default values, but @@ -87,6 +88,8 @@ static int max_channel = 3; static int init_timeout = 5; static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; +static struct scsi_transport_template *ibmvscsi_transport_template; + #define IBMVSCSI_VERSION "1.5.8" MODULE_DESCRIPTION("IBM Virtual SCSI"); @@ -393,12 +396,6 @@ static int map_sg_data(struct scsi_cmnd return 1; else if (sg_mapped < 0) return 0; - else if (sg_mapped > SG_ALL) { - printk(KERN_ERR - "ibmvscsi: More than %d mapped sg entries, got %d\n", - SG_ALL, sg_mapped); - return 0; - } set_srp_direction(cmd, srp_cmd, sg_mapped); @@ -708,8 +705,7 @@ static int ibmvscsi_queuecommand(struct struct srp_cmd *srp_cmd; struct srp_event_struct *evt_struct; struct srp_indirect_buf *indirect; - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host); u16 lun = lun_from_dev(cmnd->device); u8 out_fmt, in_fmt; @@ -960,8 +956,7 @@ static void sync_completion(struct srp_e */ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) { - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); struct srp_tsk_mgmt *tsk_mgmt; struct srp_event_struct *evt; struct srp_event_struct *tmp_evt, *found_evt; @@ -1084,9 +1079,7 @@ static int ibmvscsi_eh_abort_handler(str */ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) { - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; - + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); struct srp_tsk_mgmt *tsk_mgmt; struct srp_event_struct *evt; struct srp_event_struct *tmp_evt, *pos; @@ -1183,8 +1176,7 @@ static int ibmvscsi_eh_device_reset_hand static int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd) { unsigned long wait_switch = 0; - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); dev_err(hostdata->dev, "Resetting connection due to error recovery\n"); @@ -1412,8 +1404,7 @@ static int ibmvscsi_change_queue_depth(s static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%s\n", @@ -1433,8 +1424,7 @@ static ssize_t show_host_partition_name( char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%s\n", @@ -1454,8 +1444,7 @@ static ssize_t show_host_partition_numbe char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", @@ -1474,8 +1463,7 @@ static struct class_device_attribute ibm static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", @@ -1494,8 +1482,7 @@ static struct class_device_attribute ibm static ssize_t show_host_os_type(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type); @@ -1513,8 +1500,7 @@ static struct class_device_attribute ibm static ssize_t show_host_config(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); /* returns null-terminated host config data */ if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0) @@ -1570,6 +1556,8 @@ static int ibmvscsi_probe(struct vio_dev struct ibmvscsi_host_data *hostdata; struct Scsi_Host *host; struct device *dev = &vdev->dev; + struct srp_rport_identifiers ids; + struct srp_rport *rport; unsigned long wait_switch = 0; int rc; @@ -1582,7 +1570,8 @@ static int ibmvscsi_probe(struct vio_dev goto scsi_host_alloc_failed; } - hostdata = (struct ibmvscsi_host_data *)host->hostdata; + host->transportt = ibmvscsi_transport_template; + hostdata = shost_priv(host); memset(hostdata, 0x00, sizeof(*hostdata)); INIT_LIST_HEAD(&hostdata->sent); hostdata->host = host; @@ -1607,6 +1596,14 @@ static int ibmvscsi_probe(struct vio_dev if (scsi_add_host(hostdata->host, hostdata->dev)) goto add_host_failed; + /* we don't have a proper target_port_id so let's use the fake one */ + memcpy(ids.port_id, hostdata->madapter_info.partition_name, + sizeof(ids.port_id)); + ids.roles = SRP_RPORT_ROLE_TARGET; + rport = srp_rport_add(host, &ids); + if (IS_ERR(rport)) + goto add_srp_port_failed; + /* Try to send an initialization message. Note that this is allowed * to fail if the other end is not acive. In that case we don't * want to scan @@ -1634,6 +1631,8 @@ static int ibmvscsi_probe(struct vio_dev vdev->dev.driver_data = hostdata; return 0; + add_srp_port_failed: + scsi_remove_host(hostdata->host); add_host_failed: release_event_pool(&hostdata->pool, hostdata); init_pool_failed: @@ -1650,7 +1649,8 @@ static int ibmvscsi_remove(struct vio_de release_event_pool(&hostdata->pool, hostdata); ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests); - + + srp_remove_host(hostdata->host); scsi_remove_host(hostdata->host); scsi_host_put(hostdata->host); @@ -1677,14 +1677,28 @@ static struct vio_driver ibmvscsi_driver } }; +static struct srp_function_template ibmvscsi_transport_functions = { +}; + int __init ibmvscsi_module_init(void) { - return vio_register_driver(&ibmvscsi_driver); + int ret; + + ibmvscsi_transport_template = + srp_attach_transport(&ibmvscsi_transport_functions); + if (!ibmvscsi_transport_template) + return -ENOMEM; + + ret = vio_register_driver(&ibmvscsi_driver); + if (ret) + srp_release_transport(ibmvscsi_transport_template); + return ret; } void __exit ibmvscsi_module_exit(void) { vio_unregister_driver(&ibmvscsi_driver); + srp_release_transport(ibmvscsi_transport_template); } module_init(ibmvscsi_module_init); diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 8ba7dd0..3db03dd 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -25,6 +25,7 @@ #include #include #include #include +#include #include #include #include @@ -68,9 +69,12 @@ struct vio_port { unsigned long liobn; unsigned long riobn; struct srp_target *target; + + struct srp_rport *rport; }; static struct workqueue_struct *vtgtd; +static struct scsi_transport_template *ibmvstgt_transport_template; /* * These are fixed for the system and come from the Open Firmware device tree. @@ -188,6 +192,7 @@ static int send_rsp(struct iu_entry *iue static void handle_cmd_queue(struct srp_target *target) { struct Scsi_Host *shost = target->shost; + struct srp_rport *rport = target_to_port(target)->rport; struct iu_entry *iue; struct srp_cmd *cmd; unsigned long flags; @@ -200,7 +205,8 @@ retry: if (!test_and_set_bit(V_FLYING, &iue->flags)) { spin_unlock_irqrestore(&target->lock, flags); cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, 0); + err = srp_cmd_queue(shost, cmd, iue, + (unsigned long)rport, 0); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue); @@ -359,6 +365,16 @@ static void process_login(struct iu_entr union viosrp_iu *iu = vio_iu(iue); struct srp_login_rsp *rsp = &iu->srp.login_rsp; uint64_t tag = iu->srp.rsp.tag; + struct Scsi_Host *shost = iue->target->shost; + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + struct srp_rport_identifiers ids; + + memset(&ids, 0, sizeof(ids)); + sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); + ids.roles = SRP_RPORT_ROLE_INITIATOR; + if (!vport->rport) + vport->rport = srp_rport_add(shost, &ids); /* TODO handle case that requested size is wrong and * buffer format is wrong @@ -412,7 +428,9 @@ static int process_tsk_mgmt(struct iu_en fn = 0; } if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, + scsi_tgt_tsk_mgmt_request(iue->target->shost, + (unsigned long)iue->target->shost, + fn, iu->srp.tsk_mgmt.task_tag, (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, iue); @@ -721,7 +739,8 @@ static int ibmvstgt_eh_abort_handler(str return 0; } -static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) +static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, + u64 itn_id, u64 mid, int result) { struct iu_entry *iue = (struct iu_entry *) ((void *) mid); union viosrp_iu *iu = vio_iu(iue); @@ -747,6 +766,20 @@ static int ibmvstgt_tsk_mgmt_response(u6 return 0; } +static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, + int result) +{ + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + + if (result) { + eprintk("%p %d\n", shost, result); + srp_rport_del(vport->rport); + vport->rport = NULL; + } + return 0; +} + static ssize_t system_id_show(struct class_device *cdev, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", system_id); @@ -785,7 +818,6 @@ static struct scsi_host_template ibmvstg .max_sectors = DEFAULT_MAX_SECTORS, .transfer_response = ibmvstgt_cmd_done, .eh_abort_handler = ibmvstgt_eh_abort_handler, - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, .shost_attrs = ibmvstgt_attrs, .proc_name = TGT_NAME, }; @@ -804,6 +836,7 @@ static int ibmvstgt_probe(struct vio_dev shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); if (!shost) goto free_vport; + shost->transportt = ibmvstgt_transport_template; err = scsi_tgt_alloc_queue(shost); if (err) goto put_host; @@ -837,8 +870,8 @@ static int ibmvstgt_probe(struct vio_dev err = scsi_add_host(shost, target->dev); if (err) goto destroy_queue; - return 0; + return 0; destroy_queue: crq_queue_destroy(target); free_srp_target: @@ -857,6 +890,7 @@ static int ibmvstgt_remove(struct vio_de struct vio_port *vport = target->ldata; crq_queue_destroy(target); + srp_remove_host(shost); scsi_remove_host(shost); scsi_tgt_free_queue(shost); srp_target_free(target); @@ -909,15 +943,25 @@ static int get_system_info(void) return 0; } +static struct srp_function_template ibmvstgt_transport_functions = { + .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, + .it_nexus_response = ibmvstgt_it_nexus_response, +}; + static int ibmvstgt_init(void) { int err = -ENOMEM; printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); + ibmvstgt_transport_template = + srp_attach_transport(&ibmvstgt_transport_functions); + if (!ibmvstgt_transport_template) + return err; + vtgtd = create_workqueue("ibmvtgtd"); if (!vtgtd) - return err; + goto release_transport; err = get_system_info(); if (err) @@ -928,9 +972,10 @@ static int ibmvstgt_init(void) goto destroy_wq; return 0; - destroy_wq: destroy_workqueue(vtgtd); +release_transport: + srp_release_transport(ibmvstgt_transport_template); return err; } @@ -940,6 +985,7 @@ static void ibmvstgt_exit(void) destroy_workqueue(vtgtd); vio_unregister_driver(&ibmvstgt_driver); + srp_release_transport(ibmvstgt_transport_template); } MODULE_DESCRIPTION("IBM Virtual SCSI Target"); diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig index 3a3c1ac..c01a40d 100644 --- a/drivers/scsi/libsas/Kconfig +++ b/drivers/scsi/libsas/Kconfig @@ -32,7 +32,8 @@ config SCSI_SAS_LIBSAS config SCSI_SAS_ATA bool "ATA support for libsas (requires libata)" - depends on SCSI_SAS_LIBSAS && ATA + depends on SCSI_SAS_LIBSAS + depends on ATA = y || ATA = SCSI_SAS_LIBSAS help Builds in ATA support into libsas. Will necessitate the loading of libata along with libsas. diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 732446e..2ad0a27 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -392,7 +392,7 @@ static int vscsis_data_length(struct srp } int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, - u64 addr) + u64 itn_id, u64 addr) { enum dma_data_direction dir; struct scsi_cmnd *sc; @@ -428,7 +428,8 @@ int srp_cmd_queue(struct Scsi_Host *shos sc->request_bufflen = len; sc->request_buffer = (void *) (unsigned long) addr; sc->tag = tag; - err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); + err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun, + cmd->tag); if (err) scsi_host_put_command(shost, sc); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c488996..93c0c7e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2154,6 +2154,19 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } } + /* Get memory for cached NVRAM */ + ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); + if (ha->nvram == NULL) { + /* error */ + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - nvram cache\n"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + /* Done all allocations without any error. */ status = 0; @@ -2266,6 +2279,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->fw_dump_reading = 0; vfree(ha->optrom_buffer); + kfree(ha->nvram); } /* diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index ca22ddf..9815a1a 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c @@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 typ return 0; } -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *lun, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi memset(&ev, 0, sizeof(ev)); ev.p.cmd_req.host_no = shost->host_no; + ev.p.cmd_req.itn_id = itn_id; ev.p.cmd_req.data_len = cmd->request_bufflen; memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); @@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi return err; } -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct s memset(&ev, 0, sizeof(ev)); ev.p.cmd_done.host_no = shost->host_no; + ev.p.cmd_done.itn_id = itn_id; ev.p.cmd_done.tag = tag; ev.p.cmd_done.result = cmd->result; @@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct s return err; } -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, + u64 tag, struct scsi_lun *scsilun, void *data) { struct tgt_event ev; int err; memset(&ev, 0, sizeof(ev)); ev.p.tsk_mgmt_req.host_no = host_no; + ev.p.tsk_mgmt_req.itn_id = itn_id; ev.p.tsk_mgmt_req.function = function; ev.p.tsk_mgmt_req.tag = tag; memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); @@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int ho return err; } +int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id, + int function, char *initiator_id) +{ + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.it_nexus_req.host_no = host_no; + ev.p.it_nexus_req.function = function; + ev.p.it_nexus_req.itn_id = itn_id; + if (initiator_id) + strncpy(ev.p.it_nexus_req.initiator_id, initiator_id, + sizeof(ev.p.it_nexus_req.initiator_id)); + + dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id); + + err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + static int event_recv_msg(struct tgt_event *ev) { int err = 0; @@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_eve switch (ev->hdr.type) { case TGT_UEVENT_CMD_RSP: err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, + ev->p.cmd_rsp.itn_id, ev->p.cmd_rsp.result, ev->p.cmd_rsp.tag, ev->p.cmd_rsp.uaddr, @@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_eve break; case TGT_UEVENT_TSK_MGMT_RSP: err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, + ev->p.tsk_mgmt_rsp.itn_id, ev->p.tsk_mgmt_rsp.mid, ev->p.tsk_mgmt_rsp.result); break; + case TGT_UEVENT_IT_NEXUS_RSP: + err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no, + ev->p.it_nexus_rsp.itn_id, + ev->p.it_nexus_rsp.result); + break; default: eprintk("unknown type %d\n", ev->hdr.type); err = -EINVAL; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 371b69c..5851c8e 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -27,6 +27,7 @@ #include #include #include #include +#include #include #include "scsi_tgt_priv.h" @@ -46,6 +47,7 @@ struct scsi_tgt_cmd { struct list_head hash_list; struct request *rq; + u64 itn_id; u64 tag; }; @@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct } static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, - u64 tag) + u64 itn_id, u64 tag) { struct scsi_tgt_queuedata *qdata = rq->q->queuedata; unsigned long flags; struct list_head *head; + tcmd->itn_id = itn_id; tcmd->tag = tag; tcmd->bio = NULL; INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); @@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); * @scsilun: scsi lun * @tag: unique value to identify this command for tmf */ -int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, - u64 tag) +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *scsilun, u64 tag) { struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; int err; - init_scsi_tgt_cmd(cmd->request, tcmd, tag); - err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); + init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); + err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); if (err) cmd_hashlist_del(cmd); @@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scs dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); - scsi_tgt_uspace_send_status(cmd, tcmd->tag); + scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); if (cmd->request_buffer) scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); @@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_look return rq; } -int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, +int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, unsigned long uaddr, u32 len, unsigned long sense_uaddr, u32 sense_len, u8 rw) { @@ -541,21 +544,22 @@ done: return err; } -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, + int function, u64 tag, struct scsi_lun *scsilun, + void *data) { int err; /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, - tag, scsilun, data); + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, + function, tag, scsilun, data); if (err < 0) eprintk("The task management request lost!\n"); return err; } EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); -int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) { struct Scsi_Host *shost; int err = -EINVAL; @@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no goto done; } - err = shost->hostt->tsk_mgmt_response(mid, result); + err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result); +done: + scsi_host_put(shost); + return err; +} + +int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, + initiator); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); + +int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, + itn_id, 1, NULL); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); + +int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) +{ + struct Scsi_Host *shost; + int err = -EINVAL; + + dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); + + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return err; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + err = shost->transportt->it_nexus_response(shost, itn_id, result); done: scsi_host_put(shost); return err; diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h index e9e6db1..cb92888 100644 --- a/drivers/scsi/scsi_tgt_priv.h +++ b/drivers/scsi/scsi_tgt_priv.h @@ -15,12 +15,18 @@ #define dprintk(fmt, args...) extern void scsi_tgt_if_exit(void); extern int scsi_tgt_if_init(void); -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, - u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, - unsigned long uaddr, u32 len, unsigned long sense_uaddr, - u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, +extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, + struct scsi_lun *lun, u64 tag); +extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, + u64 tag); +extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, + unsigned long uaddr, u32 len, + unsigned long sense_uaddr, u32 sense_len, u8 rw); +extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, + int function, u64 tag, struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, + u64 mid, int result); +extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, + int function, char *initiator); +extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result); diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c new file mode 100644 index 0000000..cdd001a --- /dev/null +++ b/drivers/scsi/scsi_transport_srp.c @@ -0,0 +1,379 @@ +/* + * SCSI RDMA (SRP) transport class + * + * Copyright (C) 2007 FUJITA Tomonori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct srp_host_attrs { + atomic_t next_port_id; +}; +#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) + +#define SRP_HOST_ATTRS 0 +#define SRP_RPORT_ATTRS 2 + +struct srp_internal { + struct scsi_transport_template t; + struct srp_function_template *f; + + struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1]; + + struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1]; + struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS]; + struct transport_container rport_attr_cont; +}; + +#define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t) + +#define dev_to_rport(d) container_of(d, struct srp_rport, dev) +#define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev) + +static int srp_host_setup(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct srp_host_attrs *srp_host = to_srp_host_attrs(shost); + + atomic_set(&srp_host->next_port_id, 0); + return 0; +} + +static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup, + NULL, NULL); + +static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports", + NULL, NULL, NULL); + +#define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm) \ + i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count].attr.mode = perm; \ + if (ro_test) { \ + i->private_##attrb[count].attr.mode = ro_perm; \ + i->private_##attrb[count].store = NULL; \ + } \ + i->attrb[count] = &i->private_##attrb[count]; \ + if (test) \ + count++ + +#define SETUP_RPORT_ATTRIBUTE_RD(field) \ + SETUP_TEMPLATE(rport_attrs, field, S_IRUGO, 1, 0, 0) + +#define SETUP_RPORT_ATTRIBUTE_RW(field) \ + SETUP_TEMPLATE(rport_attrs, field, S_IRUGO | S_IWUSR, \ + 1, 1, S_IRUGO) + +#define SRP_PID(p) \ + (p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \ + (p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \ + (p)->port_id[8], (p)->port_id[9], (p)->port_id[10], (p)->port_id[11], \ + (p)->port_id[12], (p)->port_id[13], (p)->port_id[14], (p)->port_id[15] + +#define SRP_PID_FMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \ + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" + +static ssize_t +show_srp_rport_id(struct class_device *cdev, char *buf) +{ + struct srp_rport *rport = transport_class_to_srp_rport(cdev); + return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport)); +} + +static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL); + +static const struct { + u32 value; + char *name; +} srp_rport_role_names[] = { + {SRP_RPORT_ROLE_INITIATOR, "SRP Initiator"}, + {SRP_RPORT_ROLE_TARGET, "SRP Target"}, +}; + +static ssize_t +show_srp_rport_roles(struct class_device *cdev, char *buf) +{ + struct srp_rport *rport = transport_class_to_srp_rport(cdev); + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(srp_rport_role_names); i++) + if (srp_rport_role_names[i].value == rport->roles) { + name = srp_rport_role_names[i].name; + break; + } + return sprintf(buf, "%s\n", name ? : "unknown"); +} + +static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); + +static void srp_rport_release(struct device *dev) +{ + struct srp_rport *rport = dev_to_rport(dev); + + put_device(dev->parent); + kfree(rport); +} + +static int scsi_is_srp_rport(const struct device *dev) +{ + return dev->release == srp_rport_release; +} + +static int srp_rport_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct srp_internal *i; + + if (!scsi_is_srp_rport(dev)) + return 0; + + shost = dev_to_shost(dev->parent); + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != &srp_host_class.class) + return 0; + + i = to_srp_internal(shost->transportt); + return &i->rport_attr_cont.ac == cont; +} + +static int srp_host_match(struct attribute_container *cont, struct device *dev) +{ + struct Scsi_Host *shost; + struct srp_internal *i; + + if (!scsi_is_host_device(dev)) + return 0; + + shost = dev_to_shost(dev); + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != &srp_host_class.class) + return 0; + + i = to_srp_internal(shost->transportt); + return &i->t.host_attrs.ac == cont; +} + +/** + * srp_rport_add - add a SRP remote port to the device hierarchy + * + * @shost: scsi host the remote port is connected to. + * @ids: The port id for the remote port. + * + * publishes a port to the rest of the system + */ +struct srp_rport *srp_rport_add(struct Scsi_Host *shost, + struct srp_rport_identifiers *ids) +{ + struct srp_rport *rport; + struct device *parent = &shost->shost_gendev; + int id, ret; + + rport = kzalloc(sizeof(*rport), GFP_KERNEL); + if (!rport) + return ERR_PTR(-ENOMEM); + + device_initialize(&rport->dev); + + rport->dev.parent = get_device(parent); + rport->dev.release = srp_rport_release; + + memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id)); + rport->roles = ids->roles; + + id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id); + sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id); + + transport_setup_device(&rport->dev); + + ret = device_add(&rport->dev); + if (ret) { + transport_destroy_device(&rport->dev); + put_device(&rport->dev); + return ERR_PTR(ret); + } + + if (ids->roles == SRP_RPORT_ROLE_INITIATOR) { + ret = scsi_tgt_it_nexus_create(shost, (unsigned long)rport, + rport->port_id); + if (ret) { + device_del(&rport->dev); + transport_destroy_device(&rport->dev); + put_device(&rport->dev); + return ERR_PTR(ret); + } + } + + transport_add_device(&rport->dev); + transport_configure_device(&rport->dev); + + return rport; +} +EXPORT_SYMBOL_GPL(srp_rport_add); + +/** + * srp_rport_del -- remove a SRP remote port + * @port: SRP remote port to remove + * + * Removes the specified SRP remote port. + */ +void srp_rport_del(struct srp_rport *rport) +{ + struct device *dev = &rport->dev; + + if (rport->roles == SRP_RPORT_ROLE_INITIATOR) + scsi_tgt_it_nexus_destroy(dev_to_shost(dev->parent), + (unsigned long)rport); + + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); + put_device(dev); +} +EXPORT_SYMBOL_GPL(srp_rport_del); + +static int do_srp_rport_del(struct device *dev, void *data) +{ + srp_rport_del(dev_to_rport(dev)); + return 0; +} + +/** + * srp_remove_host -- tear down a Scsi_Host's SRP data structures + * @shost: Scsi Host that is torn down + * + * Removes all SRP remote ports for a given Scsi_Host. + * Must be called just before scsi_remove_host for SRP HBAs. + */ +void srp_remove_host(struct Scsi_Host *shost) +{ + device_for_each_child(&shost->shost_gendev, NULL, do_srp_rport_del); +} +EXPORT_SYMBOL_GPL(srp_remove_host); + +static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, + int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); +} + +static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->it_nexus_response(shost, nexus, result); +} + +/** + * srp_attach_transport -- instantiate SRP transport template + * @ft: SRP transport class function template + */ +struct scsi_transport_template * +srp_attach_transport(struct srp_function_template *ft) +{ + int count; + struct srp_internal *i; + + i = kzalloc(sizeof(*i), GFP_KERNEL); + if (!i) + return NULL; + + i->t.tsk_mgmt_response = srp_tsk_mgmt_response; + i->t.it_nexus_response = srp_it_nexus_response; + + i->t.host_size = sizeof(struct srp_host_attrs); + i->t.host_attrs.ac.attrs = &i->host_attrs[0]; + i->t.host_attrs.ac.class = &srp_host_class.class; + i->t.host_attrs.ac.match = srp_host_match; + i->host_attrs[0] = NULL; + transport_container_register(&i->t.host_attrs); + + i->rport_attr_cont.ac.attrs = &i->rport_attrs[0]; + i->rport_attr_cont.ac.class = &srp_rport_class.class; + i->rport_attr_cont.ac.match = srp_rport_match; + transport_container_register(&i->rport_attr_cont); + + count = 0; + SETUP_RPORT_ATTRIBUTE_RD(port_id); + SETUP_RPORT_ATTRIBUTE_RD(roles); + i->rport_attrs[count] = NULL; + + i->f = ft; + + return &i->t; +} +EXPORT_SYMBOL_GPL(srp_attach_transport); + +/** + * srp_release_transport -- release SRP transport template instance + * @t: transport template instance + */ +void srp_release_transport(struct scsi_transport_template *t) +{ + struct srp_internal *i = to_srp_internal(t); + + transport_container_unregister(&i->t.host_attrs); + transport_container_unregister(&i->rport_attr_cont); + + kfree(i); +} +EXPORT_SYMBOL_GPL(srp_release_transport); + +static __init int srp_transport_init(void) +{ + int ret; + + ret = transport_class_register(&srp_host_class); + if (ret) + return ret; + ret = transport_class_register(&srp_rport_class); + if (ret) + goto unregister_host_class; + + return 0; +unregister_host_class: + transport_class_unregister(&srp_host_class); + return ret; +} + +static void __exit srp_transport_exit(void) +{ + transport_class_unregister(&srp_host_class); + transport_class_unregister(&srp_rport_class); +} + +MODULE_AUTHOR("FUJITA Tomonori"); +MODULE_DESCRIPTION("SRP Transport Attributes"); +MODULE_LICENSE("GPL"); + +module_init(srp_transport_init); +module_exit(srp_transport_exit); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a4f7b84..73c44cb 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1485,7 +1485,7 @@ st_write(struct file *filp, const char _ struct st_buffer *STbp; char *name = tape_name(STp); - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -1736,7 +1736,7 @@ st_write(struct file *filp, const char _ if (SRpnt != NULL) st_release_request(SRpnt); release_buffering(STp, 0); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -1942,7 +1942,7 @@ st_read(struct file *filp, char __user * struct st_buffer *STbp = STp->buffer; DEB( char *name = tape_name(STp); ) - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -2069,7 +2069,7 @@ st_read(struct file *filp, char __user * release_buffering(STp, 1); STbp->buffer_bytes = 0; } - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -3226,7 +3226,7 @@ static int st_ioctl(struct inode *inode, char *name = tape_name(STp); void __user *p = (void __user *)arg; - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; DEB( @@ -3537,7 +3537,7 @@ static int st_ioctl(struct inode *inode, retval = (-EFAULT); goto out; } - up(&STp->lock); + mutex_unlock(&STp->lock); switch (cmd_in) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: @@ -3563,7 +3563,7 @@ static int st_ioctl(struct inode *inode, return retval; out: - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -4029,7 +4029,7 @@ static int st_probe(struct device *dev) tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0; - init_MUTEX(&tpnt->lock); + mutex_init(&tpnt->lock); st_nr_dev++; write_unlock(&st_dev_arr_lock); diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 50f3deb..6c80757 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -3,6 +3,7 @@ #ifndef _ST_H #define _ST_H #include +#include #include #include @@ -98,7 +99,7 @@ #define ST_NBR_PARTITIONS 4 struct scsi_tape { struct scsi_driver *driver; struct scsi_device *device; - struct semaphore lock; /* For serialization */ + struct mutex lock; /* For serialization */ struct completion wait; /* For SCSI commands */ struct st_buffer *buffer; diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 102dc09..60e377b 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -15,14 +15,18 @@ struct sg_io_v4 { __u32 request_len; /* [i] in bytes */ __u64 request; /* [i], [*i] {SCSI: cdb} */ + __u64 request_tag; /* [i] {SCSI: task tag (only if flagged)} */ __u32 request_attr; /* [i] {SCSI: task attribute} */ - __u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */ __u32 request_priority; /* [i] {SCSI: task priority} */ + __u32 request_extra; /* [i] {spare, for padding} */ __u32 max_response_len; /* [i] in bytes */ __u64 response; /* [i], [*o] {SCSI: (auto)sense data} */ - /* "din_" for data in (from device); "dout_" for data out (to device) */ + /* "dout_": data out (to device); "din_": data in (from device) */ + __u32 dout_iovec_count; /* [i] 0 -> "flat" dout transfer else + dout_xfer points to array of iovec */ __u32 dout_xfer_len; /* [i] bytes to be transferred to device */ + __u32 din_iovec_count; /* [i] 0 -> "flat" din transfer */ __u32 din_xfer_len; /* [i] bytes to be transferred from device */ __u64 dout_xferp; /* [i], [*i] */ __u64 din_xferp; /* [i], [*o] */ @@ -39,8 +43,9 @@ struct sg_io_v4 { __u32 info; /* [o] additional information */ __u32 duration; /* [o] time to complete, in milliseconds */ __u32 response_len; /* [o] bytes of response actually written */ - __s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */ - __u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */ + __s32 din_resid; /* [o] din_xfer_len - actual_din_xfer_len */ + __s32 dout_resid; /* [o] dout_xfer_len - actual_dout_xfer_len */ + __u64 generated_tag; /* [o] {SCSI: transport generated task tag} */ __u32 spare_out; /* [o] */ __u32 padding; diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h index d143171..ba615e4 100644 --- a/include/scsi/libsrp.h +++ b/include/scsi/libsrp.h @@ -59,7 +59,7 @@ extern void srp_target_free(struct srp_t extern struct iu_entry *srp_iu_get(struct srp_target *); extern void srp_iu_put(struct iu_entry *); -extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64); +extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64); extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, srp_rdma_t, int, int); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 3b8a6a8..88f6871 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -145,9 +145,6 @@ #endif int (* transfer_response)(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); - /* Used as callback for the completion of task management request. */ - int (* tsk_mgmt_response)(u64 mid, int result); - /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h index 4f44279..d0fefb9 100644 --- a/include/scsi/scsi_tgt.h +++ b/include/scsi/scsi_tgt.h @@ -11,9 +11,11 @@ struct scsi_lun; extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); extern int scsi_tgt_alloc_queue(struct Scsi_Host *); extern void scsi_tgt_free_queue(struct Scsi_Host *); -extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, - void *); +extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64); +extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, + struct scsi_lun *, void *); extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, enum dma_data_direction, gfp_t); extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); +extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *); +extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64); diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h index 4cf9dff..f2ee7c2 100644 --- a/include/scsi/scsi_tgt_if.h +++ b/include/scsi/scsi_tgt_if.h @@ -23,13 +23,15 @@ #ifndef __SCSI_TARGET_IF_H #define __SCSI_TARGET_IF_H /* user -> kernel */ -#define TGT_UEVENT_CMD_RSP 0x0001 -#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 +#define TGT_UEVENT_CMD_RSP 0x0001 +#define TGT_UEVENT_IT_NEXUS_RSP 0x0002 +#define TGT_UEVENT_TSK_MGMT_RSP 0x0003 /* kernel -> user */ -#define TGT_KEVENT_CMD_REQ 0x1001 -#define TGT_KEVENT_CMD_DONE 0x1002 -#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 +#define TGT_KEVENT_CMD_REQ 0x1001 +#define TGT_KEVENT_CMD_DONE 0x1002 +#define TGT_KEVENT_IT_NEXUS_REQ 0x1003 +#define TGT_KEVENT_TSK_MGMT_REQ 0x1004 struct tgt_event_hdr { uint16_t version; @@ -46,6 +48,7 @@ struct tgt_event { struct { int host_no; int result; + aligned_u64 itn_id; aligned_u64 tag; aligned_u64 uaddr; aligned_u64 sense_uaddr; @@ -55,15 +58,22 @@ struct tgt_event { } cmd_rsp; struct { int host_no; - aligned_u64 mid; int result; + aligned_u64 itn_id; + aligned_u64 mid; } tsk_mgmt_rsp; - + struct { + __s32 host_no; + __s32 result; + aligned_u64 itn_id; + __u32 function; + } it_nexus_rsp; /* kernel -> user */ struct { int host_no; uint32_t data_len; + aligned_u64 itn_id; uint8_t scb[16]; uint8_t lun[8]; int attribute; @@ -71,16 +81,25 @@ struct tgt_event { } cmd_req; struct { int host_no; - aligned_u64 tag; int result; + aligned_u64 itn_id; + aligned_u64 tag; } cmd_done; struct { int host_no; int function; + aligned_u64 itn_id; aligned_u64 tag; uint8_t lun[8]; aligned_u64 mid; } tsk_mgmt_req; + struct { + __s32 host_no; + __u32 function; + aligned_u64 itn_id; + __u32 max_cmds; + __u8 initiator_id[16]; + } it_nexus_req; } p; } __attribute__ ((aligned (sizeof(uint64_t)))); diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index 3c18baa..0dfef75 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -65,6 +65,18 @@ struct scsi_transport_template { * EH_NOT_HANDLED Begin normal error recovery */ enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + + /* + * Used as callback for the completion of i_t_nexus request + * for target drivers. + */ + int (* it_nexus_response)(struct Scsi_Host *, u64, int); + + /* + * Used as callback for the completion of task management + * request for target drivers. + */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); }; #define transport_class_to_shost(tc) \ diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h new file mode 100644 index 0000000..9c60ca1 --- /dev/null +++ b/include/scsi/scsi_transport_srp.h @@ -0,0 +1,39 @@ +#ifndef SCSI_TRANSPORT_SRP_H +#define SCSI_TRANSPORT_SRP_H + +#include +#include +#include + +#define SRP_RPORT_ROLE_INITIATOR 0 +#define SRP_RPORT_ROLE_TARGET 1 + +struct srp_rport_identifiers { + u8 port_id[16]; + u8 roles; +}; + +struct srp_rport { + struct device dev; + + u8 port_id[16]; + u8 roles; +}; + +struct srp_function_template { + /* for target drivers */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); + int (* it_nexus_response)(struct Scsi_Host *, u64, int); +}; + +extern struct scsi_transport_template * +srp_attach_transport(struct srp_function_template *); +extern void srp_release_transport(struct scsi_transport_template *); + +extern struct srp_rport *srp_rport_add(struct Scsi_Host *, + struct srp_rport_identifiers *); +extern void srp_rport_del(struct srp_rport *); + +extern void srp_remove_host(struct Scsi_Host *); + +#endif