Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 293006
b: refs/heads/master
c: f41a0c4
h: refs/heads/master
v: v3
  • Loading branch information
Dan Williams authored and James Bottomley committed Feb 29, 2012
1 parent d4c6f32 commit f174d84
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3a9c5560f677690f65038f399f4f598c79b83186
refs/heads/master: f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cd
9 changes: 6 additions & 3 deletions trunk/drivers/scsi/aic94xx/aic94xx_tmf.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ static int asd_clear_nexus_I_T(struct domain_device *dev,
int asd_I_T_nexus_reset(struct domain_device *dev)
{
int res, tmp_res, i;
struct sas_phy *phy = sas_find_local_phy(dev);
struct sas_phy *phy = sas_get_local_phy(dev);
/* Standard mandates link reset for ATA (type 0) and
* hard reset for SSP (type 1) */
int reset_type = (dev->dev_type == SATA_DEV ||
Expand All @@ -201,7 +201,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
for (i = 0 ; i < 3; i++) {
tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);
if (tmp_res == TC_RESUME)
return res;
goto out;
msleep(500);
}

Expand All @@ -211,7 +211,10 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
dev_printk(KERN_ERR, &phy->dev,
"Failed to resume nexus after reset 0x%x\n", tmp_res);

return TMF_RESP_FUNC_FAILED;
res = TMF_RESP_FUNC_FAILED;
out:
sas_put_local_phy(phy);
return res;
}

static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/scsi/isci/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ isci_task_request_complete(struct isci_host *ihost,
static int isci_reset_device(struct isci_host *ihost,
struct isci_remote_device *idev)
{
struct sas_phy *phy = sas_find_local_phy(idev->domain_dev);
struct sas_phy *phy = sas_get_local_phy(idev->domain_dev);
enum sci_status status;
unsigned long flags;
int rc;
Expand All @@ -1347,8 +1347,8 @@ static int isci_reset_device(struct isci_host *ihost,
dev_dbg(&ihost->pdev->dev,
"%s: sci_remote_device_reset(%p) returned %d!\n",
__func__, idev, status);

return TMF_RESP_FUNC_FAILED;
rc = TMF_RESP_FUNC_FAILED;
goto out;
}
spin_unlock_irqrestore(&ihost->scic_lock, flags);

Expand All @@ -1369,7 +1369,8 @@ static int isci_reset_device(struct isci_host *ihost,
}

dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev);

out:
sas_put_local_phy(phy);
return rc;
}

Expand Down
7 changes: 5 additions & 2 deletions trunk/drivers/scsi/libsas/sas_ata.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,10 @@ static int smp_ata_check_ready(struct ata_link *link)
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_find_local_phy(dev);
struct sas_phy *phy = sas_get_local_phy(dev);

res = sas_get_phy_attached_sas_addr(ex_dev, phy->number, addr);
sas_put_local_phy(phy);
/* break the wait early if the expander is unreachable,
* otherwise keep polling
*/
Expand Down Expand Up @@ -319,21 +320,23 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
int ret = 0, res;
struct sas_phy *phy;
struct ata_port *ap = link->ap;
int (*check_ready)(struct ata_link *link);
struct domain_device *dev = ap->private_data;
struct sas_phy *phy = sas_find_local_phy(dev);
struct sas_internal *i = dev_to_sas_internal(dev);

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__);

phy = sas_get_local_phy(dev);
if (scsi_is_sas_phy_local(phy))
check_ready = local_ata_check_ready;
else
check_ready = smp_ata_check_ready;
sas_put_local_phy(phy);

ret = ata_wait_after_reset(link, deadline, check_ready);
if (ret && ret != -EAGAIN)
Expand Down
24 changes: 24 additions & 0 deletions trunk/drivers/scsi/libsas/sas_discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE);
memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE);
port->disc.max_level = 0;
sas_device_set_phy(dev, port->port);

dev->rphy = rphy;

Expand Down Expand Up @@ -234,6 +235,9 @@ void sas_free_device(struct kref *kref)
if (dev->parent)
sas_put_device(dev->parent);

