X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Flibsas%2Fsas_expander.c;h=3da02e4367884b4f8fcc1015811b55b0bf88a968;hb=04489eeb02a40bc15029886cef7285ada3ab0de6;hp=969fd3eb494a7e3b9045f2c150336fd63dfe42d8;hpb=9d720d82dc295521d70939c3f5edd54050730f09;p=linux-2.6 diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 969fd3eb49..3da02e4367 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -23,6 +23,7 @@ */ #include +#include #include "sas_internal.h" @@ -36,14 +37,6 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, u8 *sas_addr, int include); static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); -#if 0 -/* FIXME: smp needs to migrate into the sas class */ -static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *, - char *, loff_t, size_t); -static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *, - char *, loff_t, size_t); -#endif - /* ---------- SMP task management ---------- */ static void smp_task_timedout(unsigned long _task) @@ -103,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); @@ -116,9 +109,19 @@ 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__, + "status 0x%x\n", __func__, SAS_ADDR(dev->sas_addr), task->task_status.resp, task->task_status.stat); @@ -514,13 +517,20 @@ static int sas_dev_present_in_domain(struct asd_sas_port *port, int sas_smp_get_phy_events(struct sas_phy *phy) { int res; + u8 *req; + u8 *resp; struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); struct domain_device *dev = sas_find_dev_by_rphy(rphy); - u8 *req = alloc_smp_req(RPEL_REQ_SIZE); - u8 *resp = kzalloc(RPEL_RESP_SIZE, GFP_KERNEL); - if (!resp) + req = alloc_smp_req(RPEL_REQ_SIZE); + if (!req) + return -ENOMEM; + + resp = alloc_smp_resp(RPEL_RESP_SIZE); + if (!resp) { + kfree(req); return -ENOMEM; + } req[1] = SMP_REPORT_PHY_ERR_LOG; req[9] = phy->number; @@ -542,6 +552,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy) } +#ifdef CONFIG_SCSI_SAS_ATA + #define RPS_REQ_SIZE 16 #define RPS_RESP_SIZE 60 @@ -585,6 +597,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev, kfree(rps_req); return res; } +#endif static void sas_ex_get_linkrate(struct domain_device *parent, struct domain_device *child, @@ -652,9 +665,10 @@ static struct domain_device *sas_ex_discover_end_dev( } sas_ex_get_linkrate(parent, child, phy); - if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { +#ifdef CONFIG_SCSI_SAS_ATA + 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; @@ -689,7 +703,9 @@ static struct domain_device *sas_ex_discover_end_dev( SAS_ADDR(parent->sas_addr), phy_id, res); goto out_list_del; } - } else if (phy->attached_tproto & SAS_PROTO_SSP) { + } else +#endif + if (phy->attached_tproto & SAS_PROTOCOL_SSP) { child->dev_type = SAS_END_DEV; rphy = sas_end_device_alloc(phy->port); /* FIXME: error handling */ @@ -717,6 +733,7 @@ static struct domain_device *sas_ex_discover_end_dev( SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", phy->attached_tproto, SAS_ADDR(parent->sas_addr), phy_id); + goto out_free; } list_add_tail(&child->siblings, &parent_ex->children); @@ -1262,7 +1279,7 @@ static int sas_configure_present(struct domain_device *dev, int phy_id, goto out; } else if (res != SMP_RESP_FUNC_ACC) { SAS_DPRINTK("%s: dev %016llx phy 0x%x index 0x%x " - "result 0x%x\n", __FUNCTION__, + "result 0x%x\n", __func__, SAS_ADDR(dev->sas_addr), phy_id, i, res); goto out; } @@ -1414,30 +1431,6 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) return 0; } -#if 0 -#define SMP_BIN_ATTR_NAME "smp_portal" - -static void sas_ex_smp_hook(struct domain_device *dev) -{ - struct expander_device *ex_dev = &dev->ex_dev; - struct bin_attribute *bin_attr = &ex_dev->smp_bin_attr; - - memset(bin_attr, 0, sizeof(*bin_attr)); - - bin_attr->attr.name = SMP_BIN_ATTR_NAME; - bin_attr->attr.mode = 0600; - - bin_attr->size = 0; - bin_attr->private = NULL; - bin_attr->read = smp_portal_read; - bin_attr->write= smp_portal_write; - bin_attr->mmap = NULL; - - ex_dev->smp_portal_pid = -1; - init_MUTEX(&ex_dev->smp_sema); -} -#endif - /** * sas_discover_expander -- expander discovery * @ex: pointer to expander domain device @@ -1899,76 +1892,57 @@ out: return res; } -#if 0 -/* ---------- SMP portal ---------- */ - -static ssize_t smp_portal_write(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t offs, size_t size) +int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, + struct request *req) { - struct domain_device *dev = to_dom_device(kobj); - struct expander_device *ex = &dev->ex_dev; - - if (offs != 0) - return -EFBIG; - else if (size == 0) - return 0; + struct domain_device *dev; + int ret, type; + struct request *rsp = req->next_rq; - down_interruptible(&ex->smp_sema); - if (ex->smp_req) - kfree(ex->smp_req); - ex->smp_req = kzalloc(size, GFP_USER); - if (!ex->smp_req) { - up(&ex->smp_sema); - return -ENOMEM; + if (!rsp) { + printk("%s: space for a smp response is missing\n", + __func__); + return -EINVAL; } - memcpy(ex->smp_req, buf, size); - ex->smp_req_size = size; - ex->smp_portal_pid = current->pid; - up(&ex->smp_sema); - return size; -} + /* no rphy means no smp target support (ie aic94xx host) */ + if (!rphy) + return sas_smp_host_handler(shost, req, rsp); -static ssize_t smp_portal_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t offs, size_t size) -{ - struct domain_device *dev = to_dom_device(kobj); - struct expander_device *ex = &dev->ex_dev; - u8 *smp_resp; - int res = -EINVAL; + type = rphy->identify.device_type; - /* XXX: sysfs gives us an offset of 0x10 or 0x8 while in fact - * it should be 0. - */ + if (type != SAS_EDGE_EXPANDER_DEVICE && + type != SAS_FANOUT_EXPANDER_DEVICE) { + printk("%s: can we send a smp request to a device?\n", + __func__); + return -EINVAL; + } - down_interruptible(&ex->smp_sema); - if (!ex->smp_req || ex->smp_portal_pid != current->pid) - goto out; + dev = sas_find_dev_by_rphy(rphy); + if (!dev) { + printk("%s: fail to find a domain_device?\n", __func__); + return -EINVAL; + } - res = 0; - if (size == 0) - goto out; + /* do we need to support multiple segments? */ + if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { + printk("%s: multiple segments req %u %u, rsp %u %u\n", + __func__, req->bio->bi_vcnt, req->data_len, + rsp->bio->bi_vcnt, rsp->data_len); + return -EINVAL; + } - res = -ENOMEM; - smp_resp = alloc_smp_resp(size); - if (!smp_resp) - goto out; - res = smp_execute_task(dev, ex->smp_req, ex->smp_req_size, - smp_resp, size); - if (!res) { - memcpy(buf, smp_resp, size); - res = size; + 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; } - kfree(smp_resp); -out: - kfree(ex->smp_req); - ex->smp_req = NULL; - ex->smp_req_size = 0; - ex->smp_portal_pid = -1; - up(&ex->smp_sema); - return res; + return ret; } -#endif