]> rtime.felk.cvut.cz Git - zynq/linux.git/blobdiff - drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[zynq/linux.git] / drivers / scsi / hisi_sas / hisi_sas_v3_hw.c
index 9ec8848ec54139248033fa332a70da64195a1f24..086695a4099fc13bd4c555309c5a7bffe6a18e82 100644 (file)
 #define PHY_CTRL_RESET_MSK             (0x1 << PHY_CTRL_RESET_OFF)
 #define CMD_HDR_PIR_OFF                        8
 #define CMD_HDR_PIR_MSK                        (0x1 << CMD_HDR_PIR_OFF)
+#define SERDES_CFG                     (PORT_BASE + 0x1c)
 #define SL_CFG                         (PORT_BASE + 0x84)
 #define AIP_LIMIT                      (PORT_BASE + 0x90)
 #define SL_CONTROL                     (PORT_BASE + 0x94)
 #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF        22
 #define CHL_INT2                       (PORT_BASE + 0x1bc)
 #define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
+#define CHL_INT2_RX_DISP_ERR_OFF       28
+#define CHL_INT2_RX_CODE_ERR_OFF       29
 #define CHL_INT2_RX_INVLD_DW_OFF       30
 #define CHL_INT2_STP_LINK_TIMEOUT_OFF  31
 #define CHL_INT0_MSK                   (PORT_BASE + 0x1c0)
@@ -523,6 +526,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
                }
                hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
                        prog_phy_link_rate);
+               hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
                hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
                hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
                hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
@@ -544,6 +548,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
                hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
                hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01);
                hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG, 0x32);
+               hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME,
+                                    0x30f4240);
                /* used for 12G negotiate */
                hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
                hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff);
@@ -1344,7 +1350,8 @@ static void prep_abort_v3_hw(struct hisi_hba *hisi_hba,
 
 static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
-       int i, res;
+       int i;
+       irqreturn_t res;
        u32 context, port_id, link_rate;
        struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -1575,6 +1582,39 @@ static void handle_chl_int1_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
        hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT1, irq_value);
 }
 
+static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+       struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+       struct asd_sas_phy *sas_phy = &phy->sas_phy;
+       struct sas_phy *sphy = sas_phy->phy;
+       unsigned long flags;
+       u32 reg_value;
+
+       spin_lock_irqsave(&phy->lock, flags);
+
+       /* loss dword sync */
+       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
+       sphy->loss_of_dword_sync_count += reg_value;
+
+       /* phy reset problem */
+       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
+       sphy->phy_reset_problem_count += reg_value;
+
+       /* invalid dword */
+       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
+       sphy->invalid_dword_count += reg_value;
+
+       /* disparity err */
+       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
+       sphy->running_disparity_error_count += reg_value;
+
+       /* code violation error */
+       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_CODE_ERR);
+       phy->code_violation_err_count += reg_value;
+
+       spin_unlock_irqrestore(&phy->lock, flags);
+}
+
 static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
        u32 irq_msk = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2_MSK);
@@ -1582,6 +1622,9 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
        struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
        struct pci_dev *pci_dev = hisi_hba->pci_dev;
        struct device *dev = hisi_hba->dev;
+       static const u32 msk = BIT(CHL_INT2_RX_DISP_ERR_OFF) |
+                       BIT(CHL_INT2_RX_CODE_ERR_OFF) |
+                       BIT(CHL_INT2_RX_INVLD_DW_OFF);
 
        irq_value &= ~irq_msk;
        if (!irq_value)
@@ -1602,6 +1645,25 @@ static void handle_chl_int2_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
                        hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
        }
 
+       if (pci_dev->revision > 0x20 && (irq_value & msk)) {
+               struct asd_sas_phy *sas_phy = &phy->sas_phy;
+               struct sas_phy *sphy = sas_phy->phy;
+
+               phy_get_events_v3_hw(hisi_hba, phy_no);
+
+               if (irq_value & BIT(CHL_INT2_RX_INVLD_DW_OFF))
+                       dev_info(dev, "phy%d invalid dword cnt:   %u\n", phy_no,
+                                sphy->invalid_dword_count);
+
+               if (irq_value & BIT(CHL_INT2_RX_CODE_ERR_OFF))
+                       dev_info(dev, "phy%d code violation cnt:  %u\n", phy_no,
+                                phy->code_violation_err_count);
+
+               if (irq_value & BIT(CHL_INT2_RX_DISP_ERR_OFF))
+                       dev_info(dev, "phy%d disparity error cnt: %u\n", phy_no,
+                                sphy->running_disparity_error_count);
+       }
+
        if ((irq_value & BIT(CHL_INT2_RX_INVLD_DW_OFF)) &&
            (pci_dev->revision == 0x20)) {
                u32 reg_value;
@@ -2230,31 +2292,6 @@ static u32 get_phys_state_v3_hw(struct hisi_hba *hisi_hba)
        return hisi_sas_read32(hisi_hba, PHY_STATE);
 }
 
-static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
-{
-       struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
-       struct asd_sas_phy *sas_phy = &phy->sas_phy;
-       struct sas_phy *sphy = sas_phy->phy;
-       u32 reg_value;
-
-       /* loss dword sync */
-       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
-       sphy->loss_of_dword_sync_count += reg_value;
-
-       /* phy reset problem */
-       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
-       sphy->phy_reset_problem_count += reg_value;
-
-       /* invalid dword */
-       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
-       sphy->invalid_dword_count += reg_value;
-
-       /* disparity err */
-       reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
-       sphy->running_disparity_error_count += reg_value;
-
-}
-
 static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
 {
        struct device *dev = hisi_hba->dev;