* [PATCH] libsas: add host SMP processing
@ 2007-12-28 23:36 James Bottomley
2007-12-29 5:24 ` FUJITA Tomonori
0 siblings, 1 reply; 6+ messages in thread
From: James Bottomley @ 2007-12-28 23:36 UTC (permalink / raw)
To: linux-scsi
This patch allows the sas host device to accept SMP commands. This
brings the libsas attached hosts on to a par with the firmware based
ones like mptsas.
James
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index c01a40d..18f33cd 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -38,6 +38,15 @@ config SCSI_SAS_ATA
Builds in ATA support into libsas. Will necessitate
the loading of libata along with libsas.
+config SCSI_SAS_HOST_SMP
+ bool "Support for SMP interpretation for SAS hosts"
+ default y
+ depends on SCSI_SAS_LIBSAS
+ help
+ Allows sas hosts to receive SMP frames. Selecting this
+ option builds an SMP interpreter into libsas. Say
+ N here if you want to save the few kb this consumes.
+
config SCSI_SAS_LIBSAS_DEBUG
bool "Compile the SAS Domain Transport Attributes in debug mode"
default y
diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile
index fd387b9..60d6e93 100644
--- a/drivers/scsi/libsas/Makefile
+++ b/drivers/scsi/libsas/Makefile
@@ -35,3 +35,4 @@ libsas-y += sas_init.o \
sas_expander.o \
sas_scsi_host.o
libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
+libsas-$(CONFIG_SCSI_SAS_HOST_SMP) += sas_host_smp.o
\ No newline at end of file
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 27674fe..76555b1 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
}
/* no rphy means no smp target support (ie aic94xx host) */
- if (!rphy) {
- printk("%s: can we send a smp request to a host?\n",
- __FUNCTION__);
- return -EINVAL;
- }
+ if (!rphy)
+ return sas_smp_host_handler(shost, req, rsp);
+
type = rphy->identify.device_type;
if (type != SAS_EDGE_EXPANDER_DEVICE &&
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
new file mode 100644
index 0000000..5b9370a
--- /dev/null
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -0,0 +1,247 @@
+/*
+ * Serial Attached SCSI (SAS) Expander discovery and configuration
+ *
+ * Copyright (C) 2007 James E.J. Bottomley
+ * <James.Bottomley@HansenPartnership.com>
+ *
+ * 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 only.
+ */
+#include <linux/scatterlist.h>
+#include <linux/blkdev.h>
+
+#include "sas_internal.h"
+
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_sas.h>
+#include "../scsi_sas_internal.h"
+
+static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data,
+ u8 phy_id)
+{
+ struct sas_phy *phy;
+ struct sas_rphy *rphy;
+
+ if (phy_id >= sas_ha->num_phys) {
+ resp_data[2] = SMP_RESP_NO_PHY;
+ return;
+ }
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+
+ phy = sas_ha->sas_phy[phy_id]->phy;
+ resp_data[9] = phy_id;
+ resp_data[13] = phy->negotiated_linkrate;
+ memcpy(resp_data + 16, sas_ha->sas_addr, SAS_ADDR_SIZE);
+ memcpy(resp_data + 24, sas_ha->sas_phy[phy_id]->attached_sas_addr,
+ SAS_ADDR_SIZE);
+ resp_data[40] = (phy->minimum_linkrate << 4) |
+ phy->minimum_linkrate_hw;
+ resp_data[41] = (phy->maximum_linkrate << 4) |
+ phy->maximum_linkrate_hw;
+
+ if (!sas_ha->sas_phy[phy_id]->port)
+ return;
+
+ rphy = sas_ha->sas_phy[phy_id]->port->port_dev->rphy;
+ resp_data[12] = rphy->identify.device_type << 4;
+ resp_data[14] = rphy->identify.initiator_port_protocols;
+ resp_data[15] = rphy->identify.target_port_protocols;
+}
+
+static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data,
+ u8 phy_id)
+{
+ struct sas_rphy *rphy;
+ struct dev_to_host_fis *fis;
+ int i;
+
+ if (phy_id >= sas_ha->num_phys) {
+ resp_data[2] = SMP_RESP_NO_PHY;
+ return;
+ }
+
+ resp_data[2] = SMP_RESP_PHY_NO_SATA;
+
+ if (!sas_ha->sas_phy[phy_id]->port)
+ return;
+
+ rphy = sas_ha->sas_phy[phy_id]->port->port_dev->rphy;
+ fis = (struct dev_to_host_fis *)
+ sas_ha->sas_phy[phy_id]->port->port_dev->frame_rcvd;
+ if (rphy->identify.target_port_protocols != SAS_PROTOCOL_SATA)
+ return;
+
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+ resp_data[9] = phy_id;
+ memcpy(resp_data + 16, sas_ha->sas_phy[phy_id]->attached_sas_addr,
+ SAS_ADDR_SIZE);
+
+ /* check to see if we have a valid d2h fis */
+ if (fis->fis_type != 0x34)
+ return;
+
+ /* the d2h fis is required by the standard to be in LE format */
+ for (i = 0; i < 20; i += 4) {
+ u8 *dst = resp_data + 24 + i, *src =
+ &sas_ha->sas_phy[phy_id]->port->port_dev->frame_rcvd[i];
+ dst[0] = src[3];
+ dst[1] = src[2];
+ dst[2] = src[1];
+ dst[3] = src[0];
+ }
+}
+
+static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
+ u8 phy_op, enum sas_linkrate min,
+ enum sas_linkrate max, u8 *resp_data)
+{
+ struct sas_internal *i =
+ to_sas_internal(sas_ha->core.shost->transportt);
+ struct sas_phy_linkrates rates;
+
+ if (phy_id >= sas_ha->num_phys) {
+ resp_data[2] = SMP_RESP_NO_PHY;
+ return;
+ }
+ switch (phy_op) {
+ case PHY_FUNC_NOP:
+ case PHY_FUNC_LINK_RESET:
+ case PHY_FUNC_HARD_RESET:
+ case PHY_FUNC_DISABLE:
+ case PHY_FUNC_CLEAR_ERROR_LOG:
+ case PHY_FUNC_CLEAR_AFFIL:
+ case PHY_FUNC_TX_SATA_PS_SIGNAL:
+ break;
+
+ default:
+ resp_data[2] = SMP_RESP_PHY_UNK_OP;
+ return;
+ }
+
+ rates.minimum_linkrate = min;
+ rates.maximum_linkrate = max;
+
+ if (i->dft->lldd_control_phy(sas_ha->sas_phy[phy_id], phy_op, &rates))
+ resp_data[2] = SMP_RESP_FUNC_FAILED;
+ else
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+}
+
+int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
+ struct request *rsp)
+{
+ u8 *req_data = NULL, *resp_data = NULL, *buf;
+ struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ int error = -EINVAL;
+
+ /* eight is the minimum size for request and response frames */
+ if (req->data_len < 8 || rsp->data_len < 8)
+ goto out;
+
+ if (bio_offset(req->bio) + req->data_len > PAGE_SIZE ||
+ bio_offset(rsp->bio) + rsp->data_len > PAGE_SIZE) {
+ shost_printk(KERN_ERR, shost,
+ "SMP request/response frame crosses page boundary");
+ goto out;
+ }
+
+ req_data = kzalloc(req->data_len, GFP_KERNEL);
+
+ /* make sure frame can always be built ... we copy
+ * back only the requested length */
+ resp_data = kzalloc(max(rsp->data_len, 128U), GFP_KERNEL);
+
+ if (!req_data || !resp_data) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ local_irq_disable();
+ buf = kmap_atomic(bio_page(req->bio), KM_USER0) + bio_offset(req->bio);
+ memcpy(req_data, buf, req->data_len);
+ kunmap_atomic(buf - bio_offset(req->bio), KM_USER0);
+ local_irq_enable();
+
+ if (req_data[0] != SMP_REQUEST)
+ goto out;
+
+ /* always succeeds ... even if we can't process the request
+ * the result is in the response frame */
+ error = 0;
+
+ /* set up default don't know response */
+ resp_data[0] = SMP_RESPONSE;
+ resp_data[1] = req_data[1];
+ resp_data[2] = SMP_RESP_FUNC_UNK;
+
+ switch (req_data[1]) {
+ case SMP_REPORT_GENERAL:
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+ resp_data[9] = sas_ha->num_phys;
+ break;
+
+ case SMP_REPORT_MANUF_INFO:
+ resp_data[2] = SMP_RESP_FUNC_ACC;
+ memcpy(resp_data + 12, shost->hostt->name,
+ SAS_EXPANDER_VENDOR_ID_LEN);
+ memcpy(resp_data + 20, "libsas virt phy",
+ SAS_EXPANDER_PRODUCT_ID_LEN);
+ break;
+
+ case SMP_READ_GPIO_REG:
+ /* FIXME: need GPIO support in the transport class */
+ break;
+
+ case SMP_DISCOVER:
+ sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
+ break;
+
+ case SMP_REPORT_PHY_ERR_LOG:
+ /* FIXME: could implement this with additional
+ * libsas callbacks providing the HW supports it */
+ break;
+
+ case SMP_REPORT_PHY_SATA:
+ sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
+ break;
+
+ case SMP_REPORT_ROUTE_INFO:
+ /* Can't implement; hosts have no routes */
+ break;
+
+ case SMP_WRITE_GPIO_REG:
+ /* FIXME: need GPIO support in the transport class */
+ break;
+
+ case SMP_CONF_ROUTE_INFO:
+ /* Can't implement; hosts have no routes */
+ break;
+
+ case SMP_PHY_CONTROL:
+ sas_phy_control(sas_ha, req_data[9], req_data[10],
+ req_data[32] >> 4, req_data[33] >> 4,
+ resp_data);
+ break;
+
+ case SMP_PHY_TEST_FUNCTION:
+ /* FIXME: should this be implemented? */
+ break;
+
+ default:
+ /* probably a 2.0 function */
+ break;
+ }
+
+ local_irq_disable();
+ buf = kmap_atomic(bio_page(rsp->bio), KM_USER0) + bio_offset(rsp->bio);
+ memcpy(buf, resp_data, rsp->data_len);
+ flush_kernel_dcache_page(bio_page(rsp->bio));
+ kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0);
+ local_irq_enable();
+
+ out:
+ kfree(req_data);
+ kfree(resp_data);
+ return error;
+}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index baa0666..b4f9368 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -80,6 +80,20 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
void sas_hae_reset(struct work_struct *work);
+#ifdef CONFIG_SCSI_SAS_HOST_SMP
+extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
+ struct request *rsp);
+#else
+static inline int sas_smp_host_handler(struct Scsi_Host *shost,
+ struct request *req,
+ struct request *rsp)
+{
+ shost_printk(KERN_ERR, shost,
+ "Cannot send SMP to a sas host (not enabled in CONFIG)\n");
+ return -EINVAL;
+}
+#endif
+
static inline void sas_queue_event(int event, spinlock_t *lock,
unsigned long *pending,
struct work_struct *work,
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 007d929..09125fa 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -11,10 +11,10 @@ struct sas_rphy;
struct request;
enum sas_device_type {
- SAS_PHY_UNUSED,
- SAS_END_DEVICE,
- SAS_EDGE_EXPANDER_DEVICE,
- SAS_FANOUT_EXPANDER_DEVICE,
+ SAS_PHY_UNUSED = 0,
+ SAS_END_DEVICE = 1,
+ SAS_EDGE_EXPANDER_DEVICE = 2,
+ SAS_FANOUT_EXPANDER_DEVICE = 3,
};
static inline int sas_protocol_ata(enum sas_protocol proto)
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] libsas: add host SMP processing
2007-12-28 23:36 [PATCH] libsas: add host SMP processing James Bottomley
@ 2007-12-29 5:24 ` FUJITA Tomonori
2007-12-29 15:44 ` James Bottomley
0 siblings, 1 reply; 6+ messages in thread
From: FUJITA Tomonori @ 2007-12-29 5:24 UTC (permalink / raw)
To: James.Bottomley; +Cc: linux-scsi, fujita.tomonori
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Subject: [PATCH] libsas: add host SMP processing
Date: Fri, 28 Dec 2007 17:36:38 -0600
> This patch allows the sas host device to accept SMP commands. This
> brings the libsas attached hosts on to a par with the firmware based
> ones like mptsas.
>
> James
>
> diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
> index c01a40d..18f33cd 100644
> --- a/drivers/scsi/libsas/Kconfig
> +++ b/drivers/scsi/libsas/Kconfig
> @@ -38,6 +38,15 @@ config SCSI_SAS_ATA
> Builds in ATA support into libsas. Will necessitate
> the loading of libata along with libsas.
>
> +config SCSI_SAS_HOST_SMP
> + bool "Support for SMP interpretation for SAS hosts"
> + default y
> + depends on SCSI_SAS_LIBSAS
> + help
> + Allows sas hosts to receive SMP frames. Selecting this
> + option builds an SMP interpreter into libsas. Say
> + N here if you want to save the few kb this consumes.
> +
> config SCSI_SAS_LIBSAS_DEBUG
> bool "Compile the SAS Domain Transport Attributes in debug mode"
> default y
> diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile
> index fd387b9..60d6e93 100644
> --- a/drivers/scsi/libsas/Makefile
> +++ b/drivers/scsi/libsas/Makefile
> @@ -35,3 +35,4 @@ libsas-y += sas_init.o \
> sas_expander.o \
> sas_scsi_host.o
> libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o
> +libsas-$(CONFIG_SCSI_SAS_HOST_SMP) += sas_host_smp.o
> \ No newline at end of file
> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
> index 27674fe..76555b1 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
> }
>
> /* no rphy means no smp target support (ie aic94xx host) */
> - if (!rphy) {
> - printk("%s: can we send a smp request to a host?\n",
> - __FUNCTION__);
> - return -EINVAL;
> - }
> + if (!rphy)
> + return sas_smp_host_handler(shost, req, rsp);
> +
I have one related question.
Currently, bsg doesn't return an error to user space since I had no
idea how to convert errors such as EINVAL and ENOMEM into
driver_status, transport_status, and device_status in struct sg_io_v4.
I think that it's confusing that bsg don't return an error even if SMP
requests aren't sent (e.g. devices are offline).
Do we need to map errors to the current error code in scsi/scsi.h
(like DID_*) or define a new one for SMP?
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] libsas: add host SMP processing
2007-12-29 5:24 ` FUJITA Tomonori
@ 2007-12-29 15:44 ` James Bottomley
2007-12-29 16:06 ` FUJITA Tomonori
0 siblings, 1 reply; 6+ messages in thread
From: James Bottomley @ 2007-12-29 15:44 UTC (permalink / raw)
To: FUJITA Tomonori; +Cc: linux-scsi, fujita.tomonori
On Sat, 2007-12-29 at 14:24 +0900, FUJITA Tomonori wrote:
> From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > --- a/drivers/scsi/libsas/sas_expander.c
> > +++ b/drivers/scsi/libsas/sas_expander.c
> > @@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
> > }
> >
> > /* no rphy means no smp target support (ie aic94xx host) */
> > - if (!rphy) {
> > - printk("%s: can we send a smp request to a host?\n",
> > - __FUNCTION__);
> > - return -EINVAL;
> > - }
> > + if (!rphy)
> > + return sas_smp_host_handler(shost, req, rsp);
> > +
>
> I have one related question.
>
> Currently, bsg doesn't return an error to user space since I had no
> idea how to convert errors such as EINVAL and ENOMEM into
> driver_status, transport_status, and device_status in struct sg_io_v4.
> I think that it's confusing that bsg don't return an error even if SMP
> requests aren't sent (e.g. devices are offline).
>
> Do we need to map errors to the current error code in scsi/scsi.h
> (like DID_*) or define a new one for SMP?
Neither, I think ... the DID codes are only for things that actually
pass through the SCSI stack. The way you implemented the smp functions
in bsg, they're direct queue handlers themselves (Incidentally, that's
another point about this: I think almost every use of bsg like this is
going to be for SG_IO only, so it makes sense to move the actual queue
handler into bsg, since they'll all share it).
The attached is the simplest patch that implements this. However, it
unfortunately can't be applied yet ... the current SMP tools send
receive buffers too large and libsas actually returns a data underrun
error (which is now propagated).
I'll fix it with a series of patches transferring the protocol handler
into bsg, adding error handling and correcting libsas.
James
diff --git a/block/bsg.c b/block/bsg.c
index 8e181ab..fbf0be3 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -837,6 +837,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct bsg_device *bd = file->private_data;
int __user *uarg = (int __user *) arg;
+ int ret;
switch (cmd) {
/*
@@ -889,12 +890,13 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (rq->next_rq)
bidi_bio = rq->next_rq->bio;
blk_execute_rq(bd->queue, NULL, rq, 0);
+ ret = rq->errors;
blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
if (copy_to_user(uarg, &hdr, sizeof(hdr)))
return -EFAULT;
- return 0;
+ return ret;
}
/*
* block device ioctls
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 87e786d..f2149d0 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -173,6 +173,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
handler = to_sas_internal(shost->transportt)->f->smp_handler;
ret = handler(shost, rphy, req);
+ req->errors = ret;
spin_lock_irq(q->queue_lock);
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] libsas: add host SMP processing
2007-12-29 15:44 ` James Bottomley
@ 2007-12-29 16:06 ` FUJITA Tomonori
2007-12-29 16:59 ` James Bottomley
0 siblings, 1 reply; 6+ messages in thread
From: FUJITA Tomonori @ 2007-12-29 16:06 UTC (permalink / raw)
To: James.Bottomley; +Cc: tomof, linux-scsi, fujita.tomonori
On Sat, 29 Dec 2007 09:44:32 -0600
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> On Sat, 2007-12-29 at 14:24 +0900, FUJITA Tomonori wrote:
> > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > --- a/drivers/scsi/libsas/sas_expander.c
> > > +++ b/drivers/scsi/libsas/sas_expander.c
> > > @@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
> > > }
> > >
> > > /* no rphy means no smp target support (ie aic94xx host) */
> > > - if (!rphy) {
> > > - printk("%s: can we send a smp request to a host?\n",
> > > - __FUNCTION__);
> > > - return -EINVAL;
> > > - }
> > > + if (!rphy)
> > > + return sas_smp_host_handler(shost, req, rsp);
> > > +
> >
> > I have one related question.
> >
> > Currently, bsg doesn't return an error to user space since I had no
> > idea how to convert errors such as EINVAL and ENOMEM into
> > driver_status, transport_status, and device_status in struct sg_io_v4.
> > I think that it's confusing that bsg don't return an error even if SMP
> > requests aren't sent (e.g. devices are offline).
> >
> > Do we need to map errors to the current error code in scsi/scsi.h
> > (like DID_*) or define a new one for SMP?
>
> Neither, I think ... the DID codes are only for things that actually
> pass through the SCSI stack. The way you implemented the smp functions
> in bsg, they're direct queue handlers themselves (Incidentally, that's
> another point about this: I think almost every use of bsg like this is
> going to be for SG_IO only, so it makes sense to move the actual queue
> handler into bsg, since they'll all share it).
>
> The attached is the simplest patch that implements this. However, it
> unfortunately can't be applied yet ... the current SMP tools send
> receive buffers too large and libsas actually returns a data underrun
> error (which is now propagated).
bsg read/write interface doens't return errors in this way (compatible
with sg3 read/write interface). If we support only SG_IO for non SCSI
request/response protocols, then that's fine.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] libsas: add host SMP processing
2007-12-29 16:06 ` FUJITA Tomonori
@ 2007-12-29 16:59 ` James Bottomley
2007-12-30 6:07 ` FUJITA Tomonori
0 siblings, 1 reply; 6+ messages in thread
From: James Bottomley @ 2007-12-29 16:59 UTC (permalink / raw)
To: FUJITA Tomonori; +Cc: linux-scsi, fujita.tomonori
On Sun, 2007-12-30 at 01:06 +0900, FUJITA Tomonori wrote:
> On Sat, 29 Dec 2007 09:44:32 -0600
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> > On Sat, 2007-12-29 at 14:24 +0900, FUJITA Tomonori wrote:
> > > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > > --- a/drivers/scsi/libsas/sas_expander.c
> > > > +++ b/drivers/scsi/libsas/sas_expander.c
> > > > @@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
> > > > }
> > > >
> > > > /* no rphy means no smp target support (ie aic94xx host) */
> > > > - if (!rphy) {
> > > > - printk("%s: can we send a smp request to a host?\n",
> > > > - __FUNCTION__);
> > > > - return -EINVAL;
> > > > - }
> > > > + if (!rphy)
> > > > + return sas_smp_host_handler(shost, req, rsp);
> > > > +
> > >
> > > I have one related question.
> > >
> > > Currently, bsg doesn't return an error to user space since I had no
> > > idea how to convert errors such as EINVAL and ENOMEM into
> > > driver_status, transport_status, and device_status in struct sg_io_v4.
> > > I think that it's confusing that bsg don't return an error even if SMP
> > > requests aren't sent (e.g. devices are offline).
> > >
> > > Do we need to map errors to the current error code in scsi/scsi.h
> > > (like DID_*) or define a new one for SMP?
> >
> > Neither, I think ... the DID codes are only for things that actually
> > pass through the SCSI stack. The way you implemented the smp functions
> > in bsg, they're direct queue handlers themselves (Incidentally, that's
> > another point about this: I think almost every use of bsg like this is
> > going to be for SG_IO only, so it makes sense to move the actual queue
> > handler into bsg, since they'll all share it).
> >
> > The attached is the simplest patch that implements this. However, it
> > unfortunately can't be applied yet ... the current SMP tools send
> > receive buffers too large and libsas actually returns a data underrun
> > error (which is now propagated).
>
> bsg read/write interface doens't return errors in this way (compatible
> with sg3 read/write interface). If we support only SG_IO for non SCSI
> request/response protocols, then that's fine.
OK, guilty of disliking the read/write interface (and therefore not
thinking about it). However, it's easy to fix. How about this? Note,
I think returning errors when they occur is more important than
preserving compatibility and swallowing the error somewhere, especially
as the bsg v3 interface *only* dealt with SCSI, so this is more like an
extension to non-scsi error returning. But if I'd had my way, bsg
wouldn't have had a read/write interface, so I'm happy to do whatever
people who actually use it want.
James
diff --git a/block/bsg.c b/block/bsg.c
index 8e181ab..69b0a9d 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -445,6 +445,15 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
else
hdr->dout_resid = rq->data_len;
+ /*
+ * If the request generated a negative error number, return it
+ * (providing we aren't already returning an error); if it's
+ * just a protocol response (i.e. non negative), that gets
+ * processed above.
+ */
+ if (!ret && rq->errors < 0)
+ ret = rq->errors;
+
blk_rq_unmap_user(bio);
blk_put_request(rq);
@@ -837,6 +846,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct bsg_device *bd = file->private_data;
int __user *uarg = (int __user *) arg;
+ int ret;
switch (cmd) {
/*
@@ -889,12 +899,12 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (rq->next_rq)
bidi_bio = rq->next_rq->bio;
blk_execute_rq(bd->queue, NULL, rq, 0);
- blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
+ ret = blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);
if (copy_to_user(uarg, &hdr, sizeof(hdr)))
return -EFAULT;
- return 0;
+ return ret;
}
/*
* block device ioctls
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 87e786d..f2149d0 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -173,6 +173,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
handler = to_sas_internal(shost->transportt)->f->smp_handler;
ret = handler(shost, rphy, req);
+ req->errors = ret;
spin_lock_irq(q->queue_lock);
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] libsas: add host SMP processing
2007-12-29 16:59 ` James Bottomley
@ 2007-12-30 6:07 ` FUJITA Tomonori
0 siblings, 0 replies; 6+ messages in thread
From: FUJITA Tomonori @ 2007-12-30 6:07 UTC (permalink / raw)
To: James.Bottomley; +Cc: tomof, linux-scsi, fujita.tomonori
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Subject: Re: [PATCH] libsas: add host SMP processing
Date: Sat, 29 Dec 2007 10:59:53 -0600
>
> On Sun, 2007-12-30 at 01:06 +0900, FUJITA Tomonori wrote:
> > On Sat, 29 Dec 2007 09:44:32 -0600
> > James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> >
> > > On Sat, 2007-12-29 at 14:24 +0900, FUJITA Tomonori wrote:
> > > > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > > > --- a/drivers/scsi/libsas/sas_expander.c
> > > > > +++ b/drivers/scsi/libsas/sas_expander.c
> > > > > @@ -1896,11 +1896,9 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
> > > > > }
> > > > >
> > > > > /* no rphy means no smp target support (ie aic94xx host) */
> > > > > - if (!rphy) {
> > > > > - printk("%s: can we send a smp request to a host?\n",
> > > > > - __FUNCTION__);
> > > > > - return -EINVAL;
> > > > > - }
> > > > > + if (!rphy)
> > > > > + return sas_smp_host_handler(shost, req, rsp);
> > > > > +
> > > >
> > > > I have one related question.
> > > >
> > > > Currently, bsg doesn't return an error to user space since I had no
> > > > idea how to convert errors such as EINVAL and ENOMEM into
> > > > driver_status, transport_status, and device_status in struct sg_io_v4.
> > > > I think that it's confusing that bsg don't return an error even if SMP
> > > > requests aren't sent (e.g. devices are offline).
> > > >
> > > > Do we need to map errors to the current error code in scsi/scsi.h
> > > > (like DID_*) or define a new one for SMP?
> > >
> > > Neither, I think ... the DID codes are only for things that actually
> > > pass through the SCSI stack. The way you implemented the smp functions
> > > in bsg, they're direct queue handlers themselves (Incidentally, that's
> > > another point about this: I think almost every use of bsg like this is
> > > going to be for SG_IO only, so it makes sense to move the actual queue
> > > handler into bsg, since they'll all share it).
> > >
> > > The attached is the simplest patch that implements this. However, it
> > > unfortunately can't be applied yet ... the current SMP tools send
> > > receive buffers too large and libsas actually returns a data underrun
> > > error (which is now propagated).
> >
> > bsg read/write interface doens't return errors in this way (compatible
> > with sg3 read/write interface). If we support only SG_IO for non SCSI
> > request/response protocols, then that's fine.
>
> OK, guilty of disliking the read/write interface (and therefore not
> thinking about it). However, it's easy to fix. How about this? Note,
> I think returning errors when they occur is more important than
> preserving compatibility and swallowing the error somewhere, especially
> as the bsg v3 interface *only* dealt with SCSI, so this is more like an
> extension to non-scsi error returning.
Oops, I remember wrongly. I've just realized that sgv3 returns errors
in this way (that is, returns negative values) though bsg doesn't (I
guess Jens did that because bsg read/write interface handle multiple
request/responses). There isn't the compatibility issue.
The patch looks fine.
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
> But if I'd had my way, bsg
> wouldn't have had a read/write interface, so I'm happy to do whatever
> people who actually use it want.
I don't like the read/write interface much but OSD people need an
efficient interface to perform SCSI commands (the interface should to
handle multiple requests/response at a time and work
asynchronously). Some of them seem to use bsg read/write interface. So
I guess that we to invent a substitute to kill the read/write
interface.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-12-30 6:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-28 23:36 [PATCH] libsas: add host SMP processing James Bottomley
2007-12-29 5:24 ` FUJITA Tomonori
2007-12-29 15:44 ` James Bottomley
2007-12-29 16:06 ` FUJITA Tomonori
2007-12-29 16:59 ` James Bottomley
2007-12-30 6:07 ` FUJITA Tomonori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox