* [PATCH v6 1/7] libsas: fix sas_unregister_ports vs sas_drain_work
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
@ 2012-01-21 1:50 ` Dan Williams
2012-01-21 1:50 ` [PATCH v6 2/7] libsas: improve ata debug statements Dan Williams
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:50 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide, Jacek Danecki
We need to hold drain_mutex across the unregistration as port down events
queue device removal as chained events, so we need to make sure no other
drainers are active.
[ 1118.673968] WARNING: at kernel/workqueue.c:996 __queue_work+0x11a/0x326()
[ 1118.681982] Hardware name: S2600CP
[ 1118.686193] Modules linked in: isci(-) libsas scsi_transport_sas nls_utf8
ipv6 uinput sg iTCO_wdt iTCO_vendor_support i2c_i801 i2c_core ioatdma dca
sd_mod sr_mod cdrom ahci libahci libata [last unloaded: scsi_transport_sas]
[ 1118.709893] Pid: 6831, comm: rmmod Not tainted 3.2.0-isci+ #1
[ 1118.716727] Call Trace:
[ 1118.719867] [<ffffffff8103e9f5>] warn_slowpath_common+0x85/0x9d
[ 1118.727000] [<ffffffff8103ea27>] warn_slowpath_null+0x1a/0x1c
[ 1118.733942] [<ffffffff81056d44>] __queue_work+0x11a/0x326
[ 1118.740481] [<ffffffff81056f99>] queue_work_on+0x1b/0x22
[ 1118.746925] [<ffffffff81057106>] queue_work+0x37/0x3e
[ 1118.753105] [<ffffffffa0120e05>] ? sas_discover_event+0x55/0x82 [libsas]
[ 1118.761094] [<ffffffff813217c3>] scsi_queue_work+0x42/0x44
[ 1118.767717] [<ffffffffa0120e19>] sas_discover_event+0x69/0x82 [libsas]
[ 1118.775509] [<ffffffffa0120f5b>] sas_unregister_dev+0xc3/0xcc [libsas]
[ 1118.783319] [<ffffffffa0120fae>] sas_unregister_domain_devices+0x4a/0xc8 [libsas]
[ 1118.792731] [<ffffffffa0120071>] sas_deform_port+0x60/0x1a6 [libsas]
[ 1118.800339] [<ffffffffa01201ea>] sas_unregister_ports+0x33/0x44 [libsas]
[ 1118.808342] [<ffffffffa011f7e5>] sas_unregister_ha+0x41/0x6b [libsas]
[ 1118.816055] [<ffffffffa0134055>] isci_unregister+0x22/0x4d [isci]
[ 1118.823384] [<ffffffffa0143040>] isci_pci_remove+0x2e/0x60 [isci]
Reported-by: Jacek Danecki <jacek.danecki@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_event.c | 19 +++++++++++++------
drivers/scsi/libsas/sas_init.c | 18 +++++++++++-------
drivers/scsi/libsas/sas_internal.h | 1 +
3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index dbfacee..16639bb 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -51,15 +51,11 @@ static void sas_queue_event(int event, unsigned long *pending,
}
}
-int sas_drain_work(struct sas_ha_struct *ha)
+
+void __sas_drain_work(struct sas_ha_struct *ha)
{
struct workqueue_struct *wq = ha->core.shost->work_q;
struct work_struct *w, *_w;
- int err;
-
- err = mutex_lock_interruptible(&ha->drain_mutex);
- if (err)
- return err;
set_bit(SAS_HA_DRAINING, &ha->state);
/* flush submitters */
@@ -75,6 +71,17 @@ int sas_drain_work(struct sas_ha_struct *ha)
sas_queue_work(ha, w);
}
spin_unlock_irq(&ha->state_lock);
+}
+
+int sas_drain_work(struct sas_ha_struct *ha)
+{
+ int err;
+
+ err = mutex_lock_interruptible(&ha->drain_mutex);
+ if (err)
+ return err;
+ if (test_bit(SAS_HA_REGISTERED, &ha->state))
+ __sas_drain_work(ha);
mutex_unlock(&ha->drain_mutex);
return 0;
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index dc93e118..09c14ca 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -160,18 +160,22 @@ Undo_phys:
int sas_unregister_ha(struct sas_ha_struct *sas_ha)
{
- unsigned long flags;
-
/* Set the state to unregistered to avoid further unchained
- * events to be queued
+ * events to be queued, and flush any in-progress drainers
*/
- spin_lock_irqsave(&sas_ha->state_lock, flags);
+ mutex_lock(&sas_ha->drain_mutex);
+ spin_lock_irq(&sas_ha->state_lock);
clear_bit(SAS_HA_REGISTERED, &sas_ha->state);
- spin_unlock_irqrestore(&sas_ha->state_lock, flags);
- sas_drain_work(sas_ha);
+ spin_unlock_irq(&sas_ha->state_lock);
+ __sas_drain_work(sas_ha);
+ mutex_unlock(&sas_ha->drain_mutex);
sas_unregister_ports(sas_ha);
- sas_drain_work(sas_ha);
+
+ /* flush unregistration work */
+ mutex_lock(&sas_ha->drain_mutex);
+ __sas_drain_work(sas_ha);
+ mutex_unlock(&sas_ha->drain_mutex);
if (sas_ha->lldd_max_execute_num > 1) {
sas_shutdown_queue(sas_ha);
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 4157f6e..7818c46 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -70,6 +70,7 @@ int sas_init_events(struct sas_ha_struct *sas_ha);
void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
void sas_disable_revalidation(struct sas_ha_struct *ha);
void sas_enable_revalidation(struct sas_ha_struct *ha);
+void __sas_drain_work(struct sas_ha_struct *ha);
void sas_deform_port(struct asd_sas_phy *phy, int gone);
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 2/7] libsas: improve ata debug statements
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
2012-01-21 1:50 ` [PATCH v6 1/7] libsas: fix sas_unregister_ports vs sas_drain_work Dan Williams
@ 2012-01-21 1:50 ` Dan Williams
2012-01-21 5:36 ` Jack Wang
2012-01-21 1:50 ` [PATCH v6 3/7] libsas: fix sas port naming Dan Williams
` (5 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:50 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide
It's difficult to determine which domain_device is triggering error recovery,
so convert messages like:
sas: ex 5001b4da000e703f phy08:T attached: 5001b4da000e7028
sas: ex 5001b4da000e703f phy09:T attached: 5001b4da000e7029
...
ata7: sas eh calling libata port error handler
ata8: sas eh calling libata port error handler
...into:
sas: ex 5001517e85cfefff phy05:T:9 attached: 5001517e85cfefe5 (stp)
sas: ex 5001517e3b0af0bf phy11:T:8 attached: 5001517e3b0af0ab (stp)
...
sas: ata7: end_device-21:1: dev error handler
sas: ata8: end_device-20:0:5: dev error handler
which shows attached link rate, device type, and associates a
domain_device with its ata_port id to correlate messages emitted from
libata-eh.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_ata.c | 43 ++++++++++++++++++++++++++++--------
drivers/scsi/libsas/sas_expander.c | 38 ++++++++++++++++++++++++++------
2 files changed, 64 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 0ee6831..b43e395 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -317,6 +317,28 @@ static int local_ata_check_ready(struct ata_link *link)
}
}
+static int sas_ata_printk(const char *level, const struct domain_device *ddev,
+ const char *fmt, ...)
+{
+ struct ata_port *ap = ddev->sata_dev.ap;
+ struct device *dev = &ddev->rphy->dev;
+ struct va_format vaf;
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ r = printk("%ssas: ata%u: %s: %pV",
+ level, ap->print_id, dev_name(dev), &vaf);
+
+ va_end(args);
+
+ return r;
+}
+
static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
@@ -333,7 +355,7 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
res = i->dft->lldd_I_T_nexus_reset(dev);
if (res != TMF_RESP_FUNC_COMPLETE)
- SAS_DPRINTK("%s: Unable to reset ata device?\n", __func__);
+ sas_ata_printk(KERN_DEBUG, dev, "Unable to reset ata device?\n");
phy = sas_get_local_phy(dev);
if (scsi_is_sas_phy_local(phy))
@@ -344,7 +366,7 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
ret = ata_wait_after_reset(link, deadline, check_ready);
if (ret && ret != -EAGAIN)
- ata_link_err(link, "COMRESET failed (errno=%d)\n", ret);
+ sas_ata_printk(KERN_ERR, dev, "reset failed (errno=%d)\n", ret);
/* XXX: if the class changes during the reset the upper layer
* should be informed, if the device has gone away we assume
@@ -665,7 +687,7 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
* remove once all commands are completed
*/
kref_get(&dev->kref);
- ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
+ sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n");
ata_scsi_port_error_handler(ha->core.shost, ap);
sas_put_device(dev);
@@ -708,26 +730,27 @@ void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
struct list_head *done_q)
{
struct scsi_cmnd *cmd, *n;
- struct ata_port *ap;
+ struct domain_device *eh_dev;
do {
LIST_HEAD(sata_q);
-
- ap = NULL;
+ eh_dev = NULL;
list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
struct domain_device *ddev = cmd_to_domain_dev(cmd);
if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
continue;
- if (ap && ap != ddev->sata_dev.ap)
+ if (eh_dev && eh_dev != ddev)
continue;
- ap = ddev->sata_dev.ap;
+ eh_dev = ddev;
list_move(&cmd->eh_entry, &sata_q);
}
if (!list_empty(&sata_q)) {
- ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n");
+ struct ata_port *ap = eh_dev->sata_dev.ap;
+
+ sas_ata_printk(KERN_DEBUG, eh_dev, "cmd error handler\n");
ata_scsi_cmd_error_handler(shost, ap, &sata_q);
/*
* ata's error handler may leave the cmd on the list
@@ -743,7 +766,7 @@ void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
while (!list_empty(&sata_q))
list_del_init(sata_q.next);
}
- } while (ap);
+ } while (eh_dev);
}
void sas_ata_schedule_reset(struct domain_device *dev)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 68a80a0..f8d941f 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -176,9 +176,10 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
struct smp_resp *resp = disc_resp;
struct discover_resp *dr = &resp->disc;
struct sas_rphy *rphy = dev->rphy;
- int rediscover = (phy->phy != NULL);
+ bool new_phy = !phy->phy;
+ char *type;
- if (!rediscover) {
+ if (new_phy) {
phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
/* FIXME: error_handling */
@@ -223,20 +224,43 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
phy->phy->maximum_linkrate = dr->pmax_linkrate;
phy->phy->negotiated_linkrate = phy->linkrate;
- if (!rediscover)
+ if (new_phy)
if (sas_phy_add(phy->phy)) {
sas_phy_free(phy->phy);
return;
}
- SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
+ switch (phy->attached_dev_type) {
+ case NO_DEVICE:
+ type = "no device";
+ break;
+ case SAS_END_DEV:
+ if (phy->attached_iproto) {
+ if (phy->attached_tproto)
+ type = "host+target";
+ else
+ type = "host";
+ } else {
+ if (dr->attached_sata_dev)
+ type = "stp";
+ else
+ type = "ssp";
+ }
+ break;
+ case EDGE_DEV:
+ case FANOUT_DEV:
+ type = "smp";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
SAS_ADDR(dev->sas_addr), phy->phy_id,
phy->routing_attr == TABLE_ROUTING ? 'T' :
phy->routing_attr == DIRECT_ROUTING ? 'D' :
phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?',
- SAS_ADDR(phy->attached_sas_addr));
-
- return;
+ phy->linkrate, SAS_ADDR(phy->attached_sas_addr), type);
}
/* check if we have an existing attached ata device on this expander phy */
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v6 2/7] libsas: improve ata debug statements
2012-01-21 1:50 ` [PATCH v6 2/7] libsas: improve ata debug statements Dan Williams
@ 2012-01-21 5:36 ` Jack Wang
2012-01-21 20:26 ` Douglas Gilbert
0 siblings, 1 reply; 13+ messages in thread
From: Jack Wang @ 2012-01-21 5:36 UTC (permalink / raw)
To: 'Dan Williams', linux-scsi; +Cc: linux-ide
>
[Jack Wang]
Nice improvement.
Thanks.
> It's difficult to determine which domain_device is triggering error
recovery,
> so convert messages like:
>
> sas: ex 5001b4da000e703f phy08:T attached: 5001b4da000e7028
> sas: ex 5001b4da000e703f phy09:T attached: 5001b4da000e7029
> ...
> ata7: sas eh calling libata port error handler
> ata8: sas eh calling libata port error handler
>
> ...into:
>
> sas: ex 5001517e85cfefff phy05:T:9 attached: 5001517e85cfefe5 (stp)
> sas: ex 5001517e3b0af0bf phy11:T:8 attached: 5001517e3b0af0ab (stp)
> ...
> sas: ata7: end_device-21:1: dev error handler
> sas: ata8: end_device-20:0:5: dev error handler
>
> which shows attached link rate, device type, and associates a
> domain_device with its ata_port id to correlate messages emitted from
> libata-eh.
>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> drivers/scsi/libsas/sas_ata.c | 43
> ++++++++++++++++++++++++++++--------
> drivers/scsi/libsas/sas_expander.c | 38
++++++++++++++++++++++++++------
> 2 files changed, 64 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
> index 0ee6831..b43e395 100644
> --- a/drivers/scsi/libsas/sas_ata.c
> +++ b/drivers/scsi/libsas/sas_ata.c
> @@ -317,6 +317,28 @@ static int local_ata_check_ready(struct ata_link
*link)
> }
> }
>
> +static int sas_ata_printk(const char *level, const struct domain_device
> *ddev,
> + const char *fmt, ...)
> +{
> + struct ata_port *ap = ddev->sata_dev.ap;
> + struct device *dev = &ddev->rphy->dev;
> + struct va_format vaf;
> + va_list args;
> + int r;
> +
> + va_start(args, fmt);
> +
> + vaf.fmt = fmt;
> + vaf.va = &args;
> +
> + r = printk("%ssas: ata%u: %s: %pV",
> + level, ap->print_id, dev_name(dev), &vaf);
> +
> + va_end(args);
> +
> + return r;
> +}
> +
> static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
> unsigned long deadline)
> {
> @@ -333,7 +355,7 @@ static int sas_ata_hard_reset(struct ata_link *link,
> unsigned int *class,
> res = i->dft->lldd_I_T_nexus_reset(dev);
>
> if (res != TMF_RESP_FUNC_COMPLETE)
> - SAS_DPRINTK("%s: Unable to reset ata device?\n", __func__);
> + sas_ata_printk(KERN_DEBUG, dev, "Unable to reset ata
device?\n");
>
> phy = sas_get_local_phy(dev);
> if (scsi_is_sas_phy_local(phy))
> @@ -344,7 +366,7 @@ static int sas_ata_hard_reset(struct ata_link *link,
> unsigned int *class,
>
> ret = ata_wait_after_reset(link, deadline, check_ready);
> if (ret && ret != -EAGAIN)
> - ata_link_err(link, "COMRESET failed (errno=%d)\n", ret);
> + sas_ata_printk(KERN_ERR, dev, "reset failed (errno=%d)\n",
ret);
>
> /* XXX: if the class changes during the reset the upper layer
> * should be informed, if the device has gone away we assume
> @@ -665,7 +687,7 @@ static void async_sas_ata_eh(void *data,
async_cookie_t
> cookie)
> * remove once all commands are completed
> */
> kref_get(&dev->kref);
> - ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error
> handler");
> + sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n");
> ata_scsi_port_error_handler(ha->core.shost, ap);
> sas_put_device(dev);
>
> @@ -708,26 +730,27 @@ void sas_ata_eh(struct Scsi_Host *shost, struct
> list_head *work_q,
> struct list_head *done_q)
> {
> struct scsi_cmnd *cmd, *n;
> - struct ata_port *ap;
> + struct domain_device *eh_dev;
>
> do {
> LIST_HEAD(sata_q);
> -
> - ap = NULL;
> + eh_dev = NULL;
>
> list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
> struct domain_device *ddev = cmd_to_domain_dev(cmd);
>
> if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
> continue;
> - if (ap && ap != ddev->sata_dev.ap)
> + if (eh_dev && eh_dev != ddev)
> continue;
> - ap = ddev->sata_dev.ap;
> + eh_dev = ddev;
> list_move(&cmd->eh_entry, &sata_q);
> }
>
> if (!list_empty(&sata_q)) {
> - ata_port_printk(ap, KERN_DEBUG, "sas eh calling
libata cmd
> error handler\n");
> + struct ata_port *ap = eh_dev->sata_dev.ap;
> +
> + sas_ata_printk(KERN_DEBUG, eh_dev, "cmd error
handler\n");
> ata_scsi_cmd_error_handler(shost, ap, &sata_q);
> /*
> * ata's error handler may leave the cmd on the list
> @@ -743,7 +766,7 @@ void sas_ata_eh(struct Scsi_Host *shost, struct
list_head
> *work_q,
> while (!list_empty(&sata_q))
> list_del_init(sata_q.next);
> }
> - } while (ap);
> + } while (eh_dev);
> }
>
> void sas_ata_schedule_reset(struct domain_device *dev)
> diff --git a/drivers/scsi/libsas/sas_expander.c
> b/drivers/scsi/libsas/sas_expander.c
> index 68a80a0..f8d941f 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -176,9 +176,10 @@ static void sas_set_ex_phy(struct domain_device *dev,
int
> phy_id,
> struct smp_resp *resp = disc_resp;
> struct discover_resp *dr = &resp->disc;
> struct sas_rphy *rphy = dev->rphy;
> - int rediscover = (phy->phy != NULL);
> + bool new_phy = !phy->phy;
> + char *type;
>
> - if (!rediscover) {
> + if (new_phy) {
> phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
>
> /* FIXME: error_handling */
> @@ -223,20 +224,43 @@ static void sas_set_ex_phy(struct domain_device
*dev,
> int phy_id,
> phy->phy->maximum_linkrate = dr->pmax_linkrate;
> phy->phy->negotiated_linkrate = phy->linkrate;
>
> - if (!rediscover)
> + if (new_phy)
> if (sas_phy_add(phy->phy)) {
> sas_phy_free(phy->phy);
> return;
> }
>
> - SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
> + switch (phy->attached_dev_type) {
> + case NO_DEVICE:
> + type = "no device";
> + break;
> + case SAS_END_DEV:
> + if (phy->attached_iproto) {
> + if (phy->attached_tproto)
> + type = "host+target";
> + else
> + type = "host";
> + } else {
> + if (dr->attached_sata_dev)
> + type = "stp";
> + else
> + type = "ssp";
> + }
> + break;
> + case EDGE_DEV:
> + case FANOUT_DEV:
> + type = "smp";
> + break;
> + default:
> + type = "unknown";
> + }
> +
> + SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
> SAS_ADDR(dev->sas_addr), phy->phy_id,
> phy->routing_attr == TABLE_ROUTING ? 'T' :
> phy->routing_attr == DIRECT_ROUTING ? 'D' :
> phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?',
> - SAS_ADDR(phy->attached_sas_addr));
> -
> - return;
> + phy->linkrate, SAS_ADDR(phy->attached_sas_addr), type);
> }
>
> /* check if we have an existing attached ata device on this expander phy
*/
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 2/7] libsas: improve ata debug statements
2012-01-21 5:36 ` Jack Wang
@ 2012-01-21 20:26 ` Douglas Gilbert
2012-01-23 20:51 ` Dan Williams
0 siblings, 1 reply; 13+ messages in thread
From: Douglas Gilbert @ 2012-01-21 20:26 UTC (permalink / raw)
To: Jack Wang; +Cc: 'Dan Williams', linux-scsi, linux-ide
On 12-01-21 12:36 AM, Jack Wang wrote:
>>
>
> [Jack Wang]
> Nice improvement.
> Thanks.
>> It's difficult to determine which domain_device is triggering error
> recovery,
>> so convert messages like:
>>
>> sas: ex 5001b4da000e703f phy08:T attached: 5001b4da000e7028
>> sas: ex 5001b4da000e703f phy09:T attached: 5001b4da000e7029
>> ...
>> ata7: sas eh calling libata port error handler
>> ata8: sas eh calling libata port error handler
>>
>> ...into:
>>
>> sas: ex 5001517e85cfefff phy05:T:9 attached: 5001517e85cfefe5 (stp)
>> sas: ex 5001517e3b0af0bf phy11:T:8 attached: 5001517e3b0af0ab (stp)
>> ...
>> sas: ata7: end_device-21:1: dev error handler
>> sas: ata8: end_device-20:0:5: dev error handler
>>
>> which shows attached link rate, device type, and associates a
>> domain_device with its ata_port id to correlate messages emitted from
>> libata-eh.
A couple of comments. The "T" in the "phy08:T" stands for
an expander phy's routing attribute being "table" I presume.
In smp_utils I'm thinking of changing that to "U" in the case
where that expander (SAS-2 or later) supports table-to-table
routing. The "U" indicates that phy can join other (sibling)
expander phys to become an "enclosure universal port" which
is nirvana for SAS expanders.
enum sas_dev_type::EDGE_DEV seems a pretty bad name and
should be changed to EXPANDER_DEV as that is more
accurate. Where fanout expanders ever made in SAS-1?
Not many I would expect. In SAS-2++ (SPL, SPL-2) the
"edge" and "fanout" distinction has been dropped and
the numerical value for fanout expanders (3) has been
marked as obsolete.
Doug Gilbert
>> Signed-off-by: Dan Williams<dan.j.williams@intel.com>
>> ---
>> drivers/scsi/libsas/sas_ata.c | 43
>> ++++++++++++++++++++++++++++--------
>> drivers/scsi/libsas/sas_expander.c | 38
> ++++++++++++++++++++++++++------
>> 2 files changed, 64 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
>> index 0ee6831..b43e395 100644
>> --- a/drivers/scsi/libsas/sas_ata.c
>> +++ b/drivers/scsi/libsas/sas_ata.c
>> @@ -317,6 +317,28 @@ static int local_ata_check_ready(struct ata_link
> *link)
>> }
>> }
>>
>> +static int sas_ata_printk(const char *level, const struct domain_device
>> *ddev,
>> + const char *fmt, ...)
>> +{
>> + struct ata_port *ap = ddev->sata_dev.ap;
>> + struct device *dev =&ddev->rphy->dev;
>> + struct va_format vaf;
>> + va_list args;
>> + int r;
>> +
>> + va_start(args, fmt);
>> +
>> + vaf.fmt = fmt;
>> + vaf.va =&args;
>> +
>> + r = printk("%ssas: ata%u: %s: %pV",
>> + level, ap->print_id, dev_name(dev),&vaf);
>> +
>> + va_end(args);
>> +
>> + return r;
>> +}
>> +
>> static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
>> unsigned long deadline)
>> {
>> @@ -333,7 +355,7 @@ static int sas_ata_hard_reset(struct ata_link *link,
>> unsigned int *class,
>> res = i->dft->lldd_I_T_nexus_reset(dev);
>>
>> if (res != TMF_RESP_FUNC_COMPLETE)
>> - SAS_DPRINTK("%s: Unable to reset ata device?\n", __func__);
>> + sas_ata_printk(KERN_DEBUG, dev, "Unable to reset ata
> device?\n");
>>
>> phy = sas_get_local_phy(dev);
>> if (scsi_is_sas_phy_local(phy))
>> @@ -344,7 +366,7 @@ static int sas_ata_hard_reset(struct ata_link *link,
>> unsigned int *class,
>>
>> ret = ata_wait_after_reset(link, deadline, check_ready);
>> if (ret&& ret != -EAGAIN)
>> - ata_link_err(link, "COMRESET failed (errno=%d)\n", ret);
>> + sas_ata_printk(KERN_ERR, dev, "reset failed (errno=%d)\n",
> ret);
>>
>> /* XXX: if the class changes during the reset the upper layer
>> * should be informed, if the device has gone away we assume
>> @@ -665,7 +687,7 @@ static void async_sas_ata_eh(void *data,
> async_cookie_t
>> cookie)
>> * remove once all commands are completed
>> */
>> kref_get(&dev->kref);
>> - ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error
>> handler");
>> + sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n");
>> ata_scsi_port_error_handler(ha->core.shost, ap);
>> sas_put_device(dev);
>>
>> @@ -708,26 +730,27 @@ void sas_ata_eh(struct Scsi_Host *shost, struct
>> list_head *work_q,
>> struct list_head *done_q)
>> {
>> struct scsi_cmnd *cmd, *n;
>> - struct ata_port *ap;
>> + struct domain_device *eh_dev;
>>
>> do {
>> LIST_HEAD(sata_q);
>> -
>> - ap = NULL;
>> + eh_dev = NULL;
>>
>> list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
>> struct domain_device *ddev = cmd_to_domain_dev(cmd);
>>
>> if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
>> continue;
>> - if (ap&& ap != ddev->sata_dev.ap)
>> + if (eh_dev&& eh_dev != ddev)
>> continue;
>> - ap = ddev->sata_dev.ap;
>> + eh_dev = ddev;
>> list_move(&cmd->eh_entry,&sata_q);
>> }
>>
>> if (!list_empty(&sata_q)) {
>> - ata_port_printk(ap, KERN_DEBUG, "sas eh calling
> libata cmd
>> error handler\n");
>> + struct ata_port *ap = eh_dev->sata_dev.ap;
>> +
>> + sas_ata_printk(KERN_DEBUG, eh_dev, "cmd error
> handler\n");
>> ata_scsi_cmd_error_handler(shost, ap,&sata_q);
>> /*
>> * ata's error handler may leave the cmd on the list
>> @@ -743,7 +766,7 @@ void sas_ata_eh(struct Scsi_Host *shost, struct
> list_head
>> *work_q,
>> while (!list_empty(&sata_q))
>> list_del_init(sata_q.next);
>> }
>> - } while (ap);
>> + } while (eh_dev);
>> }
>>
>> void sas_ata_schedule_reset(struct domain_device *dev)
>> diff --git a/drivers/scsi/libsas/sas_expander.c
>> b/drivers/scsi/libsas/sas_expander.c
>> index 68a80a0..f8d941f 100644
>> --- a/drivers/scsi/libsas/sas_expander.c
>> +++ b/drivers/scsi/libsas/sas_expander.c
>> @@ -176,9 +176,10 @@ static void sas_set_ex_phy(struct domain_device *dev,
> int
>> phy_id,
>> struct smp_resp *resp = disc_resp;
>> struct discover_resp *dr =&resp->disc;
>> struct sas_rphy *rphy = dev->rphy;
>> - int rediscover = (phy->phy != NULL);
>> + bool new_phy = !phy->phy;
>> + char *type;
>>
>> - if (!rediscover) {
>> + if (new_phy) {
>> phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
>>
>> /* FIXME: error_handling */
>> @@ -223,20 +224,43 @@ static void sas_set_ex_phy(struct domain_device
> *dev,
>> int phy_id,
>> phy->phy->maximum_linkrate = dr->pmax_linkrate;
>> phy->phy->negotiated_linkrate = phy->linkrate;
>>
>> - if (!rediscover)
>> + if (new_phy)
>> if (sas_phy_add(phy->phy)) {
>> sas_phy_free(phy->phy);
>> return;
>> }
>>
>> - SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
>> + switch (phy->attached_dev_type) {
>> + case NO_DEVICE:
>> + type = "no device";
>> + break;
>> + case SAS_END_DEV:
>> + if (phy->attached_iproto) {
>> + if (phy->attached_tproto)
>> + type = "host+target";
>> + else
>> + type = "host";
>> + } else {
>> + if (dr->attached_sata_dev)
>> + type = "stp";
>> + else
>> + type = "ssp";
>> + }
>> + break;
>> + case EDGE_DEV:
>> + case FANOUT_DEV:
>> + type = "smp";
>> + break;
>> + default:
>> + type = "unknown";
>> + }
>> +
>> + SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
>> SAS_ADDR(dev->sas_addr), phy->phy_id,
>> phy->routing_attr == TABLE_ROUTING ? 'T' :
>> phy->routing_attr == DIRECT_ROUTING ? 'D' :
>> phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?',
>> - SAS_ADDR(phy->attached_sas_addr));
>> -
>> - return;
>> + phy->linkrate, SAS_ADDR(phy->attached_sas_addr), type);
>> }
>>
>> /* check if we have an existing attached ata device on this expander phy
> */
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 2/7] libsas: improve ata debug statements
2012-01-21 20:26 ` Douglas Gilbert
@ 2012-01-23 20:51 ` Dan Williams
0 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-23 20:51 UTC (permalink / raw)
To: dgilbert; +Cc: Jack Wang, linux-scsi, linux-ide
On Sat, Jan 21, 2012 at 12:26 PM, Douglas Gilbert <dgilbert@interlog.com> wrote:
> On 12-01-21 12:36 AM, Jack Wang wrote:
>>>
>>>
>>
>> [Jack Wang]
>> Nice improvement.
>> Thanks.
>>>
>>> It's difficult to determine which domain_device is triggering error
>>
>> recovery,
>>>
>>> so convert messages like:
>>>
>>> sas: ex 5001b4da000e703f phy08:T attached: 5001b4da000e7028
>>> sas: ex 5001b4da000e703f phy09:T attached: 5001b4da000e7029
>>> ...
>>> ata7: sas eh calling libata port error handler
>>> ata8: sas eh calling libata port error handler
>>>
>>> ...into:
>>>
>>> sas: ex 5001517e85cfefff phy05:T:9 attached: 5001517e85cfefe5 (stp)
>>> sas: ex 5001517e3b0af0bf phy11:T:8 attached: 5001517e3b0af0ab (stp)
>>> ...
>>> sas: ata7: end_device-21:1: dev error handler
>>> sas: ata8: end_device-20:0:5: dev error handler
>>>
>>> which shows attached link rate, device type, and associates a
>>> domain_device with its ata_port id to correlate messages emitted from
>>> libata-eh.
>
>
> A couple of comments. The "T" in the "phy08:T" stands for
> an expander phy's routing attribute being "table" I presume.
Yes.
> In smp_utils I'm thinking of changing that to "U" in the case
> where that expander (SAS-2 or later) supports table-to-table
> routing. The "U" indicates that phy can join other (sibling)
> expander phys to become an "enclosure universal port" which
> is nirvana for SAS expanders.
Ok, something like the following (please excuse mailer line wrapping):
diff --git a/drivers/scsi/libsas/sas_expander.c
b/drivers/scsi/libsas/sas_expander.c
index f8d941f..4b2ecd3 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -166,7 +166,22 @@ static inline void *alloc_smp_resp(int size)
return kzalloc(size, GFP_KERNEL);
}
-/* ---------- Expander configuration ---------- */
+static char sas_route_char(struct domain_device *dev, struct ex_phy *phy)
+{
+ switch (phy->routing_attr) {
+ case TABLE_ROUTING:
+ if (dev->ex_dev.t2t_supp)
+ return 'U';
+ else
+ return 'T';
+ case DIRECT_ROUTING:
+ return 'D';
+ case SUBTRACTIVE_ROUTING:
+ return 'S';
+ default:
+ return '?';
+ }
+}
static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
void *disc_resp)
@@ -257,10 +272,8 @@ static void sas_set_ex_phy(struct domain_device
*dev, int phy_id,
SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
SAS_ADDR(dev->sas_addr), phy->phy_id,
- phy->routing_attr == TABLE_ROUTING ? 'T' :
- phy->routing_attr == DIRECT_ROUTING ? 'D' :
- phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?',
- phy->linkrate, SAS_ADDR(phy->attached_sas_addr), type);
+ sas_route_char(dev, phy), phy->linkrate,
+ SAS_ADDR(phy->attached_sas_addr), type);
}
...can also fix up the same in sas_print_parent_topology_bug
>
> enum sas_dev_type::EDGE_DEV seems a pretty bad name and
> should be changed to EXPANDER_DEV as that is more
> accurate. Where fanout expanders ever made in SAS-1?
> Not many I would expect. In SAS-2++ (SPL, SPL-2) the
> "edge" and "fanout" distinction has been dropped and
> the numerical value for fanout expanders (3) has been
> marked as obsolete.
Ok, that's a cleanup for another patch, but I'll go ahead and
formalize the above routing char fixup and repost the patch as
"libsas: improve debug statements" rather than "libsas: improve ata
debug statements"
--
Dan
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 3/7] libsas: fix sas port naming
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
2012-01-21 1:50 ` [PATCH v6 1/7] libsas: fix sas_unregister_ports vs sas_drain_work Dan Williams
2012-01-21 1:50 ` [PATCH v6 2/7] libsas: improve ata debug statements Dan Williams
@ 2012-01-21 1:50 ` Dan Williams
2012-01-21 1:51 ` [PATCH v6 4/7] libsas: let libata recover links that fail to transmit initial sig-fis Dan Williams
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:50 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide, Patrick Thomson
Make sas-port naming consistent with the expander-attached case whereby
the phy-id is the last digit in the port name. Otherwise we get the
random behavior of the allocation order.
Reported-by: Patrick Thomson <patrick.s.thomson@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_port.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 59ee8a0..29f8fd3 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -122,7 +122,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
if (!port->port) {
- port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
+ port->port = sas_port_alloc(phy->phy->dev.parent, phy->id);
BUG_ON(!port->port);
sas_port_add(port->port);
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 4/7] libsas: let libata recover links that fail to transmit initial sig-fis
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
` (2 preceding siblings ...)
2012-01-21 1:50 ` [PATCH v6 3/7] libsas: fix sas port naming Dan Williams
@ 2012-01-21 1:51 ` Dan Williams
2012-01-21 1:51 ` [PATCH v6 5/7] libsas: delete device on sas address changed Dan Williams
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:51 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide, Jack Wang, Luben Tuikov, Xiangliang Yu
libsas fails to discover all sata devices in the domain. If a device fails
negotiation and does not transmit a signature fis the link needs recovery.
libata already understands how to manage slow to come up links, so treat these
conditions as ata device attach events for the purposes of creating an
ata_port. This allows libata to manage retrying link bring up.
Rediscovery is modified to be careful about checking changes in dev_type. It
looks like libsas leaks old devices if the sas address changes, but that's a
fix for another patch.
Cc: Xiangliang Yu <yuxiangl@marvell.com>
Cc: Luben Tuikov <ltuikov@yahoo.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_ata.c | 71 +++++++++++++-
drivers/scsi/libsas/sas_discover.c | 1
drivers/scsi/libsas/sas_expander.c | 178 ++++++++++++++++++++----------------
drivers/scsi/libsas/sas_internal.h | 6 +
include/scsi/sas.h | 4 -
include/scsi/sas_ata.h | 8 +-
6 files changed, 178 insertions(+), 90 deletions(-)
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index b43e395..0da1f3c 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -278,26 +278,84 @@ static struct sas_internal *dev_to_sas_internal(struct domain_device *dev)
return to_sas_internal(dev->port->ha->core.shost->transportt);
}
+static void sas_get_ata_command_set(struct domain_device *dev);
+
+int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
+{
+ if (phy->attached_tproto & SAS_PROTOCOL_STP)
+ dev->tproto = phy->attached_tproto;
+ if (phy->attached_sata_dev)
+ dev->tproto |= SATA_DEV;
+
+ if (phy->attached_dev_type == SATA_PENDING)
+ dev->dev_type = SATA_PENDING;
+ else {
+ int res;
+
+ dev->dev_type = SATA_DEV;
+ res = sas_get_report_phy_sata(dev->parent, phy->phy_id,
+ &dev->sata_dev.rps_resp);
+ if (res) {
+ SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
+ "0x%x\n", SAS_ADDR(dev->parent->sas_addr),
+ phy->phy_id, res);
+ return res;
+ }
+ memcpy(dev->frame_rcvd, &dev->sata_dev.rps_resp.rps.fis,
+ sizeof(struct dev_to_host_fis));
+ /* TODO switch to ata_dev_classify() */
+ sas_get_ata_command_set(dev);
+ }
+ return 0;
+}
+
+static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy)
+{
+ int res;
+
+ /* we weren't pending, so successfully end the reset sequence now */
+ if (dev->dev_type != SATA_PENDING)
+ return 1;
+
+ /* hmmm, if this succeeds do we need to repost the domain_device to the
+ * lldd so it can pick up new parameters?
+ */
+ res = sas_get_ata_info(dev, phy);
+ if (res)
+ return 0; /* retry */
+ else
+ return 1;
+}
+
static int smp_ata_check_ready(struct ata_link *link)
{
int res;
- u8 addr[8];
struct ata_port *ap = link->ap;
struct domain_device *dev = ap->private_data;
struct domain_device *ex_dev = dev->parent;
struct sas_phy *phy = sas_get_local_phy(dev);
+ struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy->number];
- res = sas_get_phy_attached_sas_addr(ex_dev, phy->number, addr);
+ res = sas_ex_phy_discover(ex_dev, phy->number);
sas_put_local_phy(phy);
+
/* break the wait early if the expander is unreachable,
* otherwise keep polling
*/
if (res == -ECOMM)
return res;
- if (res != SMP_RESP_FUNC_ACC || SAS_ADDR(addr) == 0)
+ if (res != SMP_RESP_FUNC_ACC)
return 0;
- else
- return 1;
+
+ switch (ex_phy->attached_dev_type) {
+ case SATA_PENDING:
+ return 0;
+ case SAS_END_DEV:
+ if (ex_phy->attached_sata_dev)
+ return sas_ata_clear_pending(dev, ex_phy);
+ default:
+ return -ENODEV;
+ }
}
static int local_ata_check_ready(struct ata_link *link)
@@ -584,6 +642,9 @@ static void sas_get_ata_command_set(struct domain_device *dev)
struct dev_to_host_fis *fis =
(struct dev_to_host_fis *) dev->frame_rcvd;
+ if (dev->dev_type == SATA_PENDING)
+ return;
+
if ((fis->sector_count == 1 && /* ATA */
fis->lbal == 1 &&
fis->lbam == 0 &&
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index c6681b4..dc8baef 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -48,6 +48,7 @@ void sas_init_dev(struct domain_device *dev)
case SATA_DEV:
case SATA_PM:
case SATA_PM_PORT:
+ case SATA_PENDING:
INIT_LIST_HEAD(&dev->sata_dev.children);
break;
default:
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f8d941f..dc6bba5 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -166,15 +166,27 @@ static inline void *alloc_smp_resp(int size)
return kzalloc(size, GFP_KERNEL);
}
-/* ---------- Expander configuration ---------- */
+static enum sas_dev_type to_dev_type(struct discover_resp *dr)
+{
+ /* This is detecting a failure to transmit initial dev to host
+ * FIS as described in section J.5 of sas-2 r16
+ */
+ if (dr->attached_dev_type == NO_DEVICE && dr->attached_sata_dev &&
+ dr->linkrate >= SAS_LINK_RATE_1_5_GBPS)
+ return SATA_PENDING;
+ else
+ return dr->attached_dev_type;
+}
-static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
- void *disc_resp)
+static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
{
+ enum sas_dev_type dev_type;
+ enum sas_linkrate linkrate;
+ u8 sas_addr[SAS_ADDR_SIZE];
+ struct smp_resp *resp = rsp;
+ struct discover_resp *dr = &resp->disc;
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id];
- struct smp_resp *resp = disc_resp;
- struct discover_resp *dr = &resp->disc;
struct sas_rphy *rphy = dev->rphy;
bool new_phy = !phy->phy;
char *type;
@@ -198,8 +210,13 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
break;
}
+ /* check if anything important changed to squelch debug */
+ dev_type = phy->attached_dev_type;
+ linkrate = phy->linkrate;
+ memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
+
+ phy->attached_dev_type = to_dev_type(dr);
phy->phy_id = phy_id;
- phy->attached_dev_type = dr->attached_dev_type;
phy->linkrate = dr->linkrate;
phy->attached_sata_host = dr->attached_sata_host;
phy->attached_sata_dev = dr->attached_sata_dev;
@@ -214,7 +231,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
phy->last_da_index = -1;
phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
- phy->phy->identify.device_type = phy->attached_dev_type;
+ phy->phy->identify.device_type = dr->attached_dev_type;
phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
phy->phy->identify.target_port_protocols = phy->attached_tproto;
phy->phy->identify.phy_identifier = phy_id;
@@ -231,6 +248,9 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
}
switch (phy->attached_dev_type) {
+ case SATA_PENDING:
+ type = "stp pending";
+ break;
case NO_DEVICE:
type = "no device";
break;
@@ -255,6 +275,16 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
type = "unknown";
}
+ /* this routine is polled by libata error recovery so filter
+ * unimportant messages
+ */
+ if (new_phy || phy->attached_dev_type != dev_type ||
+ phy->linkrate != linkrate ||
+ SAS_ADDR(phy->attached_sas_addr) != SAS_ADDR(sas_addr))
+ /* pass */;
+ else
+ return;
+
SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
SAS_ADDR(dev->sas_addr), phy->phy_id,
phy->routing_attr == TABLE_ROUTING ? 'T' :
@@ -291,50 +321,25 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
u8 *disc_resp, int single)
{
- struct domain_device *ata_dev = sas_ex_to_ata(dev, single);
- int i, res;
+ struct discover_resp *dr;
+ int res;
disc_req[9] = single;
- for (i = 1 ; i < 3; i++) {
- struct discover_resp *dr;
- res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
- disc_resp, DISCOVER_RESP_SIZE);
- if (res)
- return res;
- dr = &((struct smp_resp *)disc_resp)->disc;
- if (memcmp(dev->sas_addr, dr->attached_sas_addr,
- SAS_ADDR_SIZE) == 0) {
- sas_printk("Found loopback topology, just ignore it!\n");
- return 0;
- }
-
- /* This is detecting a failure to transmit initial
- * dev to host FIS as described in section J.5 of
- * sas-2 r16
- */
- if (!(dr->attached_dev_type == 0 &&
- dr->attached_sata_dev))
- break;
-
- /* In order to generate the dev to host FIS, we send a
- * link reset to the expander port. If a device was
- * previously detected on this port we ask libata to
- * manage the reset and link recovery.
- */
- if (ata_dev) {
- sas_ata_schedule_reset(ata_dev);
- break;
- }
- sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET, NULL);
- /* Wait for the reset to trigger the negotiation */
- msleep(500);
+ res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
+ disc_resp, DISCOVER_RESP_SIZE);
+ if (res)
+ return res;
+ dr = &((struct smp_resp *)disc_resp)->disc;
+ if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) {
+ sas_printk("Found loopback topology, just ignore it!\n");
+ return 0;
}
sas_set_ex_phy(dev, single, disc_resp);
return 0;
}
-static int sas_ex_phy_discover(struct domain_device *dev, int single)
+int sas_ex_phy_discover(struct domain_device *dev, int single)
{
struct expander_device *ex = &dev->ex_dev;
int res = 0;
@@ -639,9 +644,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy)
#define RPS_REQ_SIZE 16
#define RPS_RESP_SIZE 60
-static int sas_get_report_phy_sata(struct domain_device *dev,
- int phy_id,
- struct smp_resp *rps_resp)
+int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
+ struct smp_resp *rps_resp)
{
int res;
u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
@@ -751,21 +755,9 @@ static struct domain_device *sas_ex_discover_end_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_PROTOCOL_STP)
- child->tproto = phy->attached_tproto;
- if (phy->attached_sata_dev)
- child->tproto |= SATA_DEV;
- res = sas_get_report_phy_sata(parent, phy_id,
- &child->sata_dev.rps_resp);
- if (res) {
- SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
- "0x%x\n", SAS_ADDR(parent->sas_addr),
- phy_id, res);
+ res = sas_get_ata_info(child, phy);
+ if (res)
goto out_free;
- }
- memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
- sizeof(struct dev_to_host_fis));
rphy = sas_end_device_alloc(phy->port);
if (unlikely(!rphy))
@@ -980,7 +972,8 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
if (ex_phy->attached_dev_type != SAS_END_DEV &&
ex_phy->attached_dev_type != FANOUT_DEV &&
- ex_phy->attached_dev_type != EDGE_DEV) {
+ ex_phy->attached_dev_type != EDGE_DEV &&
+ ex_phy->attached_dev_type != SATA_PENDING) {
SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx "
"phy 0x%x\n", ex_phy->attached_dev_type,
SAS_ADDR(dev->sas_addr),
@@ -1006,6 +999,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
switch (ex_phy->attached_dev_type) {
case SAS_END_DEV:
+ case SATA_PENDING:
child = sas_ex_discover_end_dev(dev, phy_id);
break;
case FANOUT_DEV:
@@ -1682,8 +1676,8 @@ static int sas_get_phy_change_count(struct domain_device *dev,
return res;
}
-int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
- u8 *attached_sas_addr)
+static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
+ u8 *sas_addr, enum sas_dev_type *type)
{
int res;
struct smp_resp *disc_resp;
@@ -1695,10 +1689,11 @@ int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
dr = &disc_resp->disc;
res = sas_get_phy_discover(dev, phy_id, disc_resp);
- if (!res) {
- memcpy(attached_sas_addr,disc_resp->disc.attached_sas_addr,8);
- if (dr->attached_dev_type == 0)
- memset(attached_sas_addr, 0, 8);
+ if (res == 0) {
+ memcpy(sas_addr, disc_resp->disc.attached_sas_addr, 8);
+ *type = to_dev_type(dr);
+ if (*type == 0)
+ memset(sas_addr, 0, 8);
}
kfree(disc_resp);
return res;
@@ -1947,39 +1942,62 @@ out:
return res;
}
+static bool dev_type_flutter(enum sas_dev_type new, enum sas_dev_type old)
+{
+ if (old == new)
+ return true;
+
+ /* treat device directed resets as flutter, if we went
+ * SAS_END_DEV to SATA_PENDING the link needs recovery
+ */
+ if ((old == SATA_PENDING && new == SAS_END_DEV) ||
+ (old == SAS_END_DEV && new == SATA_PENDING))
+ return true;
+
+ return false;
+}
+
static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
{
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id];
- u8 attached_sas_addr[8];
+ enum sas_dev_type type = NO_DEVICE;
+ u8 sas_addr[8];
int res;
- res = sas_get_phy_attached_sas_addr(dev, phy_id, attached_sas_addr);
+ res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
switch (res) {
case SMP_RESP_NO_PHY:
phy->phy_state = PHY_NOT_PRESENT;
sas_unregister_devs_sas_addr(dev, phy_id, last);
- goto out; break;
+ return res;
case SMP_RESP_PHY_VACANT:
phy->phy_state = PHY_VACANT;
sas_unregister_devs_sas_addr(dev, phy_id, last);
- goto out; break;
+ return res;
case SMP_RESP_FUNC_ACC:
break;
}
- if (SAS_ADDR(attached_sas_addr) == 0) {
+ if (SAS_ADDR(sas_addr) == 0) {
phy->phy_state = PHY_EMPTY;
sas_unregister_devs_sas_addr(dev, phy_id, last);
- } else if (SAS_ADDR(attached_sas_addr) ==
- SAS_ADDR(phy->attached_sas_addr)) {
- SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n",
- SAS_ADDR(dev->sas_addr), phy_id);
+ return res;
+ } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
+ dev_type_flutter(type, phy->attached_dev_type)) {
+ struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
+ char *action = "";
+
sas_ex_phy_discover(dev, phy_id);
- } else
- res = sas_discover_new(dev, phy_id);
-out:
- return res;
+
+ if (ata_dev && phy->attached_dev_type == SATA_PENDING)
+ action = ", needs recovery";
+ SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n",
+ SAS_ADDR(dev->sas_addr), phy_id, action);
+ return res;
+ }
+
+ return sas_discover_new(dev, phy_id);
}
/**
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 7818c46..e028d7a 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -91,8 +91,9 @@ int sas_smp_get_phy_events(struct sas_phy *phy);
void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
-int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
- u8 *attached_sas_addr);
+int sas_ex_phy_discover(struct domain_device *dev, int single);
+int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
+ struct smp_resp *rps_resp);
int sas_try_ata_reset(struct asd_sas_phy *phy);
void sas_hae_reset(struct work_struct *work);
@@ -122,6 +123,7 @@ static inline void sas_fill_in_rphy(struct domain_device *dev,
case SATA_DEV:
/* FIXME: need sata device type */
case SAS_END_DEV:
+ case SATA_PENDING:
rphy->identify.device_type = SAS_END_DEVICE;
break;
case EDGE_DEV:
diff --git a/include/scsi/sas.h b/include/scsi/sas.h
index 3673d68..a577a83 100644
--- a/include/scsi/sas.h
+++ b/include/scsi/sas.h
@@ -89,8 +89,7 @@ enum sas_oob_mode {
SAS_OOB_MODE
};
-/* See sas_discover.c if you plan on changing these.
- */
+/* See sas_discover.c if you plan on changing these */
enum sas_dev_type {
NO_DEVICE = 0, /* protocol */
SAS_END_DEV = 1, /* protocol */
@@ -100,6 +99,7 @@ enum sas_dev_type {
SATA_DEV = 5,
SATA_PM = 7,
SATA_PM_PORT= 8,
+ SATA_PENDING = 9,
};
enum sas_protocol {
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index cb724fd..0ca2f8a 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -33,9 +33,10 @@
static inline int dev_is_sata(struct domain_device *dev)
{
return dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
- dev->dev_type == SATA_PM_PORT;
+ dev->dev_type == SATA_PM_PORT || dev->dev_type == SATA_PENDING;
}
+int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
int sas_ata_init_host_and_port(struct domain_device *found_dev,
struct scsi_target *starget);
@@ -82,6 +83,11 @@ static inline void sas_ata_schedule_reset(struct domain_device *dev)
static inline void sas_ata_wait_eh(struct domain_device *dev)
{
}
+
+static inline int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
+{
+ return 0;
+}
#endif
#endif /* _SAS_ATA_H_ */
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 5/7] libsas: delete device on sas address changed
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
` (3 preceding siblings ...)
2012-01-21 1:51 ` [PATCH v6 4/7] libsas: let libata recover links that fail to transmit initial sig-fis Dan Williams
@ 2012-01-21 1:51 ` Dan Williams
2012-01-21 1:51 ` [PATCH v6 6/7] libsas: restore scan order Dan Williams
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:51 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide
If the phy is attached to a new sas address unregister the first address
before processing the new attachment.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_expander.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index dc6bba5..3d6ba30 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1997,6 +1997,15 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
return res;
}
+ /* delete the old link */
+ if (SAS_ADDR(phy->attached_sas_addr) &&
+ SAS_ADDR(sas_addr) != SAS_ADDR(phy->attached_sas_addr)) {
+ SAS_DPRINTK("ex %016llx phy 0x%x replace %016llx\n",
+ SAS_ADDR(dev->sas_addr), phy_id,
+ SAS_ADDR(phy->attached_sas_addr));
+ sas_unregister_devs_sas_addr(dev, phy_id, last);
+ }
+
return sas_discover_new(dev, phy_id);
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 6/7] libsas: restore scan order
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
` (4 preceding siblings ...)
2012-01-21 1:51 ` [PATCH v6 5/7] libsas: delete device on sas address changed Dan Williams
@ 2012-01-21 1:51 ` Dan Williams
2012-01-21 1:51 ` [PATCH v6 7/7] libsas: async ata scanning Dan Williams
2012-01-21 6:12 ` [PATCH v6 0/7] libsas error handling + discovery v6 Jack Wang
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:51 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide
ata devices are always scanned after ssp. Prior to the ata error
handling reworks libsas would tend to scan devices in ascending expander
phy order. Restore this ordering by deferring ssp discovery to a
DISCE_PROBE event, and keep the probe order consistent with the
discovery order, not the placement of sata devices.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/libsas/sas_ata.c | 29 ------------------------
drivers/scsi/libsas/sas_discover.c | 44 +++++++++++++++++++++++++-----------
drivers/scsi/libsas/sas_expander.c | 4 +--
include/scsi/sas_ata.h | 5 ----
4 files changed, 32 insertions(+), 50 deletions(-)
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 0da1f3c..4751829 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -683,35 +683,6 @@ static void sas_get_ata_command_set(struct domain_device *dev)
dev->sata_dev.command_set = ATAPI_COMMAND_SET;
}
-void sas_probe_sata(struct work_struct *work)
-{
- struct domain_device *dev, *n;
- struct sas_discovery_event *ev =
- container_of(work, struct sas_discovery_event, work);
- struct asd_sas_port *port = ev->port;
-
- clear_bit(DISCE_PROBE, &port->disc.pending);
-
- list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
- int err;
-
- spin_lock_irq(&port->dev_list_lock);
- list_add_tail(&dev->dev_list_node, &port->dev_list);
- spin_unlock_irq(&port->dev_list_lock);
-
- err = sas_rphy_add(dev->rphy);
-
- if (err) {
- SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
- __func__, dev->parent ? "exp-attached" :
- "direct-attached",
- SAS_ADDR(dev->sas_addr), err);
- sas_unregister_dev(port, dev);
- } else
- list_del_init(&dev->disco_list_node);
- }
-}
-
/**
* sas_discover_sata -- discover an STP/SATA domain device
* @dev: pointer to struct domain_device of interest
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index dc8baef..f60b602 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -152,7 +152,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
dev->rphy = rphy;
- if (dev_is_sata(dev))
+ if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
list_add_tail(&dev->disco_list_node, &port->disco_list);
else {
spin_lock_irq(&port->dev_list_lock);
@@ -198,8 +198,34 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
}
}
-/* ---------- Common/dispatchers ---------- */
+static void sas_probe_devices(struct work_struct *work)
+{
+ struct domain_device *dev, *n;
+ struct sas_discovery_event *ev =
+ container_of(work, struct sas_discovery_event, work);
+ struct asd_sas_port *port = ev->port;
+ clear_bit(DISCE_PROBE, &port->disc.pending);
+
+ list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+ int err;
+
+ spin_lock_irq(&port->dev_list_lock);
+ list_add_tail(&dev->dev_list_node, &port->dev_list);
+ spin_unlock_irq(&port->dev_list_lock);
+
+ err = sas_rphy_add(dev->rphy);
+
+ if (err) {
+ SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
+ __func__, dev->parent ? "exp-attached" :
+ "direct-attached",
+ SAS_ADDR(dev->sas_addr), err);
+ sas_unregister_dev(port, dev);
+ } else
+ list_del_init(&dev->disco_list_node);
+ }
+}
/**
* sas_discover_end_dev -- discover an end device (SSP, etc)
@@ -213,18 +239,10 @@ int sas_discover_end_dev(struct domain_device *dev)
res = sas_notify_lldd_dev_found(dev);
if (res)
- goto out_err2;
-
- res = sas_rphy_add(dev->rphy);
- if (res)
- goto out_err;
+ return res;
+ sas_discover_event(dev->port, DISCE_PROBE);
return 0;
-
-out_err:
- sas_notify_lldd_dev_gone(dev);
-out_err2:
- return res;
}
/* ---------- Device registration and unregistration ---------- */
@@ -491,7 +509,7 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
[DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
[DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
- [DISCE_PROBE] = sas_probe_sata,
+ [DISCE_PROBE] = sas_probe_devices,
[DISCE_DESTRUCT] = sas_destruct_devices,
};
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 3d6ba30..0aa90d7 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -791,9 +791,7 @@ static struct domain_device *sas_ex_discover_end_dev(
child->rphy = rphy;
sas_fill_in_rphy(child, rphy);
- spin_lock_irq(&parent->port->dev_list_lock);
- list_add_tail(&child->dev_list_node, &parent->port->dev_list);
- spin_unlock_irq(&parent->port->dev_list_lock);
+ list_add_tail(&child->disco_list_node, &parent->port->disco_list);
res = sas_discover_end_dev(child);
if (res) {
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index 0ca2f8a..1556eff 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -44,7 +44,6 @@ void sas_ata_task_abort(struct sas_task *task);
void sas_ata_strategy_handler(struct Scsi_Host *shost);
void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
struct list_head *done_q);
-void sas_probe_sata(struct work_struct *work);
void sas_ata_schedule_reset(struct domain_device *dev);
void sas_ata_wait_eh(struct domain_device *dev);
#else
@@ -72,10 +71,6 @@ static inline void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
{
}
-static inline void sas_probe_sata(struct work_struct *work)
-{
-}
-
static inline void sas_ata_schedule_reset(struct domain_device *dev)
{
}
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 7/7] libsas: async ata scanning
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
` (5 preceding siblings ...)
2012-01-21 1:51 ` [PATCH v6 6/7] libsas: restore scan order Dan Williams
@ 2012-01-21 1:51 ` Dan Williams
2012-01-21 6:12 ` [PATCH v6 0/7] libsas error handling + discovery v6 Jack Wang
7 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-21 1:51 UTC (permalink / raw)
To: linux-scsi; +Cc: linux-ide
libsas ata error handling is already async but this does not help the
scan case. Move initial link recovery out from under host->scan_mutex,
and delay synchronization with eh until after all port probe/recovery
work has been queued.
Device ordering is maintained with scan order by still calling
sas_rphy_add() in order of domain discovery.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/ata/libata-core.c | 34 +++++++++++---------
drivers/ata/libata-scsi.c | 13 ++++++++
drivers/ata/libata.h | 1 +
drivers/scsi/aic94xx/aic94xx_init.c | 1 -
drivers/scsi/isci/init.c | 1 -
drivers/scsi/libsas/sas_ata.c | 60 +++++++++++++++++++++++++++++------
drivers/scsi/libsas/sas_discover.c | 22 ++++++-------
drivers/scsi/libsas/sas_internal.h | 9 +++++
drivers/scsi/libsas/sas_scsi_host.c | 18 -----------
drivers/scsi/mvsas/mv_init.c | 1 -
drivers/scsi/pm8001/pm8001_init.c | 1 -
include/linux/libata.h | 1 +
include/scsi/libsas.h | 1 -
include/scsi/sas_ata.h | 12 ++++---
14 files changed, 109 insertions(+), 66 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c04ad68..1654c94 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5874,29 +5874,31 @@ void ata_host_init(struct ata_host *host, struct device *dev,
host->ops = ops;
}
-int ata_port_probe(struct ata_port *ap)
+void __ata_port_probe(struct ata_port *ap)
{
- int rc = 0;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ unsigned long flags;
- /* probe */
- if (ap->ops->error_handler) {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- unsigned long flags;
+ /* kick EH for boot probing */
+ spin_lock_irqsave(ap->lock, flags);
- /* kick EH for boot probing */
- spin_lock_irqsave(ap->lock, flags);
+ ehi->probe_mask |= ATA_ALL_DEVICES;
+ ehi->action |= ATA_EH_RESET;
+ ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
- ehi->probe_mask |= ATA_ALL_DEVICES;
- ehi->action |= ATA_EH_RESET;
- ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+ ap->pflags &= ~ATA_PFLAG_INITIALIZING;
+ ap->pflags |= ATA_PFLAG_LOADING;
+ ata_port_schedule_eh(ap);
- ap->pflags &= ~ATA_PFLAG_INITIALIZING;
- ap->pflags |= ATA_PFLAG_LOADING;
- ata_port_schedule_eh(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
+}
- spin_unlock_irqrestore(ap->lock, flags);
+int ata_port_probe(struct ata_port *ap)
+{
+ int rc = 0;
- /* wait for EH to finish */
+ if (ap->ops->error_handler) {
+ __ata_port_probe(ap);
ata_port_wait_eh(ap);
} else {
DPRINTK("ata%u: bus probe begin\n", ap->print_id);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2a5412e..faf8730 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3837,6 +3837,19 @@ void ata_sas_port_stop(struct ata_port *ap)
}
EXPORT_SYMBOL_GPL(ata_sas_port_stop);
+int ata_sas_async_port_init(struct ata_port *ap)
+{
+ int rc = ap->ops->port_start(ap);
+
+ if (!rc) {
+ ap->print_id = ata_print_id++;
+ __ata_port_probe(ap);
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ata_sas_async_port_init);
+
/**
* ata_sas_port_init - Initialize a SATA device
* @ap: SATA port to initialize
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 78c356d..2a2aa51 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -104,6 +104,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct ata_port *ata_port_alloc(struct ata_host *host);
extern const char *sata_spd_string(unsigned int spd);
extern int ata_port_probe(struct ata_port *ap);
+extern void __ata_port_probe(struct ata_port *ap);
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index eea988a..ff80552 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -81,7 +81,6 @@ static struct scsi_host_template aic94xx_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
};
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 437f76b..9a28270 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -157,7 +157,6 @@ static struct scsi_host_template isci_sht = {
.sg_tablesize = SG_ALL,
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
.use_clustering = ENABLE_CLUSTERING,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = isci_host_attrs,
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 4751829..fe60736 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -585,11 +585,10 @@ static struct ata_port_info sata_port_info = {
.port_ops = &sas_sata_ops
};
-int sas_ata_init_host_and_port(struct domain_device *found_dev,
- struct scsi_target *starget)
+int sas_ata_init_host_and_port(struct domain_device *found_dev)
{
- struct Scsi_Host *shost = dev_to_shost(&starget->dev);
- struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
+ struct sas_ha_struct *ha = found_dev->port->ha;
+ struct Scsi_Host *shost = ha->core.shost;
struct ata_port *ap;
ata_host_init(&found_dev->sata_dev.ata_host,
@@ -683,6 +682,38 @@ static void sas_get_ata_command_set(struct domain_device *dev)
dev->sata_dev.command_set = ATAPI_COMMAND_SET;
}
+void sas_probe_sata(struct asd_sas_port *port)
+{
+ struct domain_device *dev, *n;
+ int err;
+
+ mutex_lock(&port->ha->disco_mutex);
+ list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+ if (!dev_is_sata(dev))
+ continue;
+
+ err = sas_ata_init_host_and_port(dev);
+ if (err)
+ sas_fail_probe(dev, __func__, err);
+ else
+ ata_sas_async_port_init(dev->sata_dev.ap);
+ }
+ mutex_unlock(&port->ha->disco_mutex);
+
+ list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+ if (!dev_is_sata(dev))
+ continue;
+
+ sas_ata_wait_eh(dev);
+
+ /* if libata could not bring the link up, don't surface
+ * the device
+ */
+ if (ata_dev_disabled(sas_to_ata_dev(dev)))
+ sas_fail_probe(dev, __func__, -ENODEV);
+ }
+}
+
/**
* sas_discover_sata -- discover an STP/SATA domain device
* @dev: pointer to struct domain_device of interest
@@ -731,9 +762,9 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
void sas_ata_strategy_handler(struct Scsi_Host *shost)
{
- struct scsi_device *sdev;
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
LIST_HEAD(async);
+ int i;
/* it's ok to defer revalidation events during ata eh, these
* disks are in one of three states:
@@ -745,14 +776,21 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
*/
sas_disable_revalidation(sas_ha);
- shost_for_each_device(sdev, shost) {
- struct domain_device *ddev = sdev_to_domain_dev(sdev);
+ spin_lock_irq(&sas_ha->phy_port_lock);
+ for (i = 0; i < sas_ha->num_phys; i++) {
+ struct asd_sas_port *port = sas_ha->sas_port[i];
+ struct domain_device *dev;
- if (!dev_is_sata(ddev))
- continue;
-
- async_schedule_domain(async_sas_ata_eh, ddev, &async);
+ spin_lock(&port->dev_list_lock);
+ list_for_each_entry(dev, &port->dev_list, dev_list_node) {
+ if (!dev_is_sata(dev))
+ continue;
+ async_schedule_domain(async_sas_ata_eh, dev, &async);
+ }
+ spin_unlock(&port->dev_list_lock);
}
+ spin_unlock_irq(&sas_ha->phy_port_lock);
+
async_synchronize_full_domain(&async);
sas_enable_revalidation(sas_ha);
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index f60b602..ed3f8c0 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -207,22 +207,22 @@ static void sas_probe_devices(struct work_struct *work)
clear_bit(DISCE_PROBE, &port->disc.pending);
- list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
- int err;
-
+ /* devices must be domain members before link recovery and probe */
+ list_for_each_entry(dev, &port->disco_list, disco_list_node) {
spin_lock_irq(&port->dev_list_lock);
list_add_tail(&dev->dev_list_node, &port->dev_list);
spin_unlock_irq(&port->dev_list_lock);
+ }
- err = sas_rphy_add(dev->rphy);
+ sas_probe_sata(port);
- if (err) {
- SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
- __func__, dev->parent ? "exp-attached" :
- "direct-attached",
- SAS_ADDR(dev->sas_addr), err);
- sas_unregister_dev(port, dev);
- } else
+ list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+ int err;
+
+ err = sas_rphy_add(dev->rphy);
+ if (err)
+ sas_fail_probe(dev, __func__, err);
+ else
list_del_init(&dev->disco_list_node);
}
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index e028d7a..d0d9bf1 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -113,6 +113,15 @@ static inline int sas_smp_host_handler(struct Scsi_Host *shost,
}
#endif
+static inline void sas_fail_probe(struct domain_device *dev, const char *func, int err)
+{
+ SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
+ func, dev->parent ? "exp-attached" :
+ "direct-attached",
+ SAS_ADDR(dev->sas_addr), err);
+ sas_unregister_dev(dev->port, dev);
+}
+
static inline void sas_fill_in_rphy(struct domain_device *dev,
struct sas_rphy *rphy)
{
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index e58ca50..3701ff7 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -762,17 +762,10 @@ int sas_target_alloc(struct scsi_target *starget)
{
struct sas_rphy *rphy = dev_to_rphy(starget->dev.parent);
struct domain_device *found_dev = sas_find_dev_by_rphy(rphy);
- int res;
if (!found_dev)
return -ENODEV;
- if (dev_is_sata(found_dev)) {
- res = sas_ata_init_host_and_port(found_dev, starget);
- if (res)
- return res;
- }
-
kref_get(&found_dev->kref);
starget->hostdata = found_dev;
return 0;
@@ -1012,16 +1005,6 @@ void sas_task_abort(struct sas_task *task)
}
}
-int sas_slave_alloc(struct scsi_device *scsi_dev)
-{
- struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
-
- if (dev_is_sata(dev))
- return ata_sas_port_init(dev->sata_dev.ap);
-
- return 0;
-}
-
void sas_target_destroy(struct scsi_target *starget)
{
struct domain_device *found_dev = starget->hostdata;
@@ -1082,6 +1065,5 @@ 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_slave_alloc);
EXPORT_SYMBOL_GPL(sas_target_destroy);
EXPORT_SYMBOL_GPL(sas_ioctl);
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index d45878b..cc59dff 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -73,7 +73,6 @@ static struct scsi_host_template mvs_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = mvst_host_attrs,
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index bd165ea..36efaa7 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -75,7 +75,6 @@ static struct scsi_host_template pm8001_sht = {
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.shost_attrs = pm8001_host_attrs,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index aa42704..42378d6 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -996,6 +996,7 @@ extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev,
extern void ata_sas_port_destroy(struct ata_port *);
extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
struct ata_port_info *, struct Scsi_Host *);
+extern int ata_sas_async_port_init(struct ata_port *);
extern int ata_sas_port_init(struct ata_port *);
extern int ata_sas_port_start(struct ata_port *ap);
extern void ata_sas_port_stop(struct ata_port *ap);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 4a42be3..20153d5 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -646,7 +646,6 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset);
int sas_queue_up(struct sas_task *task);
extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *);
extern int sas_target_alloc(struct scsi_target *);
-extern int sas_slave_alloc(struct scsi_device *);
extern int sas_slave_configure(struct scsi_device *);
extern int sas_change_queue_depth(struct scsi_device *, int new_depth,
int reason);
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index 1556eff..cdccd2e 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -37,15 +37,14 @@ static inline int dev_is_sata(struct domain_device *dev)
}
int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
-int sas_ata_init_host_and_port(struct domain_device *found_dev,
- struct scsi_target *starget);
-
+int sas_ata_init_host_and_port(struct domain_device *found_dev);
void sas_ata_task_abort(struct sas_task *task);
void sas_ata_strategy_handler(struct Scsi_Host *shost);
void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
struct list_head *done_q);
void sas_ata_schedule_reset(struct domain_device *dev);
void sas_ata_wait_eh(struct domain_device *dev);
+void sas_probe_sata(struct asd_sas_port *port);
#else
@@ -53,8 +52,7 @@ static inline int dev_is_sata(struct domain_device *dev)
{
return 0;
}
-static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
- struct scsi_target *starget)
+static inline int sas_ata_init_host_and_port(struct domain_device *found_dev)
{
return 0;
}
@@ -79,6 +77,10 @@ static inline void sas_ata_wait_eh(struct domain_device *dev)
{
}
+static inline void sas_probe_sata(struct asd_sas_port *port)
+{
+}
+
static inline int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
{
return 0;
^ permalink raw reply related [flat|nested] 13+ messages in thread
* RE: [PATCH v6 0/7] libsas error handling + discovery v6
2012-01-21 1:50 [PATCH v6 0/7] libsas error handling + discovery v6 Dan Williams
` (6 preceding siblings ...)
2012-01-21 1:51 ` [PATCH v6 7/7] libsas: async ata scanning Dan Williams
@ 2012-01-21 6:12 ` Jack Wang
2012-01-23 20:57 ` Dan Williams
7 siblings, 1 reply; 13+ messages in thread
From: Jack Wang @ 2012-01-21 6:12 UTC (permalink / raw)
To: 'Dan Williams', linux-scsi; +Cc: linux-ide
> Changes since v5: http://marc.info/?l=linux-scsi&m=132656475829637&w=2
>
> 1/ Reworked "libsas: let libata recover links that fail to transmit
initial
> sig-fis" to better handle problematic expanders and slow to attach ata
> devices. libsas will now validate linkrate and take 'device-type' into
> account when determining if a new device is attached.
>
> 2/ Added support for asynchronously scanning ata devices.
>
> 3/ Reworked "libsas: fix sas_unregister_ports vs sas_drain_work" as
lockdep
> complained about the original.
>
> 4/ New patch "libsas: fix sas port naming" makes direct-attached device
naming
> more predictable and consistent with expander attached device naming.
>
> 5/ Made scan order more predictable by ensuring that regardless of device
type
> we always attach in discovery order. Slow to link devices will still
be
> scanned out of order, link needs to be in at least the 'stp pending'
state
> before the device will be considered attached.
>
[Jack Wang]
Asynchronously scan really make the discovery far more quickly, with v4
reset expander will need more than 3 minites to get discovered, with this v6
patchset it takes less than 5 seconds.
Dear Dan,
Could you share how you test procedure to find out these bugs?
Thanks.
> ---
>
> Dan Williams (7):
> libsas: fix sas_unregister_ports vs sas_drain_work
> libsas: improve ata debug statements
> libsas: fix sas port naming
> libsas: let libata recover links that fail to transmit initial
sig-fis
> libsas: delete device on sas address changed
> libsas: restore scan order
> libsas: async ata scanning
>
>
> drivers/ata/libata-core.c | 34 +++--
> drivers/ata/libata-scsi.c | 13 ++
> drivers/ata/libata.h | 1
> drivers/scsi/aic94xx/aic94xx_init.c | 1
> drivers/scsi/isci/init.c | 1
> drivers/scsi/libsas/sas_ata.c | 187 +++++++++++++++++++++--------
> drivers/scsi/libsas/sas_discover.c | 47 +++++--
> drivers/scsi/libsas/sas_event.c | 19 ++-
> drivers/scsi/libsas/sas_expander.c | 229
> +++++++++++++++++++++--------------
> drivers/scsi/libsas/sas_init.c | 18 ++-
> drivers/scsi/libsas/sas_internal.h | 16 ++
> drivers/scsi/libsas/sas_port.c | 2
> drivers/scsi/libsas/sas_scsi_host.c | 18 ---
> drivers/scsi/mvsas/mv_init.c | 1
> drivers/scsi/pm8001/pm8001_init.c | 1
> include/linux/libata.h | 1
> include/scsi/libsas.h | 1
> include/scsi/sas.h | 4 -
> include/scsi/sas_ata.h | 23 ++--
> 19 files changed, 398 insertions(+), 219 deletions(-)
>
>
> Full snapshot in git: note that
libsas-eh-reworks-v4..libsas-eh-reworks-v6
> is
> a fast-forward, but that will not always be the case.
>
> The following changes since commit
76ffe8a3f766358a0ade543153625b3e4e66159d:
>
> [SCSI] libfc: remove redundant timer init for fcp (2012-01-16 12:47:18
+0400)
>
> are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git
> libsas-eh-reworks-v6
>
> Dan Williams (47):
> libsas: remove unused ata_task_resp fields
> libsas: kill sas_slave_destroy
> libsas: fix domain_device leak
> libsas: fix leak of dev->sata_dev.identify_[packet_]device
> libsas: replace event locks with atomic bitops
> libsas: convert ha->state to flags
> libsas: introduce sas_drain_work()
> libsas: remove ata_port.lock management duties from lldds
> libsas: convert dev->gone to flags
> libsas: prevent domain rediscovery competing with ata error handling
> libsas: use ->set_dmamode to notify lldds of NCQ parameters
> libsas: kill invocation of scsi_eh_finish_cmd from sas_ata_task_done
> libsas: close error handling vs sas_ata_task_done() race
> libsas: prevent double completion of scmds from eh
> libsas: fix timeout vs completion race
> libsas: let libata handle command timeouts
> libsas: defer SAS_TASK_NEED_DEV_RESET commands to libata
> libsas: use libata-eh-reset for sata rediscovery fis transmit
failures
> libsas: perform sas-transport resets in shost->workq context
> libsas: execute transport link resets with libata-eh via host
workqueue
> libsas: sas_phy_enable via transport_sas_phy_reset
> libsas: async ata-eh
> libsas: poll for ata device readiness after reset
> libsas: don't mark expanders as gone when a child device is removed
> libsas: check for 'gone' expanders in smp_execute_task()
> libsas: fix sas_find_local_phy(), take phy references
> libsas: don't recover 'gone' devices in sas_ata_hard_reset()
> isci: kill iphy->isci_port lookups
> isci: kill isci_port->status
> isci: fix interpretation of "hard" reset
> isci: stop interpreting ->lldd_lu_reset() as an ata soft-reset
> isci: ->lldd_ata_check_ready handler
> isci: remove bus and reset handlers
> isci: remove IDEV_EH hack to disable "discovery-time" ata resets
> libsas: pre-clean commands that won the eh vs completion race
> libsas: feed the scsi_block_when_processing_errors() meter
> libsas: mark all domain devices gone if root port disappears
> libsas: close scsi_remove_target() vs libata-eh race
> libsas: fix mixed topology recovery
> libsas: route local link resets through ata-eh
> libsas: fix sas_unregister_ports vs sas_drain_work
> libsas: improve ata debug statements
> libsas: fix sas port naming
> libsas: let libata recover links that fail to transmit initial
sig-fis
> libsas: delete device on sas address changed
> libsas: restore scan order
> libsas: async ata scanning
>
> Jeff Skirvin (2):
> libsas: Remove redundant phy state notification calls.
> libsas: add mutex for SMP task execution
>
> Maciej Trela (1):
> libsas: kill spurious sas_put_device
>
> Documentation/scsi/libsas.txt | 15 -
> drivers/ata/libata-core.c | 34 +-
> drivers/ata/libata-eh.c | 1 +
> drivers/ata/libata-scsi.c | 13 +
> drivers/ata/libata.h | 2 +-
> drivers/scsi/aic94xx/aic94xx.h | 2 +
> drivers/scsi/aic94xx/aic94xx_dev.c | 38 +-
> drivers/scsi/aic94xx/aic94xx_init.c | 6 +-
> drivers/scsi/aic94xx/aic94xx_tmf.c | 9 +-
> drivers/scsi/isci/host.c | 8 +-
> drivers/scsi/isci/host.h | 19 +-
> drivers/scsi/isci/init.c | 14 +-
> drivers/scsi/isci/phy.c | 18 +-
> drivers/scsi/isci/phy.h | 1 -
> drivers/scsi/isci/port.c | 217 +++++-----
> drivers/scsi/isci/port.h | 11 +-
> drivers/scsi/isci/remote_device.c | 32 +-
> drivers/scsi/isci/remote_device.h | 7 +-
> drivers/scsi/isci/request.c | 198 +--------
> drivers/scsi/isci/request.h | 9 +-
> drivers/scsi/isci/task.c | 158 ++------
> drivers/scsi/isci/task.h | 40 --
> drivers/scsi/libsas/sas_ata.c | 818
> +++++++++++++++++------------------
> drivers/scsi/libsas/sas_discover.c | 204 +++++++--
> drivers/scsi/libsas/sas_event.c | 96 ++++-
> drivers/scsi/libsas/sas_expander.c | 304 +++++++++-----
> drivers/scsi/libsas/sas_host_smp.c | 11 +-
> drivers/scsi/libsas/sas_init.c | 211 ++++++++-
> drivers/scsi/libsas/sas_internal.h | 80 +++--
> drivers/scsi/libsas/sas_phy.c | 12 +-
> drivers/scsi/libsas/sas_port.c | 30 +-
> drivers/scsi/libsas/sas_scsi_host.c | 354 +++++++---------
> drivers/scsi/mvsas/mv_init.c | 2 -
> drivers/scsi/mvsas/mv_sas.c | 11 +-
> drivers/scsi/pm8001/pm8001_init.c | 2 -
> drivers/scsi/pm8001/pm8001_sas.c | 29 +-
> drivers/scsi/scsi_transport_sas.c | 59 +++-
> include/linux/libata.h | 2 +
> include/scsi/libsas.h | 70 ++--
> include/scsi/sas.h | 4 +-
> include/scsi/sas_ata.h | 44 ++-
> include/scsi/scsi_transport_sas.h | 12 +-
> 42 files changed, 1686 insertions(+), 1521 deletions(-)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 0/7] libsas error handling + discovery v6
2012-01-21 6:12 ` [PATCH v6 0/7] libsas error handling + discovery v6 Jack Wang
@ 2012-01-23 20:57 ` Dan Williams
0 siblings, 0 replies; 13+ messages in thread
From: Dan Williams @ 2012-01-23 20:57 UTC (permalink / raw)
To: Jack Wang; +Cc: linux-scsi, linux-ide
On Fri, Jan 20, 2012 at 10:12 PM, Jack Wang <jack_wang@usish.com> wrote:
>> Changes since v5: http://marc.info/?l=linux-scsi&m=132656475829637&w=2
>>
>> 1/ Reworked "libsas: let libata recover links that fail to transmit
> initial
>> sig-fis" to better handle problematic expanders and slow to attach ata
>> devices. libsas will now validate linkrate and take 'device-type' into
>> account when determining if a new device is attached.
>>
>> 2/ Added support for asynchronously scanning ata devices.
>>
>> 3/ Reworked "libsas: fix sas_unregister_ports vs sas_drain_work" as
> lockdep
>> complained about the original.
>>
>> 4/ New patch "libsas: fix sas port naming" makes direct-attached device
> naming
>> more predictable and consistent with expander attached device naming.
>>
>> 5/ Made scan order more predictable by ensuring that regardless of device
> type
>> we always attach in discovery order. Slow to link devices will still
> be
>> scanned out of order, link needs to be in at least the 'stp pending'
> state
>> before the device will be considered attached.
>>
> [Jack Wang]
> Asynchronously scan really make the discovery far more quickly, with v4
> reset expander will need more than 3 minites to get discovered, with this v6
> patchset it takes less than 5 seconds.
Great!
> Dear Dan,
>
> Could you share how you test procedure to find out these bugs?
>
These fixes have primarily been driven by libsas ata error handling as
robust as libata, and teaching libsas that ata links need more care
and handling than it was giving before.
In the case of async probing, this is something that libata has had
since 2.6.29, but was never added to libsas.
--
Dan
^ permalink raw reply [flat|nested] 13+ messages in thread