scsi: hisi_sas: remove init_id_frame_v2_hw()
[cascardo/linux.git] / drivers / scsi / hisi_sas / hisi_sas_v2_hw.c
index bd20c54..5925b93 100644 (file)
 /* HW dma structures */
 /* Delivery queue header */
 /* dw0 */
+#define CMD_HDR_ABORT_FLAG_OFF         0
+#define CMD_HDR_ABORT_FLAG_MSK         (0x3 << CMD_HDR_ABORT_FLAG_OFF)
+#define CMD_HDR_ABORT_DEVICE_TYPE_OFF  2
+#define CMD_HDR_ABORT_DEVICE_TYPE_MSK  (0x1 << CMD_HDR_ABORT_DEVICE_TYPE_OFF)
 #define CMD_HDR_RESP_REPORT_OFF                5
 #define CMD_HDR_RESP_REPORT_MSK                (0x1 << CMD_HDR_RESP_REPORT_OFF)
 #define CMD_HDR_TLR_CTRL_OFF           6
 #define CMD_HDR_DIF_SGL_LEN_MSK                (0xffff << CMD_HDR_DIF_SGL_LEN_OFF)
 #define CMD_HDR_DATA_SGL_LEN_OFF       16
 #define CMD_HDR_DATA_SGL_LEN_MSK       (0xffff << CMD_HDR_DATA_SGL_LEN_OFF)
+#define CMD_HDR_ABORT_IPTT_OFF         16
+#define CMD_HDR_ABORT_IPTT_MSK         (0xffff << CMD_HDR_ABORT_IPTT_OFF)
 
 /* Completion header */
 /* dw0 */
 #define CMPLT_HDR_RSPNS_XFRD_MSK       (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
 #define CMPLT_HDR_ERX_OFF              12
 #define CMPLT_HDR_ERX_MSK              (0x1 << CMPLT_HDR_ERX_OFF)
+#define CMPLT_HDR_ABORT_STAT_OFF       13
+#define CMPLT_HDR_ABORT_STAT_MSK       (0x7 << CMPLT_HDR_ABORT_STAT_OFF)
+/* abort_stat */
+#define STAT_IO_NOT_VALID              0x1
+#define STAT_IO_NO_DEVICE              0x2
+#define STAT_IO_COMPLETE               0x3
+#define STAT_IO_ABORTED                        0x4
 /* dw1 */
 #define CMPLT_HDR_IPTT_OFF             0
 #define CMPLT_HDR_IPTT_MSK             (0xffff << CMPLT_HDR_IPTT_OFF)
@@ -549,25 +562,17 @@ static void config_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
                        __swab32(identify_buffer[0]));
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
-                       identify_buffer[2]);
+                       __swab32(identify_buffer[1]));
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
-                       identify_buffer[1]);
+                       __swab32(identify_buffer[2]));
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
-                       identify_buffer[4]);
+                       __swab32(identify_buffer[3]));
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
-                       identify_buffer[3]);
+                       __swab32(identify_buffer[4]));
        hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
                        __swab32(identify_buffer[5]));
 }
 
