From 5929faf3334f4c69f3bb02be59d7c127e0cefa1f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 5 Nov 2007 11:51:17 -0800 Subject: [SCSI] libsas: Convert sas_proto users to sas_protocol sparse complains about the mixing of enums in libsas. Since the underlying numeric values of both enums are the same, combine them to get rid of the warning. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_discover.c | 2 +- drivers/scsi/libsas/sas_expander.c | 6 +++--- drivers/scsi/libsas/sas_internal.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 5f3a0d7b18d..31b9af22424 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -98,7 +98,7 @@ static int sas_get_port_device(struct asd_sas_port *port) dev->dev_type = SATA_PM; else dev->dev_type = SATA_DEV; - dev->tproto = SATA_PROTO; + dev->tproto = SAS_PROTOCOL_SATA; } else { struct sas_identify_frame *id = (struct sas_identify_frame *) dev->frame_rcvd; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 8727436b222..27674fe468f 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -656,9 +656,9 @@ static struct domain_device *sas_ex_discover_end_dev( sas_ex_get_linkrate(parent, child, phy); #ifdef CONFIG_SCSI_SAS_ATA - if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { + if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { child->dev_type = SATA_DEV; - if (phy->attached_tproto & SAS_PROTO_STP) + if (phy->attached_tproto & SAS_PROTOCOL_STP) child->tproto = phy->attached_tproto; if (phy->attached_sata_dev) child->tproto |= SATA_DEV; @@ -695,7 +695,7 @@ static struct domain_device *sas_ex_discover_end_dev( } } else #endif - if (phy->attached_tproto & SAS_PROTO_SSP) { + if (phy->attached_tproto & SAS_PROTOCOL_SSP) { child->dev_type = SAS_END_DEV; rphy = sas_end_device_alloc(phy->port); /* FIXME: error handling */ diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 2b8213b1832..baa0666ffa8 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -45,7 +45,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost); int sas_show_class(enum sas_class class, char *buf); -int sas_show_proto(enum sas_proto proto, char *buf); +int sas_show_proto(enum sas_protocol proto, char *buf); int sas_show_linkrate(enum sas_linkrate linkrate, char *buf); int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf); -- cgit v1.2.3-70-g09d2 From 8ee24023ef43c77cdaea1add00e1e45cc4fc3261 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 5 Nov 2007 11:52:14 -0800 Subject: [SCSI] libsas: Fix various sparse complaints Annotate sas_queuecommand with locking details, and clean up a few more sparse warnings about static/non-static declarations. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 6 +++++- include/scsi/libsas.h | 4 +--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 7663841eb4c..b784089b18d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -200,6 +200,10 @@ int sas_queue_up(struct sas_task *task) */ int sas_queuecommand(struct scsi_cmnd *cmd, void (*scsi_done)(struct scsi_cmnd *)) + __releases(host->host_lock) + __acquires(dev->sata_dev.ap->lock) + __releases(dev->sata_dev.ap->lock) + __acquires(host->host_lock) { int res = 0; struct domain_device *dev = cmd_to_domain_dev(cmd); @@ -410,7 +414,7 @@ static int sas_recover_I_T(struct domain_device *dev) } /* Find the sas_phy that's attached to this device */ -struct sas_phy *find_local_sas_phy(struct domain_device *dev) +static struct sas_phy *find_local_sas_phy(struct domain_device *dev) { struct domain_device *pdev = dev->parent; struct ex_phy *exphy = NULL; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index e42374cebf9..93248cd4837 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -563,7 +563,7 @@ struct sas_task { struct work_struct abort_work; }; - +extern struct kmem_cache *sas_task_cache; #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 @@ -573,7 +573,6 @@ struct sas_task { static inline struct sas_task *sas_alloc_task(gfp_t flags) { - extern struct kmem_cache *sas_task_cache; struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags); if (task) { @@ -590,7 +589,6 @@ static inline struct sas_task *sas_alloc_task(gfp_t flags) static inline void sas_free_task(struct sas_task *task) { if (task) { - extern struct kmem_cache *sas_task_cache; BUG_ON(!list_empty(&task->list)); kmem_cache_free(sas_task_cache, task); } -- cgit v1.2.3-70-g09d2 From b98e66fa0b687149dc3b26179096dc542c7d5001 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 28 Dec 2007 16:35:17 -0600 Subject: [SCSI] libsas: add host SMP processing This adds support for host side SMP processing, via a separate SMP interpreter file. Signed-off-by: James Bottomley --- drivers/scsi/libsas/Kconfig | 9 ++ drivers/scsi/libsas/Makefile | 1 + drivers/scsi/libsas/sas_expander.c | 8 +- drivers/scsi/libsas/sas_host_smp.c | 274 +++++++++++++++++++++++++++++++++++++ drivers/scsi/libsas/sas_internal.h | 14 ++ include/scsi/scsi_transport_sas.h | 8 +- 6 files changed, 305 insertions(+), 9 deletions(-) create mode 100644 drivers/scsi/libsas/sas_host_smp.c (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig index c01a40d321d..18f33cd5441 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 fd387b91856..60d6e93dd94 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 27674fe468f..76555b1ddfd 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 00000000000..16f93123271 --- /dev/null +++ b/drivers/scsi/libsas/sas_host_smp.c @@ -0,0 +1,274 @@ +/* + * Serial Attached SCSI (SAS) Expander discovery and configuration + * + * Copyright (C) 2007 James E.J. Bottomley + * + * + * 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 +#include + +#include "sas_internal.h" + +#include +#include +#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 || + !sas_ha->sas_phy[phy_id]->port->port_dev) + 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, resp_data_len = rsp->data_len; + + /* 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: + req->data_len -= 8; + resp_data_len -= 32; + resp_data[2] = SMP_RESP_FUNC_ACC; + resp_data[9] = sas_ha->num_phys; + break; + + case SMP_REPORT_MANUF_INFO: + req->data_len -= 8; + resp_data_len -= 64; + 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: + req->data_len =- 16; + if (req->data_len < 0) { + req->data_len = 0; + error = -EINVAL; + goto out; + } + resp_data_len -= 56; + 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: + req->data_len =- 16; + if (req->data_len < 0) { + req->data_len = 0; + error = -EINVAL; + goto out; + } + resp_data_len -= 60; + 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: + req->data_len =- 44; + if (req->data_len < 0) { + req->data_len = 0; + error = -EINVAL; + goto out; + } + resp_data_len -= 8; + 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(); + rsp->data_len = resp_data_len; + + 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 baa0666ffa8..b4f9368f116 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 007d9290420..09125fa95b9 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) -- cgit v1.2.3-70-g09d2 From 2d4b63e1505b317d4253cee3f2970792ec6d41cb Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 29 Dec 2007 11:49:53 -0600 Subject: [SCSI] libsas: don't treat underrun as an error on SMP tasks All SMP tasks sent through bsg generate messages like: sas: smp_execute_task: task to dev 500605b000001450 response: 0x0 status 0x81 Three times (because the task gets retried). Firstly, don't retry either overrun or underrun (the data buffer isn't going to change size) and secondly, just report the underrun but don't set an error for it. This is necessary so bsg can report back the residual. Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_expander.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 76555b1ddfd..8aeaad95242 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -109,6 +109,16 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, task->task_status.stat == SAM_GOOD) { res = 0; break; + } if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAS_DATA_UNDERRUN) { + /* no error, but return the number of bytes of + * underrun */ + res = task->task_status.residual; + break; + } if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAS_DATA_OVERRUN) { + res = -EMSGSIZE; + break; } else { SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " "status 0x%x\n", __FUNCTION__, @@ -1924,6 +1934,15 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, bio_data(rsp->bio), rsp->data_len); + if (ret > 0) { + /* positive number is the untransferred residual */ + rsp->data_len = ret; + req->data_len = 0; + ret = 0; + } else if (ret == 0) { + rsp->data_len = 0; + req->data_len = 0; + } return ret; } -- cgit v1.2.3-70-g09d2 From 32e8ae36b8f80372015b88b63c4358a376c9af0f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Dec 2007 12:37:31 -0600 Subject: [SCSI] libsas: don't use made up error codes This is bad for two reasons: 1. If they're returned to outside applications, no-one knows what they mean. 2. Eventually they'll clash with the ever expanding standard error codes. The problem error code in question is ETASK. I've replaced this by ECOMM (communications error on send) a network error code that seems to most closely relay what ETASK meant. Acked-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_expander.c | 2 +- include/scsi/libsas.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 0829b55c64d..adc47d481f9 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -500,7 +500,7 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, goto ex_err; } wait_for_completion(&task->completion); - res = -ETASK; + res = -ECOMM; if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { int res2; SAS_DPRINTK("task aborted, flags:0x%x\n", diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 8aeaad95242..aefd865a578 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -96,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, } wait_for_completion(&task->completion); - res = -ETASK; + res = -ECOMM; if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { SAS_DPRINTK("smp task timed out or aborted\n"); i->dft->lldd_abort_task(task); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 93248cd4837..a075f130303 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -91,8 +91,6 @@ enum discover_event { /* ---------- Expander Devices ---------- */ -#define ETASK 0xFA - #define to_dom_device(_obj) container_of(_obj, struct domain_device, dev_obj) #define to_dev_attr(_attr) container_of(_attr, struct domain_dev_attribute,\ attr) -- cgit v1.2.3-70-g09d2 From cc75e8ab6f262a3ea60e8d8268f48da5365f2823 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 13 Jan 2008 02:20:18 +0900 Subject: [SCSI] libsas: fix sense_buffer overrun Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index b784089b18d..828fed1114e 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -108,7 +108,7 @@ static void sas_scsi_task_done(struct sas_task *task) break; case SAM_CHECK_COND: memcpy(sc->sense_buffer, ts->buf, - max(SCSI_SENSE_BUFFERSIZE, ts->buf_valid_size)); + min(SCSI_SENSE_BUFFERSIZE, ts->buf_valid_size)); stat = SAM_CHECK_COND; break; default: -- cgit v1.2.3-70-g09d2 From 94aa5e5f6251ca0e1d77e083f8c2f9f40ee548c5 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 13 Jan 2008 15:46:12 +0900 Subject: [SCSI] aic7xxx_old, eata_pio, ips, libsas: don't zero out sense_buffer in queuecommand LLDs don't need to zero out scsi_cmnd::sense_buffer in queuecommand since scsi-ml does. This is a preparation of the future changes to allocate the sense_buffer only when necessary. Many LLDs zero out the sense_buffer before touching it on the error case. This patch lets them alone for now because new APIs for them would be added later on. Signed-off-by: FUJITA Tomonori Acked-by: "Salyzyn, Mark" Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx_old.c | 1 - drivers/scsi/eata_pio.c | 1 - drivers/scsi/ips.c | 3 --- drivers/scsi/libsas/sas_scsi_host.c | 1 - 4 files changed, 6 deletions(-) (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 8f8db5f0aef..2b402fafd00 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -10293,7 +10293,6 @@ static int aic7xxx_queue(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) aic7xxx_position(cmd) = scb->hscb->tag; cmd->scsi_done = fn; cmd->result = DID_OK; - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); aic7xxx_error(cmd) = DID_OK; aic7xxx_status(cmd) = 0; cmd->host_scribble = NULL; diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 9579507f555..b5a60926e55 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -369,7 +369,6 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, cp = &hd->ccb[y]; memset(cp, 0, sizeof(struct eata_ccb)); - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); cp->status = USED; /* claim free slot */ diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index e54d30c6a34..b1b22950611 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -2736,8 +2736,6 @@ ips_next(ips_ha_t * ha, int intr) SC->result = DID_OK; SC->host_scribble = NULL; - memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer)); - scb->target_id = SC->device->id; scb->lun = SC->device->lun; scb->bus = SC->device->channel; @@ -3821,7 +3819,6 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb) /* attempted, a Check Condition occurred, and Sense */ /* Data indicating an Invalid CDB OpCode is returned. */ sp = (char *) scb->scsi_cmd->sense_buffer; - memset(sp, 0, sizeof (scb->scsi_cmd->sense_buffer)); sp[0] = 0x70; /* Error Code */ sp[2] = ILLEGAL_REQUEST; /* Sense Key 5 Illegal Req. */ diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 828fed1114e..9c042254633 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -148,7 +148,6 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd, if (!task) return NULL; - *(u32 *)cmd->sense_buffer = 0; task->uldd_task = cmd; ASSIGN_SAS_TASK(cmd, task); -- cgit v1.2.3-70-g09d2 From 366ca51f30de1cbb5b356c70b7bb22051c558e41 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 18 Jan 2008 10:47:01 -0600 Subject: [SCSI] libsas: abstract STP task status into a function Break out the frame processor for STP tasks from aic94xx so they can be shared by other SAS HBA's Original patch from Jeff Garzik Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_task.c | 20 ++------------------ drivers/scsi/libsas/Makefile | 3 ++- drivers/scsi/libsas/sas_task.c | 36 ++++++++++++++++++++++++++++++++++++ include/scsi/libsas.h | 4 ++++ 4 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 drivers/scsi/libsas/sas_task.c (limited to 'drivers/scsi/libsas') diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index 663fdef38c5..965d4bb999d 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -192,24 +192,8 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb, r + 16 + sizeof(struct ssp_frame_hdr); ts->residual = le32_to_cpu(*(__le32 *)r); - ts->resp = SAS_TASK_COMPLETE; - if (iu->datapres == 0) - ts->stat = iu->status; - else if (iu->datapres == 1) - ts->stat = iu->resp_data[3]; - else if (iu->datapres == 2) { - ts->stat = SAM_CHECK_COND; - ts->buf_valid_size = min((u32) SAS_STATUS_BUF_SIZE, - be32_to_cpu(iu->sense_data_len)); - memcpy(ts->buf, iu->sense_data, ts->buf_valid_size); - if (iu->status != SAM_CHECK_COND) { - ASD_DPRINTK("device %llx sent sense data, but " - "stat(0x%x) is not CHECK_CONDITION" - "\n", - SAS_ADDR(task->dev->sas_addr), - iu->status); - } - } + + sas_ssp_task_response(&asd_ha->pcidev->dev, task, iu); } else { struct ata_task_resp *resp = (void *) &ts->buf[0]; diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile index 60d6e93dd94..1ad1323c60f 100644 --- a/drivers/scsi/libsas/Makefile +++ b/drivers/scsi/libsas/Makefile @@ -33,6 +33,7 @@ libsas-y += sas_init.o \ sas_dump.o \ sas_discover.o \ sas_expander.o \ - sas_scsi_host.o + sas_scsi_host.o \ + sas_task.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_task.c b/drivers/scsi/libsas/sas_task.c new file mode 100644 index 00000000000..594524d5bfa --- /dev/null +++ b/drivers/scsi/libsas/sas_task.c @@ -0,0 +1,36 @@ +#include +#include +#include + +/* fill task_status_struct based on SSP response frame */ +void sas_ssp_task_response(struct device *dev, struct sas_task *task, + struct ssp_response_iu *iu) +{ + struct task_status_struct *tstat = &task->task_status; + + tstat->resp = SAS_TASK_COMPLETE; + + if (iu->datapres == 0) + tstat->stat = iu->status; + else if (iu->datapres == 1) + tstat->stat = iu->resp_data[3]; + else if (iu->datapres == 2) { + tstat->stat = SAM_CHECK_COND; + tstat->buf_valid_size = + min_t(int, SAS_STATUS_BUF_SIZE, + be32_to_cpu(iu->sense_data_len)); + memcpy(tstat->buf, iu->sense_data, tstat->buf_valid_size); + + if (iu->status != SAM_CHECK_COND) + dev_printk(KERN_WARNING, dev, + "dev %llx sent sense data, but " + "stat(%x) is not CHECK CONDITION\n", + SAS_ADDR(task->dev->sas_addr), + iu->status); + } + else + /* when datapres contains corrupt/unknown value... */ + tstat->stat = SAM_CHECK_COND; +} +EXPORT_SYMBOL_GPL(sas_ssp_task_response); + diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index a075f130303..3ffd6b582a9 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -672,4 +672,8 @@ extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, struct request *req); + +extern void sas_ssp_task_response(struct device *dev, struct sas_task *task, + struct ssp_response_iu *iu); + #endif /* _SASLIB_H_ */ -- cgit v1.2.3-70-g09d2