sas_port_put_phy(dev->phy);
dev->phy = NULL;

/* remove the phys and ports, everything else should be gone */
if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
kfree(dev->ex_dev.ex_phy);
Expand Down Expand Up @@ -308,6 +312,26 @@ void sas_unregister_domain_devices(struct asd_sas_port *port)

}

void sas_device_set_phy(struct domain_device *dev, struct sas_port *port)
{
struct sas_ha_struct *ha;
struct sas_phy *new_phy;

if (!dev)
return;

ha = dev->port->ha;
new_phy = sas_port_get_phy(port);

/* pin and record last seen phy */
spin_lock_irq(&ha->phy_port_lock);
if (new_phy) {
sas_port_put_phy(dev->phy);
dev->phy = new_phy;
}
spin_unlock_irq(&ha->phy_port_lock);
}

/* ---------- Discovery and Revalidation ---------- */

/**
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/scsi/libsas/sas_expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ static struct domain_device *sas_ex_discover_end_dev(
}
}
sas_ex_get_linkrate(parent, child, phy);
sas_device_set_phy(child, phy->port);

#ifdef CONFIG_SCSI_SAS_ATA
if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
Expand Down Expand Up @@ -1810,7 +1811,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
{
struct expander_device *ex_dev = &parent->ex_dev;
struct ex_phy *phy = &ex_dev->ex_phy[phy_id];
struct domain_device *child, *n;
struct domain_device *child, *n, *found = NULL;
if (last) {
list_for_each_entry_safe(child, n,
&ex_dev->children, siblings) {
Expand All @@ -1822,6 +1823,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
sas_unregister_ex_tree(parent->port, child);
else
sas_unregister_dev(parent->port, child);
found = child;
break;
}
}
Expand All @@ -1830,6 +1832,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
if (phy->port) {
sas_port_delete_phy(phy->port, phy->phy);
sas_device_set_phy(found, phy->port);
if (phy->port->num_phys == 0)
sas_port_delete(phy->port);
phy->port = NULL;
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/scsi/libsas/sas_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id,
enum phy_func phy_func, struct sas_phy_linkrates *);
int sas_smp_get_phy_events(struct sas_phy *phy);

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,
Expand Down
7 changes: 3 additions & 4 deletions trunk/drivers/scsi/libsas/sas_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ static void sas_form_port(struct asd_sas_phy *phy)
port->num_phys++;
port->phy_mask |= (1U << phy->id);

if (!port->phy)
port->phy = phy->phy;

if (*(u64 *)port->attached_sas_addr == 0) {
port->class = phy->class;
memcpy(port->attached_sas_addr, phy->attached_sas_addr,
Expand Down Expand Up @@ -175,8 +172,10 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone)
sas_unregister_domain_devices(port);
sas_port_delete(port->port);
port->port = NULL;
} else
} else {
sas_port_delete_phy(port->port, phy->phy);
sas_device_set_phy(dev, port->port);
}

if (si->dft->lldd_port_deformed)
si->dft->lldd_port_deformed(phy);
Expand Down
38 changes: 18 additions & 20 deletions trunk/drivers/scsi/libsas/sas_scsi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,30 +439,26 @@ static int sas_recover_I_T(struct domain_device *dev)
return res;
}

/* Find the sas_phy that's attached to this device */
struct sas_phy *sas_find_local_phy(struct domain_device *dev)
/* take a reference on the last known good phy for this device */
struct sas_phy *sas_get_local_phy(struct domain_device *dev)
{
struct domain_device *pdev = dev->parent;
struct ex_phy *exphy = NULL;
int i;
struct sas_ha_struct *ha = dev->port->ha;
struct sas_phy *phy;
unsigned long flags;

/* Directly attached device */
if (!pdev)
return dev->port->phy;
/* a published domain device always has a valid phy, it may be
* stale, but it is never NULL
*/
BUG_ON(!dev->phy);

/* Otherwise look in the expander */
for (i = 0; i < pdev->ex_dev.num_phys; i++)
if (!memcmp(dev->sas_addr,
pdev->ex_dev.ex_phy[i].attached_sas_addr,
SAS_ADDR_SIZE)) {
exphy = &pdev->ex_dev.ex_phy[i];
break;
}
spin_lock_irqsave(&ha->phy_port_lock, flags);
phy = dev->phy;
get_device(&phy->dev);
spin_unlock_irqrestore(&ha->phy_port_lock, flags);

BUG_ON(!exphy);
return exphy->phy;
return phy;
}
EXPORT_SYMBOL_GPL(sas_find_local_phy);
EXPORT_SYMBOL_GPL(sas_get_local_phy);