-static void init_id_frame_v2_hw(struct hisi_hba *hisi_hba)
-{
-       int i;
-
-       for (i = 0; i < hisi_hba->n_phy; i++)
-               config_id_frame_v2_hw(hisi_hba, i);
-}
-
 static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
                             struct hisi_sas_device *sas_dev)
 {
@@ -672,9 +677,7 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
        else
                reset_val = 0x7ffff;
 
-       /* Disable all of the DQ */
-       for (i = 0; i < HISI_SAS_MAX_QUEUES; i++)
-               hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
+       hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
 
        /* Disable all of the PHYs */
        for (i = 0; i < hisi_hba->n_phy; i++) {
@@ -721,30 +724,41 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
                        return -EIO;
        }
 
-       /* reset and disable clock*/
-       regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
-                       reset_val);
-       regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
-                       reset_val);
-       msleep(1);
-       regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
-       if (reset_val != (val & reset_val)) {
-               dev_err(dev, "SAS reset fail.\n");
-               return -EIO;
-       }
+       if (ACPI_HANDLE(dev)) {
+               acpi_status s;
 
-       /* De-reset and enable clock*/
-       regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
-                       reset_val);
-       regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
-                       reset_val);
-       msleep(1);
-       regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
-                       &val);
-       if (val & reset_val) {
-               dev_err(dev, "SAS de-reset fail.\n");
-               return -EIO;
-       }
+               s = acpi_evaluate_object(ACPI_HANDLE(dev), "_RST", NULL, NULL);
+               if (ACPI_FAILURE(s)) {
+                       dev_err(dev, "Reset failed\n");
+                       return -EIO;
+               }
+       } else if (hisi_hba->ctrl) {
+               /* reset and disable clock*/
+               regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
+                               reset_val);
+               regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
+                               reset_val);
+               msleep(1);
+               regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
+               if (reset_val != (val & reset_val)) {
+                       dev_err(dev, "SAS reset fail.\n");
+                       return -EIO;
+               }
+
+               /* De-reset and enable clock*/
+               regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
+                               reset_val);
+               regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
+                               reset_val);
+               msleep(1);
+               regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
+                               &val);
+               if (val & reset_val) {
+                       dev_err(dev, "SAS de-reset fail.\n");
+                       return -EIO;
+               }
+       } else
+               dev_warn(dev, "no reset method\n");
 
        return 0;
 }
@@ -752,13 +766,12 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
 static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
 {
        struct device *dev = &hisi_hba->pdev->dev;
-       struct device_node *np = dev->of_node;
        int i;
 
        /* Global registers init */
 
        /* Deal with am-max-transmissions quirk */
-       if (of_get_property(np, "hip06-sas-v2-quirk-amt", NULL)) {
+       if (device_property_present(dev, "hip06-sas-v2-quirk-amt")) {
                hisi_sas_write32(hisi_hba, AM_CFG_MAX_TRANS, 0x2020);
                hisi_sas_write32(hisi_hba, AM_CFG_SINGLE_PORT_MAX_TRANS,
                                 0x2020);
@@ -891,8 +904,6 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
        msleep(100);
        init_reg_v2_hw(hisi_hba);
 
-       init_id_frame_v2_hw(hisi_hba);
-
        return 0;
 }
 
@@ -942,14 +953,8 @@ static void start_phys_v2_hw(unsigned long data)
 
 static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
 {
-       int i;
        struct timer_list *timer = &hisi_hba->timer;
 
-       for (i = 0; i < hisi_hba->n_phy; i++) {
-               hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x6a);
-               hisi_sas_phy_read32(hisi_hba, i, CHL_INT2_MSK);
-       }
-
        setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
        mod_timer(timer, jiffies + HZ);
 }
@@ -1000,12 +1005,13 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
 static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s)
 {
        struct device *dev = &hisi_hba->pdev->dev;
+       struct hisi_sas_dq *dq;
        u32 r, w;
        int queue = hisi_hba->queue;
 
        while (1) {
-               w = hisi_sas_read32_relaxed(hisi_hba,
-                                           DLVRY_Q_0_WR_PTR + (queue * 0x14));
+               dq = &hisi_hba->dq[queue];
+               w = dq->wr_point;
                r = hisi_sas_read32_relaxed(hisi_hba,
                                            DLVRY_Q_0_RD_PTR + (queue * 0x14));
                if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
@@ -1028,9 +1034,11 @@ static void start_delivery_v2_hw(struct hisi_hba *hisi_hba)
 {
        int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
        int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
+       struct hisi_sas_dq *dq = &hisi_hba->dq[dlvry_queue];
 
+       dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
        hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
-                        ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
+                        dq->wr_point);
 }
 
 static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
@@ -1553,6 +1561,30 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
                goto out;
        }
 
