1414#include <linux/device.h>
1515#include <linux/errno.h>
1616#include <linux/gfp.h>
17+ #include <linux/interrupt.h>
18+ #include <linux/irq.h>
19+ #include <linux/irqdesc.h>
1720#include <linux/list.h>
1821#include <linux/lockdep.h>
1922#include <linux/mutex.h>
@@ -200,6 +203,35 @@ static u64 mpam_msc_read_idr(struct mpam_msc *msc)
200203 return (idr_high << 32 ) | idr_low ;
201204}
202205
206+ static void mpam_msc_clear_esr (struct mpam_msc * msc )
207+ {
208+ u64 esr_low = __mpam_read_reg (msc , MPAMF_ESR );
209+
210+ if (!esr_low )
211+ return ;
212+
213+ /*
214+ * Clearing the high/low bits of MPAMF_ESR can not be atomic.
215+ * Clear the top half first, so that the pending error bits in the
216+ * lower half prevent hardware from updating either half of the
217+ * register.
218+ */
219+ if (msc -> has_extd_esr )
220+ __mpam_write_reg (msc , MPAMF_ESR + 4 , 0 );
221+ __mpam_write_reg (msc , MPAMF_ESR , 0 );
222+ }
223+
224+ static u64 mpam_msc_read_esr (struct mpam_msc * msc )
225+ {
226+ u64 esr_high = 0 , esr_low ;
227+
228+ esr_low = __mpam_read_reg (msc , MPAMF_ESR );
229+ if (msc -> has_extd_esr )
230+ esr_high = __mpam_read_reg (msc , MPAMF_ESR + 4 );
231+
232+ return (esr_high << 32 ) | esr_low ;
233+ }
234+
203235static void __mpam_part_sel_raw (u32 partsel , struct mpam_msc * msc )
204236{
205237 lockdep_assert_held (& msc -> part_sel_lock );
@@ -729,6 +761,7 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)
729761 pmg_max = FIELD_GET (MPAMF_IDR_PMG_MAX , idr );
730762 msc -> partid_max = min (msc -> partid_max , partid_max );
731763 msc -> pmg_max = min (msc -> pmg_max , pmg_max );
764+ msc -> has_extd_esr = FIELD_GET (MPAMF_IDR_HAS_EXTD_ESR , idr );
732765
733766 mutex_lock (& mpam_list_lock );
734767 ris = mpam_get_or_create_ris (msc , ris_idx );
@@ -743,6 +776,9 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)
743776 mutex_unlock (& msc -> part_sel_lock );
744777 }
745778
779+ /* Clear any stale errors */
780+ mpam_msc_clear_esr (msc );
781+
746782 spin_lock (& partid_max_lock );
747783 mpam_partid_max = min (mpam_partid_max , msc -> partid_max );
748784 mpam_pmg_max = min (mpam_pmg_max , msc -> pmg_max );
@@ -866,6 +902,13 @@ static void mpam_reset_msc(struct mpam_msc *msc, bool online)
866902 }
867903}
868904
905+ static void _enable_percpu_irq (void * _irq )
906+ {
907+ int * irq = _irq ;
908+
909+ enable_percpu_irq (* irq , IRQ_TYPE_NONE );
910+ }
911+
869912static int mpam_cpu_online (unsigned int cpu )
870913{
871914 struct mpam_msc * msc ;
@@ -876,6 +919,9 @@ static int mpam_cpu_online(unsigned int cpu)
876919 if (!cpumask_test_cpu (cpu , & msc -> accessibility ))
877920 continue ;
878921
922+ if (msc -> reenable_error_ppi )
923+ _enable_percpu_irq (& msc -> reenable_error_ppi );
924+
879925 if (atomic_fetch_inc (& msc -> online_refs ) == 0 )
880926 mpam_reset_msc (msc , true);
881927 }
@@ -926,6 +972,9 @@ static int mpam_cpu_offline(unsigned int cpu)
926972 if (!cpumask_test_cpu (cpu , & msc -> accessibility ))
927973 continue ;
928974
975+ if (msc -> reenable_error_ppi )
976+ disable_percpu_irq (msc -> reenable_error_ppi );
977+
929978 if (atomic_dec_and_test (& msc -> online_refs ))
930979 mpam_reset_msc (msc , false);
931980 }
@@ -952,6 +1001,42 @@ static void mpam_register_cpuhp_callbacks(int (*online)(unsigned int online),
9521001 mutex_unlock (& mpam_cpuhp_state_lock );
9531002}
9541003
1004+ static int __setup_ppi (struct mpam_msc * msc )
1005+ {
1006+ int cpu ;
1007+
1008+ msc -> error_dev_id = alloc_percpu (struct mpam_msc * );
1009+ if (!msc -> error_dev_id )
1010+ return - ENOMEM ;
1011+
1012+ for_each_cpu (cpu , & msc -> accessibility )
1013+ * per_cpu_ptr (msc -> error_dev_id , cpu ) = msc ;
1014+
1015+ return 0 ;
1016+ }
1017+
1018+ static int mpam_msc_setup_error_irq (struct mpam_msc * msc )
1019+ {
1020+ int irq ;
1021+
1022+ irq = platform_get_irq_byname_optional (msc -> pdev , "error" );
1023+ if (irq <= 0 )
1024+ return 0 ;
1025+
1026+ /* Allocate and initialise the percpu device pointer for PPI */
1027+ if (irq_is_percpu (irq ))
1028+ return __setup_ppi (msc );
1029+
1030+ /* sanity check: shared interrupts can be routed anywhere? */
1031+ if (!cpumask_equal (& msc -> accessibility , cpu_possible_mask )) {
1032+ pr_err_once ("msc:%u is a private resource with a shared error interrupt" ,
1033+ msc -> id );
1034+ return - EINVAL ;
1035+ }
1036+
1037+ return 0 ;
1038+ }
1039+
9551040/*
9561041 * An MSC can control traffic from a set of CPUs, but may only be accessible
9571042 * from a (hopefully wider) set of CPUs. The common reason for this is power
@@ -1028,6 +1113,9 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev)
10281113 if (err )
10291114 return ERR_PTR (err );
10301115
1116+ err = devm_mutex_init (dev , & msc -> error_irq_lock );
1117+ if (err )
1118+ return ERR_PTR (err );
10311119 mpam_mon_sel_lock_init (msc );
10321120 msc -> id = pdev -> id ;
10331121 msc -> pdev = pdev ;
@@ -1040,6 +1128,10 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev)
10401128 return ERR_PTR (- EINVAL );
10411129 }
10421130
1131+ err = mpam_msc_setup_error_irq (msc );
1132+ if (err )
1133+ return ERR_PTR (err );
1134+
10431135 if (device_property_read_u32 (& pdev -> dev , "pcc-channel" , & tmp ))
10441136 msc -> iface = MPAM_IFACE_MMIO ;
10451137 else
@@ -1313,8 +1405,177 @@ static void mpam_enable_merge_features(struct list_head *all_classes_list)
13131405 }
13141406}
13151407
1408+ static char * mpam_errcode_names [16 ] = {
1409+ [MPAM_ERRCODE_NONE ] = "No error" ,
1410+ [MPAM_ERRCODE_PARTID_SEL_RANGE ] = "PARTID_SEL_Range" ,
1411+ [MPAM_ERRCODE_REQ_PARTID_RANGE ] = "Req_PARTID_Range" ,
1412+ [MPAM_ERRCODE_MSMONCFG_ID_RANGE ] = "MSMONCFG_ID_RANGE" ,
1413+ [MPAM_ERRCODE_REQ_PMG_RANGE ] = "Req_PMG_Range" ,
1414+ [MPAM_ERRCODE_MONITOR_RANGE ] = "Monitor_Range" ,
1415+ [MPAM_ERRCODE_INTPARTID_RANGE ] = "intPARTID_Range" ,
1416+ [MPAM_ERRCODE_UNEXPECTED_INTERNAL ] = "Unexpected_INTERNAL" ,
1417+ [MPAM_ERRCODE_UNDEFINED_RIS_PART_SEL ] = "Undefined_RIS_PART_SEL" ,
1418+ [MPAM_ERRCODE_RIS_NO_CONTROL ] = "RIS_No_Control" ,
1419+ [MPAM_ERRCODE_UNDEFINED_RIS_MON_SEL ] = "Undefined_RIS_MON_SEL" ,
1420+ [MPAM_ERRCODE_RIS_NO_MONITOR ] = "RIS_No_Monitor" ,
1421+ [12 ... 15 ] = "Reserved"
1422+ };
1423+
1424+ static int mpam_enable_msc_ecr (void * _msc )
1425+ {
1426+ struct mpam_msc * msc = _msc ;
1427+
1428+ __mpam_write_reg (msc , MPAMF_ECR , MPAMF_ECR_INTEN );
1429+
1430+ return 0 ;
1431+ }
1432+
1433+ /* This can run in mpam_disable(), and the interrupt handler on the same CPU */
1434+ static int mpam_disable_msc_ecr (void * _msc )
1435+ {
1436+ struct mpam_msc * msc = _msc ;
1437+
1438+ __mpam_write_reg (msc , MPAMF_ECR , 0 );
1439+
1440+ return 0 ;
1441+ }
1442+
1443+ static irqreturn_t __mpam_irq_handler (int irq , struct mpam_msc * msc )
1444+ {
1445+ u64 reg ;
1446+ u16 partid ;
1447+ u8 errcode , pmg , ris ;
1448+
1449+ if (WARN_ON_ONCE (!msc ) ||
1450+ WARN_ON_ONCE (!cpumask_test_cpu (smp_processor_id (),
1451+ & msc -> accessibility )))
1452+ return IRQ_NONE ;
1453+
1454+ reg = mpam_msc_read_esr (msc );
1455+
1456+ errcode = FIELD_GET (MPAMF_ESR_ERRCODE , reg );
1457+ if (!errcode )
1458+ return IRQ_NONE ;
1459+
1460+ /* Clear level triggered irq */
1461+ mpam_msc_clear_esr (msc );
1462+
1463+ partid = FIELD_GET (MPAMF_ESR_PARTID_MON , reg );
1464+ pmg = FIELD_GET (MPAMF_ESR_PMG , reg );
1465+ ris = FIELD_GET (MPAMF_ESR_RIS , reg );
1466+
1467+ pr_err_ratelimited ("error irq from msc:%u '%s', partid:%u, pmg: %u, ris: %u\n" ,
1468+ msc -> id , mpam_errcode_names [errcode ], partid , pmg ,
1469+ ris );
1470+
1471+ /* Disable this interrupt. */
1472+ mpam_disable_msc_ecr (msc );
1473+
1474+ /*
1475+ * Schedule the teardown work. Don't use a threaded IRQ as we can't
1476+ * unregister the interrupt from the threaded part of the handler.
1477+ */
1478+ mpam_disable_reason = "hardware error interrupt" ;
1479+ schedule_work (& mpam_broken_work );
1480+
1481+ return IRQ_HANDLED ;
1482+ }
1483+
1484+ static irqreturn_t mpam_ppi_handler (int irq , void * dev_id )
1485+ {
1486+ struct mpam_msc * msc = * (struct mpam_msc * * )dev_id ;
1487+
1488+ return __mpam_irq_handler (irq , msc );
1489+ }
1490+
1491+ static irqreturn_t mpam_spi_handler (int irq , void * dev_id )
1492+ {
1493+ struct mpam_msc * msc = dev_id ;
1494+
1495+ return __mpam_irq_handler (irq , msc );
1496+ }
1497+
1498+ static int mpam_register_irqs (void )
1499+ {
1500+ int err , irq ;
1501+ struct mpam_msc * msc ;
1502+
1503+ lockdep_assert_cpus_held ();
1504+
1505+ guard (srcu )(& mpam_srcu );
1506+ list_for_each_entry_srcu (msc , & mpam_all_msc , all_msc_list ,
1507+ srcu_read_lock_held (& mpam_srcu )) {
1508+ irq = platform_get_irq_byname_optional (msc -> pdev , "error" );
1509+ if (irq <= 0 )
1510+ continue ;
1511+
1512+ /* The MPAM spec says the interrupt can be SPI, PPI or LPI */
1513+ /* We anticipate sharing the interrupt with other MSCs */
1514+ if (irq_is_percpu (irq )) {
1515+ err = request_percpu_irq (irq , & mpam_ppi_handler ,
1516+ "mpam:msc:error" ,
1517+ msc -> error_dev_id );
1518+ if (err )
1519+ return err ;
1520+
1521+ msc -> reenable_error_ppi = irq ;
1522+ smp_call_function_many (& msc -> accessibility ,
1523+ & _enable_percpu_irq , & irq ,
1524+ true);
1525+ } else {
1526+ err = devm_request_irq (& msc -> pdev -> dev , irq ,
1527+ & mpam_spi_handler , IRQF_SHARED ,
1528+ "mpam:msc:error" , msc );
1529+ if (err )
1530+ return err ;
1531+ }
1532+
1533+ mutex_lock (& msc -> error_irq_lock );
1534+ msc -> error_irq_req = true;
1535+ mpam_touch_msc (msc , mpam_enable_msc_ecr , msc );
1536+ msc -> error_irq_hw_enabled = true;
1537+ mutex_unlock (& msc -> error_irq_lock );
1538+ }
1539+
1540+ return 0 ;
1541+ }
1542+
1543+ static void mpam_unregister_irqs (void )
1544+ {
1545+ int irq ;
1546+ struct mpam_msc * msc ;
1547+
1548+ guard (cpus_read_lock )();
1549+ guard (srcu )(& mpam_srcu );
1550+ list_for_each_entry_srcu (msc , & mpam_all_msc , all_msc_list ,
1551+ srcu_read_lock_held (& mpam_srcu )) {
1552+ irq = platform_get_irq_byname_optional (msc -> pdev , "error" );
1553+ if (irq <= 0 )
1554+ continue ;
1555+
1556+ mutex_lock (& msc -> error_irq_lock );
1557+ if (msc -> error_irq_hw_enabled ) {
1558+ mpam_touch_msc (msc , mpam_disable_msc_ecr , msc );
1559+ msc -> error_irq_hw_enabled = false;
1560+ }
1561+
1562+ if (msc -> error_irq_req ) {
1563+ if (irq_is_percpu (irq )) {
1564+ msc -> reenable_error_ppi = 0 ;
1565+ free_percpu_irq (irq , msc -> error_dev_id );
1566+ } else {
1567+ devm_free_irq (& msc -> pdev -> dev , irq , msc );
1568+ }
1569+ msc -> error_irq_req = false;
1570+ }
1571+ mutex_unlock (& msc -> error_irq_lock );
1572+ }
1573+ }
1574+
13161575static void mpam_enable_once (void )
13171576{
1577+ int err ;
1578+
13181579 /*
13191580 * Once the cpuhp callbacks have been changed, mpam_partid_max can no
13201581 * longer change.
@@ -1323,9 +1584,26 @@ static void mpam_enable_once(void)
13231584 partid_max_published = true;
13241585 spin_unlock (& partid_max_lock );
13251586
1587+ /*
1588+ * If all the MSC have been probed, enabling the IRQs happens next.
1589+ * That involves cross-calling to a CPU that can reach the MSC, and
1590+ * the locks must be taken in this order:
1591+ */
1592+ cpus_read_lock ();
13261593 mutex_lock (& mpam_list_lock );
13271594 mpam_enable_merge_features (& mpam_classes );
1595+
1596+ err = mpam_register_irqs ();
1597+
13281598 mutex_unlock (& mpam_list_lock );
1599+ cpus_read_unlock ();
1600+
1601+ if (err ) {
1602+ pr_warn ("Failed to register irqs: %d\n" , err );
1603+ mpam_disable_reason = "Failed to enable." ;
1604+ schedule_work (& mpam_broken_work );
1605+ return ;
1606+ }
13291607
13301608 mpam_register_cpuhp_callbacks (mpam_cpu_online , mpam_cpu_offline ,
13311609 "mpam:online" );
@@ -1393,6 +1671,8 @@ void mpam_disable(struct work_struct *ignored)
13931671 }
13941672 mutex_unlock (& mpam_cpuhp_state_lock );
13951673
1674+ mpam_unregister_irqs ();
1675+
13961676 idx = srcu_read_lock (& mpam_srcu );
13971677 list_for_each_entry_srcu (class , & mpam_classes , classes_list ,
13981678 srcu_read_lock_held (& mpam_srcu ))
0 commit comments