/* Attempt to send a LUN reset message to a device */
int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
Expand All @@ -489,14 +485,16 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
{
struct domain_device *dev = cmd_to_domain_dev(cmd);
struct sas_phy *phy = sas_find_local_phy(dev);
struct sas_phy *phy = sas_get_local_phy(dev);
int res;

res = sas_phy_reset(phy, 1);
if (res)
SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
kobject_name(&phy->dev.kobj),
res);
sas_put_local_phy(phy);

if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
return SUCCESS;

Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/scsi/mvsas/mv_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1474,10 +1474,11 @@ static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,
static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
{
int rc;
struct sas_phy *phy = sas_find_local_phy(dev);
struct sas_phy *phy = sas_get_local_phy(dev);
int reset_type = (dev->dev_type == SATA_DEV ||
(dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
rc = sas_phy_reset(phy, reset_type);
sas_put_local_phy(phy);
msleep(2000);
return rc;
}
Expand Down
19 changes: 12 additions & 7 deletions trunk/drivers/scsi/pm8001/pm8001_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,12 +967,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)

pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
phy = sas_find_local_phy(dev);
phy = sas_get_local_phy(dev);

if (dev_is_sata(dev)) {
DECLARE_COMPLETION_ONSTACK(completion_setstate);
if (scsi_is_sas_phy_local(phy))
return 0;
if (scsi_is_sas_phy_local(phy)) {
rc = 0;
goto out;
}
rc = sas_phy_reset(phy, 1);
msleep(2000);
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
Expand All @@ -981,12 +983,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
pm8001_dev, 0x01);
wait_for_completion(&completion_setstate);
} else{
rc = sas_phy_reset(phy, 1);
msleep(2000);
} else {
rc = sas_phy_reset(phy, 1);
msleep(2000);
}
PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
pm8001_dev->device_id, rc));
out:
sas_put_local_phy(phy);
return rc;
}

Expand All @@ -998,10 +1002,11 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
struct pm8001_device *pm8001_dev = dev->lldd_dev;
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
if (dev_is_sata(dev)) {
struct sas_phy *phy = sas_find_local_phy(dev);
struct sas_phy *phy = sas_get_local_phy(dev);
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
dev, 1, 0);
rc = sas_phy_reset(phy, 1);
sas_put_local_phy(phy);
rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
pm8001_dev, 0x01);
msleep(2000);
Expand Down
23 changes: 23 additions & 0 deletions trunk/drivers/scsi/scsi_transport_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,29 @@ int scsi_is_sas_port(const struct device *dev)
}
EXPORT_SYMBOL(scsi_is_sas_port);

/**
* sas_port_get_phy - try to take a reference on a port member
* @port: port to check
*/
struct sas_phy *sas_port_get_phy(struct sas_port *port)
{
struct sas_phy *phy;

mutex_lock(&port->phy_list_mutex);
if (list_empty(&port->phy_list))
phy = NULL;
else {
struct list_head *ent = port->phy_list.next;

phy = list_entry(ent, typeof(*phy), port_siblings);
get_device(&phy->dev);
}
mutex_unlock(&port->phy_list_mutex);

return phy;
}
EXPORT_SYMBOL(sas_port_get_phy);

/**
* sas_port_add_phy - add another phy to a port to form a wide port
* @port: port to add the phy to
Expand Down
Loading

0 comments on commit f174d84

Please sign in to comment.