+       /* Use SAS+TMF status codes */
+       switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK)
+                       >> CMPLT_HDR_ABORT_STAT_OFF) {
+       case STAT_IO_ABORTED:
+               /* this io has been aborted by abort command */
+               ts->stat = SAS_ABORTED_TASK;
+               goto out;
+       case STAT_IO_COMPLETE:
+               /* internal abort command complete */
+               ts->stat = TMF_RESP_FUNC_COMPLETE;
+               goto out;
+       case STAT_IO_NO_DEVICE:
+               ts->stat = TMF_RESP_FUNC_COMPLETE;
+               goto out;
+       case STAT_IO_NOT_VALID:
+               /* abort single io, controller don't find
+                * the io need to abort
+                */
+               ts->stat = TMF_RESP_FUNC_FAILED;
+               goto out;
+       default:
+               break;
+       }
+
        if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) &&
                (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
 
@@ -1765,6 +1797,32 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
        return 0;
 }
 
+static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
+               struct hisi_sas_slot *slot,
+               int device_id, int abort_flag, int tag_to_abort)
+{
+       struct sas_task *task = slot->task;
+       struct domain_device *dev = task->dev;
+       struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+       struct hisi_sas_port *port = slot->port;
+
+       /* dw0 */
+       hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
+                              (port->id << CMD_HDR_PORT_OFF) |
+                              ((dev_is_sata(dev) ? 1:0) <<
+                               CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
+                              (abort_flag << CMD_HDR_ABORT_FLAG_OFF));
+
+       /* dw1 */
+       hdr->dw1 = cpu_to_le32(device_id << CMD_HDR_DEV_ID_OFF);
+
+       /* dw7 */
+       hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
+       hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+       return 0;
+}
+
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
        int i, res = 0;
@@ -1808,9 +1866,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
                frame_rcvd[i] = __swab32(idaf);
        }
 
-       /* Get the linkrates */
-       link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
-       link_rate = (link_rate >> (phy_no * 4)) & 0xf;
        sas_phy->linkrate = link_rate;
        hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
                                                HARD_PHY_LINKRATE);
@@ -1902,14 +1957,9 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
        struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
        struct sas_ha_struct *sas_ha = &hisi_hba->sha;
-       unsigned long flags;
 
        hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
-
-       spin_lock_irqsave(&hisi_hba->lock, flags);
        sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
-       spin_unlock_irqrestore(&hisi_hba->lock, flags);
-
        hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
                             CHL_INT0_SL_RX_BCST_ACK_MSK);
        hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
@@ -1981,7 +2031,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
        struct hisi_sas_slot *slot;
        struct hisi_sas_itct *itct;
        struct hisi_sas_complete_v2_hdr *complete_queue;
-       u32 irq_value, rd_point, wr_point, dev_id;
+       u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id;
        int queue = cq->id;
 
        complete_queue = hisi_hba->complete_hdr[queue];
@@ -1989,8 +2039,6 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
 
        hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
 
-       rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR +
-                                  (0x14 * queue));
        wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
                                   (0x14 * queue));
 
@@ -2038,6 +2086,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
        }
 
        /* update rd_point */
+       cq->rd_point = rd_point;
        hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
        return IRQ_HANDLED;
 }
@@ -2234,6 +2283,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
        .prep_smp = prep_smp_v2_hw,
        .prep_ssp = prep_ssp_v2_hw,
        .prep_stp = prep_ata_v2_hw,
+       .prep_abort = prep_abort_v2_hw,
        .get_free_slot = get_free_slot_v2_hw,
        .start_delivery = start_delivery_v2_hw,
        .slot_complete = slot_complete_v2_hw,
@@ -2260,12 +2310,20 @@ static const struct of_device_id sas_v2_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sas_v2_of_match);
 
+static const struct acpi_device_id sas_v2_acpi_match[] = {
+       { "HISI0162", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match);
+
 static struct platform_driver hisi_sas_v2_driver = {
        .probe = hisi_sas_v2_probe,
        .remove = hisi_sas_v2_remove,
        .driver = {
                .name = DRV_NAME,
                .of_match_table = sas_v2_of_match,
+               .acpi_match_table = ACPI_PTR(sas_v2_acpi_match),
        },
 };