@@ -1538,6 +1538,101 @@ static int ufs_qcom_get_outstanding_cqs(struct ufs_hba *hba,
15381538 return 0 ;
15391539}
15401540
1541+ #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
1542+ static void ufs_qcom_write_msi_msg (struct msi_desc * desc , struct msi_msg * msg )
1543+ {
1544+ struct device * dev = msi_desc_to_dev (desc );
1545+ struct ufs_hba * hba = dev_get_drvdata (dev );
1546+
1547+ ufshcd_mcq_config_esi (hba , msg );
1548+ }
1549+
1550+ static irqreturn_t ufs_qcom_mcq_esi_handler (int irq , void * __hba )
1551+ {
1552+ struct ufs_hba * hba = __hba ;
1553+ struct ufs_qcom_host * host = ufshcd_get_variant (hba );
1554+ u32 id = irq - host -> esi_base ;
1555+ struct ufs_hw_queue * hwq = & hba -> uhq [id ];
1556+
1557+ ufshcd_mcq_write_cqis (hba , 0x1 , id );
1558+ ufshcd_mcq_poll_cqe_nolock (hba , hwq );
1559+
1560+ return IRQ_HANDLED ;
1561+ }
1562+
1563+ static int ufs_qcom_config_esi (struct ufs_hba * hba )
1564+ {
1565+ struct ufs_qcom_host * host = ufshcd_get_variant (hba );
1566+ struct msi_desc * desc ;
1567+ struct msi_desc * failed_desc = NULL ;
1568+ int nr_irqs , ret ;
1569+
1570+ if (host -> esi_enabled )
1571+ return 0 ;
1572+ else if (host -> esi_base < 0 )
1573+ return - EINVAL ;
1574+
1575+ /*
1576+ * 1. We only handle CQs as of now.
1577+ * 2. Poll queues do not need ESI.
1578+ */
1579+ nr_irqs = hba -> nr_hw_queues - hba -> nr_queues [HCTX_TYPE_POLL ];
1580+ ret = platform_msi_domain_alloc_irqs (hba -> dev , nr_irqs ,
1581+ ufs_qcom_write_msi_msg );
1582+ if (ret )
1583+ goto out ;
1584+
1585+ msi_for_each_desc (desc , hba -> dev , MSI_DESC_ALL ) {
1586+ if (!desc -> msi_index )
1587+ host -> esi_base = desc -> irq ;
1588+
1589+ ret = devm_request_irq (hba -> dev , desc -> irq ,
1590+ ufs_qcom_mcq_esi_handler ,
1591+ IRQF_SHARED , "qcom-mcq-esi" , hba );
1592+ if (ret ) {
1593+ dev_err (hba -> dev , "%s: Fail to request IRQ for %d, err = %d\n" ,
1594+ __func__ , desc -> irq , ret );
1595+ failed_desc = desc ;
1596+ break ;
1597+ }
1598+ }
1599+
1600+ if (ret ) {
1601+ /* Rewind */
1602+ msi_for_each_desc (desc , hba -> dev , MSI_DESC_ALL ) {
1603+ if (desc == failed_desc )
1604+ break ;
1605+ devm_free_irq (hba -> dev , desc -> irq , hba );
1606+ }
1607+ platform_msi_domain_free_irqs (hba -> dev );
1608+ } else {
1609+ if (host -> hw_ver .major == 6 && host -> hw_ver .minor == 0 &&
1610+ host -> hw_ver .step == 0 ) {
1611+ ufshcd_writel (hba ,
1612+ ufshcd_readl (hba , REG_UFS_CFG3 ) | 0x1F000 ,
1613+ REG_UFS_CFG3 );
1614+ }
1615+ ufshcd_mcq_enable_esi (hba );
1616+ }
1617+
1618+ out :
1619+ if (ret ) {
1620+ host -> esi_base = -1 ;
1621+ dev_warn (hba -> dev , "Failed to request Platform MSI %d\n" , ret );
1622+ } else {
1623+ host -> esi_enabled = true;
1624+ }
1625+
1626+ return ret ;
1627+ }
1628+
1629+ #else
1630+ static int ufs_qcom_config_esi (struct ufs_hba * hba )
1631+ {
1632+ return - EOPNOTSUPP ;
1633+ }
1634+ #endif
1635+
15411636/*
15421637 * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
15431638 *
@@ -1566,6 +1661,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
15661661 .get_hba_mac = ufs_qcom_get_hba_mac ,
15671662 .op_runtime_config = ufs_qcom_op_runtime_config ,
15681663 .get_outstanding_cqs = ufs_qcom_get_outstanding_cqs ,
1664+ .config_esi = ufs_qcom_config_esi ,
15691665};
15701666
15711667/**
@@ -1599,6 +1695,7 @@ static int ufs_qcom_remove(struct platform_device *pdev)
15991695
16001696 pm_runtime_get_sync (& (pdev )-> dev );
16011697 ufshcd_remove (hba );
1698+ platform_msi_domain_free_irqs (hba -> dev );
16021699 return 0 ;
16031700}
16041701
0 commit comments