summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_sas.c
diff options
context:
space:
mode:
authorMark Salyzyn2012-01-17 15:18:57 +0100
committerJames Bottomley2012-02-19 15:08:51 +0100
commitd95d00016f8f51dc502cadb263d861bd8c0212bb (patch)
treeaa60333c6d9aa97f3dc1f32f0fce3f3f08baa939 /drivers/scsi/pm8001/pm8001_sas.c
parent[SCSI] pm8001: fix lockup on phy_control hard reset. (diff)
downloadkernel-qcow2-linux-d95d00016f8f51dc502cadb263d861bd8c0212bb.tar.gz
kernel-qcow2-linux-d95d00016f8f51dc502cadb263d861bd8c0212bb.tar.xz
kernel-qcow2-linux-d95d00016f8f51dc502cadb263d861bd8c0212bb.zip
[SCSI] pm8001: Add FUNC_GET_EVENTS
Jack noticed I dropped a patch fragment associated with a flags automatic variable in mpi_set_phys_g3_with_ssc (ooops) and that the pre-emptive locking that piggy-backed this patch was not in-fact necessary because of underlying atomic accesses to the hardware. Here is the updated patch fixing these two issues. The pm8001 driver is missing the FUNC_GET_EVENTS handler in the phy control function. Since the pm8001_bar4_shift function was not designed to be called at runtime, added locking surrounding the adjustment for all accesses. Signed-off-by: Mark Salyzyn <mark_salyzyn@xyratex.com> Acked-by: Jack Wang <jack_wang@usish.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_sas.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 7ae22a67bd31..ab0704e39040 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -166,6 +166,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates;
DECLARE_COMPLETION_ONSTACK(completion);
+ unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha;
pm8001_ha->phy[phy_id].enable_completion = &completion;
switch (func) {
@@ -209,8 +210,29 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
case PHY_FUNC_DISABLE:
PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
break;
+ case PHY_FUNC_GET_EVENTS:
+ spin_lock_irqsave(&pm8001_ha->lock, flags);
+ if (-1 == pm8001_bar4_shift(pm8001_ha,
+ (phy_id < 4) ? 0x30000 : 0x40000)) {
+ spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+ return -EINVAL;
+ }
+ {
+ struct sas_phy *phy = sas_phy->phy;
+ uint32_t *qp = (uint32_t *)(((char *)
+ pm8001_ha->io_mem[2].memvirtaddr)
+ + 0x1034 + (0x4000 * (phy_id & 3)));
+
+ phy->invalid_dword_count = qp[0];
+ phy->running_disparity_error_count = qp[1];
+ phy->loss_of_dword_sync_count = qp[3];
+ phy->phy_reset_problem_count = qp[4];
+ }
+ pm8001_bar4_shift(pm8001_ha, 0);
+ spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+ return 0;
default:
- rc = -ENOSYS;
+ rc = -EOPNOTSUPP;
}
msleep(300);
return rc;