[SCSI] libsas: improve debug statements
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. As Doug notes, we can also take the opportunity to clarify expander phy routing capabilities. [dgilbert@interlog.com: clarify table2table with 'U'] Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
committed by
James Bottomley
parent
fdfd9d1b89
commit
d214d81e88
@@ -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,
|
static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline)
|
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);
|
res = i->dft->lldd_I_T_nexus_reset(dev);
|
||||||
|
|
||||||
if (res != TMF_RESP_FUNC_COMPLETE)
|
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);
|
phy = sas_get_local_phy(dev);
|
||||||
if (scsi_is_sas_phy_local(phy))
|
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);
|
ret = ata_wait_after_reset(link, deadline, check_ready);
|
||||||
if (ret && ret != -EAGAIN)
|
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
|
/* XXX: if the class changes during the reset the upper layer
|
||||||
* should be informed, if the device has gone away we assume
|
* 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
|
* remove once all commands are completed
|
||||||
*/
|
*/
|
||||||
kref_get(&dev->kref);
|
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);
|
ata_scsi_port_error_handler(ha->core.shost, ap);
|
||||||
sas_put_device(dev);
|
sas_put_device(dev);
|
||||||
}
|
}
|
||||||
@@ -703,26 +725,27 @@ void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
|||||||
struct list_head *done_q)
|
struct list_head *done_q)
|
||||||
{
|
{
|
||||||
struct scsi_cmnd *cmd, *n;
|
struct scsi_cmnd *cmd, *n;
|
||||||
struct ata_port *ap;
|
struct domain_device *eh_dev;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
LIST_HEAD(sata_q);
|
LIST_HEAD(sata_q);
|
||||||
|
eh_dev = NULL;
|
||||||
ap = NULL;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
|
list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
|
||||||
struct domain_device *ddev = cmd_to_domain_dev(cmd);
|
struct domain_device *ddev = cmd_to_domain_dev(cmd);
|
||||||
|
|
||||||
if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
|
if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
|
||||||
continue;
|
continue;
|
||||||
if (ap && ap != ddev->sata_dev.ap)
|
if (eh_dev && eh_dev != ddev)
|
||||||
continue;
|
continue;
|
||||||
ap = ddev->sata_dev.ap;
|
eh_dev = ddev;
|
||||||
list_move(&cmd->eh_entry, &sata_q);
|
list_move(&cmd->eh_entry, &sata_q);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list_empty(&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_scsi_cmd_error_handler(shost, ap, &sata_q);
|
||||||
/*
|
/*
|
||||||
* ata's error handler may leave the cmd on the list
|
* ata's error handler may leave the cmd on the list
|
||||||
@@ -738,7 +761,7 @@ void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
|
|||||||
while (!list_empty(&sata_q))
|
while (!list_empty(&sata_q))
|
||||||
list_del_init(sata_q.next);
|
list_del_init(sata_q.next);
|
||||||
}
|
}
|
||||||
} while (ap);
|
} while (eh_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sas_ata_schedule_reset(struct domain_device *dev)
|
void sas_ata_schedule_reset(struct domain_device *dev)
|
||||||
|
|||||||
@@ -166,7 +166,22 @@ static inline void *alloc_smp_resp(int size)
|
|||||||
return kzalloc(size, GFP_KERNEL);
|
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,
|
static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
|
||||||
void *disc_resp)
|
void *disc_resp)
|
||||||
@@ -176,9 +191,10 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
|
|||||||
struct smp_resp *resp = disc_resp;
|
struct smp_resp *resp = disc_resp;
|
||||||
struct discover_resp *dr = &resp->disc;
|
struct discover_resp *dr = &resp->disc;
|
||||||
struct sas_rphy *rphy = dev->rphy;
|
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);
|
phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
|
||||||
|
|
||||||
/* FIXME: error_handling */
|
/* FIXME: error_handling */
|
||||||
@@ -223,20 +239,41 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
|
|||||||
phy->phy->maximum_linkrate = dr->pmax_linkrate;
|
phy->phy->maximum_linkrate = dr->pmax_linkrate;
|
||||||
phy->phy->negotiated_linkrate = phy->linkrate;
|
phy->phy->negotiated_linkrate = phy->linkrate;
|
||||||
|
|
||||||
if (!rediscover)
|
if (new_phy)
|
||||||
if (sas_phy_add(phy->phy)) {
|
if (sas_phy_add(phy->phy)) {
|
||||||
sas_phy_free(phy->phy);
|
sas_phy_free(phy->phy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
|
switch (phy->attached_dev_type) {
|
||||||
SAS_ADDR(dev->sas_addr), phy->phy_id,
|
case NO_DEVICE:
|
||||||
phy->routing_attr == TABLE_ROUTING ? 'T' :
|
type = "no device";
|
||||||
phy->routing_attr == DIRECT_ROUTING ? 'D' :
|
break;
|
||||||
phy->routing_attr == SUBTRACTIVE_ROUTING ? 'S' : '?',
|
case SAS_END_DEV:
|
||||||
SAS_ADDR(phy->attached_sas_addr));
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
|
||||||
|
SAS_ADDR(dev->sas_addr), phy->phy_id,
|
||||||
|
sas_route_char(dev, phy), phy->linkrate,
|
||||||
|
SAS_ADDR(phy->attached_sas_addr), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if we have an existing attached ata device on this expander phy */
|
/* check if we have an existing attached ata device on this expander phy */
|
||||||
@@ -1176,32 +1213,25 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
|
|||||||
struct ex_phy *parent_phy,
|
struct ex_phy *parent_phy,
|
||||||
struct ex_phy *child_phy)
|
struct ex_phy *child_phy)
|
||||||
{
|
{
|
||||||
static const char ra_char[] = {
|
|
||||||
[DIRECT_ROUTING] = 'D',
|
|
||||||
[SUBTRACTIVE_ROUTING] = 'S',
|
|
||||||
[TABLE_ROUTING] = 'T',
|
|
||||||
};
|
|
||||||
static const char *ex_type[] = {
|
static const char *ex_type[] = {
|
||||||
[EDGE_DEV] = "edge",
|
[EDGE_DEV] = "edge",
|
||||||
[FANOUT_DEV] = "fanout",
|
[FANOUT_DEV] = "fanout",
|
||||||
};
|
};
|
||||||
struct domain_device *parent = child->parent;
|
struct domain_device *parent = child->parent;
|
||||||
|
|
||||||
sas_printk("%s ex %016llx (T2T supp:%d) phy 0x%x <--> %s ex %016llx "
|
sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx "
|
||||||
"(T2T supp:%d) phy 0x%x has %c:%c routing link!\n",
|
"phy 0x%x has %c:%c routing link!\n",
|
||||||
|
|
||||||
ex_type[parent->dev_type],
|
ex_type[parent->dev_type],
|
||||||
SAS_ADDR(parent->sas_addr),
|
SAS_ADDR(parent->sas_addr),
|
||||||
parent->ex_dev.t2t_supp,
|
|
||||||
parent_phy->phy_id,
|
parent_phy->phy_id,
|
||||||
|
|
||||||
ex_type[child->dev_type],
|
ex_type[child->dev_type],
|
||||||
SAS_ADDR(child->sas_addr),
|
SAS_ADDR(child->sas_addr),
|
||||||
child->ex_dev.t2t_supp,
|
|
||||||
child_phy->phy_id,
|
child_phy->phy_id,
|
||||||
|
|
||||||
ra_char[parent_phy->routing_attr],
|
sas_route_char(parent, parent_phy),
|
||||||
ra_char[child_phy->routing_attr]);
|
sas_route_char(child, child_phy));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sas_check_eeds(struct domain_device *child,
|
static int sas_check_eeds(struct domain_device *child,
|
||||||
|
|||||||
Reference in New Issue
Block a user