summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/Kconfig1
-rw-r--r--drivers/scsi/libsas/sas_ata.c1
-rw-r--r--drivers/scsi/libsas/sas_expander.c70
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c106
-rw-r--r--drivers/scsi/libsas/sas_internal.h12
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c15
6 files changed, 91 insertions, 114 deletions
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index 9dafe64e7c7a..13739bfacc67 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -26,6 +26,7 @@ config SCSI_SAS_LIBSAS
tristate "SAS Domain Transport Attributes"
depends on SCSI
select SCSI_SAS_ATTRS
+ select BLK_DEV_BSGLIB
help
This provides transport specific helpers for SAS drivers which
use the domain device construct (like the aic94xxx).
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 87f5e694dbed..70be4425ae0b 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -343,6 +343,7 @@ static int smp_ata_check_ready(struct ata_link *link)
case SAS_END_DEVICE:
if (ex_phy->attached_sata_dev)
return sas_ata_clear_pending(dev, ex_phy);
+ /* fall through */
default:
return -ENODEV;
}
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 570b2cb2da43..6b4fd2375178 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -64,8 +64,8 @@ static void smp_task_done(struct sas_task *task)
/* Give it some long enough timeout. In seconds. */
#define SMP_TIMEOUT 10
-static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
- void *resp, int resp_size)
+static int smp_execute_task_sg(struct domain_device *dev,
+ struct scatterlist *req, struct scatterlist *resp)
{
int res, retry;
struct sas_task *task = NULL;
@@ -86,8 +86,8 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
}
task->dev = dev;
task->task_proto = dev->tproto;
- sg_init_one(&task->smp_task.smp_req, req, req_size);
- sg_init_one(&task->smp_task.smp_resp, resp, resp_size);
+ task->smp_task.smp_req = *req;
+ task->smp_task.smp_resp = *resp;
task->task_done = smp_task_done;
@@ -151,6 +151,17 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
return res;
}
+static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
+ void *resp, int resp_size)
+{
+ struct scatterlist req_sg;
+ struct scatterlist resp_sg;
+
+ sg_init_one(&req_sg, req, req_size);
+ sg_init_one(&resp_sg, resp, resp_size);
+ return smp_execute_task_sg(dev, &req_sg, &resp_sg);
+}
+
/* ---------- Allocations ---------- */
static inline void *alloc_smp_req(int size)
@@ -2130,57 +2141,50 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
return res;
}
-int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
- struct request *req)
+void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
+ struct sas_rphy *rphy)
{
struct domain_device *dev;
- int ret, type;
- struct request *rsp = req->next_rq;
-
- if (!rsp) {
- printk("%s: space for a smp response is missing\n",
- __func__);
- return -EINVAL;
- }
+ unsigned int reslen = 0;
+ int ret = -EINVAL;
/* no rphy means no smp target support (ie aic94xx host) */
if (!rphy)
- return sas_smp_host_handler(shost, req, rsp);
-
- type = rphy->identify.device_type;
+ return sas_smp_host_handler(job, shost);
- if (type != SAS_EDGE_EXPANDER_DEVICE &&
- type != SAS_FANOUT_EXPANDER_DEVICE) {
+ switch (rphy->identify.device_type) {
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
+ break;
+ default:
printk("%s: can we send a smp request to a device?\n",
__func__);
- return -EINVAL;
+ goto out;
}
dev = sas_find_dev_by_rphy(rphy);
if (!dev) {
printk("%s: fail to find a domain_device?\n", __func__);
- return -EINVAL;
+ goto out;
}
/* do we need to support multiple segments? */
- if (bio_multiple_segments(req->bio) ||
- bio_multiple_segments(rsp->bio)) {
+ if (job->request_payload.sg_cnt > 1 ||
+ job->reply_payload.sg_cnt > 1) {
printk("%s: multiple segments req %u, rsp %u\n",
- __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));
- return -EINVAL;
+ __func__, job->request_payload.payload_len,
+ job->reply_payload.payload_len);
+ goto out;
}
- ret = smp_execute_task(dev, bio_data(req->bio), blk_rq_bytes(req),
- bio_data(rsp->bio), blk_rq_bytes(rsp));
+ ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
+ job->reply_payload.sg_list);
if (ret > 0) {
/* positive number is the untransferred residual */
- scsi_req(rsp)->resid_len = ret;
- scsi_req(req)->resid_len = 0;
+ reslen = ret;
ret = 0;
- } else if (ret == 0) {
- scsi_req(rsp)->resid_len = 0;
- scsi_req(req)->resid_len = 0;
}
- return ret;
+out:
+ bsg_job_done(job, ret, reslen);
}
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 45cbbc44f4d7..9ead93df3a6e 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -225,47 +225,36 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
resp_data[2] = SMP_RESP_FUNC_ACC;
}
-int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
- struct request *rsp)
+void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost)
{
- u8 *req_data = NULL, *resp_data = NULL, *buf;
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+ u8 *req_data, *resp_data;
+ unsigned int reslen = 0;
int error = -EINVAL;
/* eight is the minimum size for request and response frames */
- if (blk_rq_bytes(req) < 8 || blk_rq_bytes(rsp) < 8)
+ if (job->request_payload.payload_len < 8 ||
+ job->reply_payload.payload_len < 8)
goto out;
- if (bio_offset(req->bio) + blk_rq_bytes(req) > PAGE_SIZE ||
- bio_offset(rsp->bio) + blk_rq_bytes(rsp) > PAGE_SIZE) {
- shost_printk(KERN_ERR, shost,
- "SMP request/response frame crosses page boundary");
+ error = -ENOMEM;
+ req_data = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
+ if (!req_data)
goto out;
- }
-
- req_data = kzalloc(blk_rq_bytes(req), GFP_KERNEL);
+ sg_copy_to_buffer(job->request_payload.sg_list,
+ job->request_payload.sg_cnt, req_data,
+ job->request_payload.payload_len);
/* make sure frame can always be built ... we copy
* back only the requested length */
- resp_data = kzalloc(max(blk_rq_bytes(rsp), 128U), GFP_KERNEL);
-
- if (!req_data || !resp_data) {
- error = -ENOMEM;
- goto out;
- }
-
- local_irq_disable();
- buf = kmap_atomic(bio_page(req->bio));
- memcpy(req_data, buf, blk_rq_bytes(req));
- kunmap_atomic(buf - bio_offset(req->bio));
- local_irq_enable();
+ resp_data = kzalloc(max(job->reply_payload.payload_len, 128U),
+ GFP_KERNEL);
+ if (!resp_data)
+ goto out_free_req;
+ error = -EINVAL;
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;
+ goto out_free_resp;
/* set up default don't know response */
resp_data[0] = SMP_RESPONSE;
@@ -274,20 +263,18 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
switch (req_data[1]) {
case SMP_REPORT_GENERAL:
- scsi_req(req)->resid_len -= 8;
- scsi_req(rsp)->resid_len -= 32;
resp_data[2] = SMP_RESP_FUNC_ACC;
resp_data[9] = sas_ha->num_phys;
+ reslen = 32;
break;
case SMP_REPORT_MANUF_INFO:
- scsi_req(req)->resid_len -= 8;
- scsi_req(rsp)->resid_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);
+ reslen = 64;
break;
case SMP_READ_GPIO_REG:
@@ -295,14 +282,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_DISCOVER:
- scsi_req(req)->resid_len -= 16;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 56;
+ if (job->request_payload.payload_len < 16)
+ goto out_free_resp;
sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
+ reslen = 56;
break;
case SMP_REPORT_PHY_ERR_LOG:
@@ -311,14 +294,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_REPORT_PHY_SATA:
- scsi_req(req)->resid_len -= 16;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 60;
+ if (job->request_payload.payload_len < 16)
+ goto out_free_resp;
sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
+ reslen = 60;
break;
case SMP_REPORT_ROUTE_INFO:
@@ -330,16 +309,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
const int base_frame_size = 11;
int to_write = req_data[4];
- if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
- scsi_req(req)->resid_len < base_frame_size + to_write * 4) {
+ if (job->request_payload.payload_len <
+ base_frame_size + to_write * 4) {
resp_data[2] = SMP_RESP_INV_FRM_LEN;
break;
}
to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
req_data[3], to_write, &req_data[8]);
- scsi_req(req)->resid_len -= base_frame_size + to_write * 4;
- scsi_req(rsp)->resid_len -= 8;
+ reslen = 8;
break;
}
@@ -348,16 +326,12 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_PHY_CONTROL:
- scsi_req(req)->resid_len -= 44;
- if ((int)scsi_req(req)->resid_len < 0) {
- scsi_req(req)->resid_len = 0;
- error = -EINVAL;
- goto out;
- }
- scsi_req(rsp)->resid_len -= 8;
+ if (job->request_payload.payload_len < 44)
+ goto out_free_resp;
sas_phy_control(sas_ha, req_data[9], req_data[10],
req_data[32] >> 4, req_data[33] >> 4,
resp_data);
+ reslen = 8;
break;
case SMP_PHY_TEST_FUNCTION:
@@ -369,15 +343,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
}
- local_irq_disable();
- buf = kmap_atomic(bio_page(rsp->bio));
- memcpy(buf, resp_data, blk_rq_bytes(rsp));
- flush_kernel_dcache_page(bio_page(rsp->bio));
- kunmap_atomic(buf - bio_offset(rsp->bio));
- local_irq_enable();
+ sg_copy_from_buffer(job->reply_payload.sg_list,
+ job->reply_payload.sg_cnt, resp_data,
+ job->reply_payload.payload_len);
- out:
- kfree(req_data);
+ error = 0;
+out_free_resp:
kfree(resp_data);
- return error;
+out_free_req:
+ kfree(req_data);
+out:
+ bsg_job_done(job, error, reslen);
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index a216c957b639..c07e08136491 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -81,6 +81,8 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw);
int sas_notify_lldd_dev_found(struct domain_device *);
void sas_notify_lldd_dev_gone(struct domain_device *);
+void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
+ struct sas_rphy *rphy);
int sas_smp_phy_control(struct domain_device *dev, int phy_id,
enum phy_func phy_func, struct sas_phy_linkrates *);
int sas_smp_get_phy_events(struct sas_phy *phy);
@@ -98,16 +100,14 @@ void sas_hae_reset(struct work_struct *work);
void sas_free_device(struct kref *kref);
#ifdef CONFIG_SCSI_SAS_HOST_SMP
-extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
- struct request *rsp);
+extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost);
#else
-static inline int sas_smp_host_handler(struct Scsi_Host *shost,
- struct request *req,
- struct request *rsp)
+static inline void sas_smp_host_handler(struct bsg_job *job,
+ struct Scsi_Host *shost)
{
shost_printk(KERN_ERR, shost,
"Cannot send SMP to a sas host (not enabled in CONFIG)\n");
- return -EINVAL;
+ bsg_job_done(job, -EINVAL, 0);
}
#endif
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 87e5079d816b..ea8ad06ff582 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -526,7 +526,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
return FAILED;
}
-int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
+int sas_eh_target_reset_handler(struct scsi_cmnd *cmd)
{
int res;
struct Scsi_Host *host = cmd->device->host;
@@ -554,15 +554,15 @@ static int try_to_reset_cmd_device(struct scsi_cmnd *cmd)
struct Scsi_Host *shost = cmd->device->host;
if (!shost->hostt->eh_device_reset_handler)
- goto try_bus_reset;
+ goto try_target_reset;
res = shost->hostt->eh_device_reset_handler(cmd);
if (res == SUCCESS)
return res;
-try_bus_reset:
- if (shost->hostt->eh_bus_reset_handler)
- return shost->hostt->eh_bus_reset_handler(cmd);
+try_target_reset:
+ if (shost->hostt->eh_target_reset_handler)
+ return shost->hostt->eh_target_reset_handler(cmd);
return FAILED;
}
@@ -855,7 +855,6 @@ int sas_target_alloc(struct scsi_target *starget)
int sas_slave_configure(struct scsi_device *scsi_dev)
{
struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
- struct sas_ha_struct *sas_ha;
BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE);
@@ -864,8 +863,6 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
return 0;
}
- sas_ha = dev->port->ha;
-
sas_read_port_mode_page(scsi_dev);
if (scsi_dev->tagged_supported) {
@@ -996,6 +993,6 @@ EXPORT_SYMBOL_GPL(sas_bios_param);
EXPORT_SYMBOL_GPL(sas_task_abort);
EXPORT_SYMBOL_GPL(sas_phy_reset);
EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
-EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
+EXPORT_SYMBOL_GPL(sas_eh_target_reset_handler);
EXPORT_SYMBOL_GPL(sas_target_destroy);
EXPORT_SYMBOL_GPL(sas_ioctl);