[SCSI] isci: export phy events via ->lldd_control_phy()
Dan Williams [Thu, 29 Sep 2011 01:48:02 +0000 (18:48 -0700)]
Allow the sas-transport-class to update events for local phys via a new
PHY_FUNC_GET_EVENTS command to ->lldd_control_phy().  Fixup drivers that
are not prepared for new enum phy_func values, and unify
->lldd_control_phy() error codes.

These are the SAS defined phy events that are reported in a
smp-report-phy-error-log command:
 * /sys/class/sas_phy/<phyX>/invalid_dword_count
 * /sys/class/sas_phy/<phyX>/running_disparity_error_count
 * /sys/class/sas_phy/<phyX>/loss_of_dword_sync_count
 * /sys/class/sas_phy/<phyX>/phy_reset_problem_count

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/isci/phy.c
drivers/scsi/libsas/sas_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/pm8001/pm8001_sas.c
include/scsi/sas.h

index 2959327..fdac7c2 100644 (file)
@@ -906,6 +906,7 @@ int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
 
        switch (func) {
        case PHY_FUNC_CLEAR_ERROR_LOG:
+       case PHY_FUNC_GET_EVENTS:
                return -ENOSYS;
        case PHY_FUNC_SET_LINK_RATE:
                rates = arg;
index 430fc8f..ab48bb1 100644 (file)
@@ -1313,6 +1313,17 @@ int isci_phy_control(struct asd_sas_phy *sas_phy,
                ret = isci_port_perform_hard_reset(ihost, iport, iphy);
 
                break;
+       case PHY_FUNC_GET_EVENTS: {
+               struct scu_link_layer_registers __iomem *r;
+               struct sas_phy *phy = sas_phy->phy;
+
+               r = iphy->link_layer_registers;
+               phy->running_disparity_error_count = readl(&r->running_disparity_error_count);
+               phy->loss_of_dword_sync_count = readl(&r->loss_of_sync_error_count);
+               phy->phy_reset_problem_count = readl(&r->phy_reset_problem_count);
+               phy->invalid_dword_count = readl(&r->invalid_dword_counter);
+               break;
+       }
 
        default:
                dev_dbg(&ihost->pdev->dev,
index dd56ea8..d81c3b1 100644 (file)
@@ -177,10 +177,15 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
 
 static int sas_get_linkerrors(struct sas_phy *phy)
 {
-       if (scsi_is_sas_phy_local(phy))
-               /* FIXME: we have no local phy stats
-                * gathering at this time */
-               return -EINVAL;
+       if (scsi_is_sas_phy_local(phy)) {
+               struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+               struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+               struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+               struct sas_internal *i =
+                       to_sas_internal(sas_ha->core.shost->transportt);
+
+               return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
+       }
 
        return sas_smp_get_phy_events(phy);
 }
index d4475d3..a4884a5 100644 (file)
@@ -214,7 +214,7 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                break;
        case PHY_FUNC_RELEASE_SPINUP_HOLD:
        default:
-               rc = -EOPNOTSUPP;
+               rc = -ENOSYS;
        }
        msleep(200);
        return rc;
index 5ac90c3..fb3dc99 100644 (file)
@@ -210,7 +210,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
                break;
        default:
-               rc = -EOPNOTSUPP;
+               rc = -ENOSYS;
        }
        msleep(300);
        return rc;
index cfdbe95..3673d68 100644 (file)
@@ -122,6 +122,7 @@ enum phy_func {
        PHY_FUNC_TX_SATA_PS_SIGNAL,
        PHY_FUNC_RELEASE_SPINUP_HOLD = 0x10, /* LOCAL PORT ONLY! */
        PHY_FUNC_SET_LINK_RATE,
+       PHY_FUNC_GET_EVENTS,
 };
 
 /* SAS LLDD would need to report only _very_few_ of those, like BROADCAST.