127
127
128
128
static const struct res_config {
129
129
bool machine_check ;
130
+ /* The number of present memory controllers. */
130
131
int num_imc ;
131
132
u32 imc_base ;
132
133
u32 cmf_base ;
@@ -1201,23 +1202,21 @@ static void igen6_check(struct mem_ctl_info *mci)
1201
1202
irq_work_queue (& ecclog_irq_work );
1202
1203
}
1203
1204
1204
- static int igen6_register_mci (int mc , u64 mchbar , struct pci_dev * pdev )
1205
+ /* Check whether the memory controller is absent. */
1206
+ static bool igen6_imc_absent (void __iomem * window )
1207
+ {
1208
+ return readl (window + MAD_INTER_CHANNEL_OFFSET ) == ~0 ;
1209
+ }
1210
+
1211
+ static int igen6_register_mci (int mc , void __iomem * window , struct pci_dev * pdev )
1205
1212
{
1206
1213
struct edac_mc_layer layers [2 ];
1207
1214
struct mem_ctl_info * mci ;
1208
1215
struct igen6_imc * imc ;
1209
- void __iomem * window ;
1210
1216
int rc ;
1211
1217
1212
1218
edac_dbg (2 , "\n" );
1213
1219
1214
- mchbar += mc * MCHBAR_SIZE ;
1215
- window = ioremap (mchbar , MCHBAR_SIZE );
1216
- if (!window ) {
1217
- igen6_printk (KERN_ERR , "Failed to ioremap 0x%llx\n" , mchbar );
1218
- return - ENODEV ;
1219
- }
1220
-
1221
1220
layers [0 ].type = EDAC_MC_LAYER_CHANNEL ;
1222
1221
layers [0 ].size = NUM_CHANNELS ;
1223
1222
layers [0 ].is_virt_csrow = false;
@@ -1283,7 +1282,6 @@ static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev)
1283
1282
fail2 :
1284
1283
edac_mc_free (mci );
1285
1284
fail :
1286
- iounmap (window );
1287
1285
return rc ;
1288
1286
}
1289
1287
@@ -1309,6 +1307,56 @@ static void igen6_unregister_mcis(void)
1309
1307
}
1310
1308
}
1311
1309
1310
+ static int igen6_register_mcis (struct pci_dev * pdev , u64 mchbar )
1311
+ {
1312
+ void __iomem * window ;
1313
+ int lmc , pmc , rc ;
1314
+ u64 base ;
1315
+
1316
+ for (lmc = 0 , pmc = 0 ; pmc < NUM_IMC ; pmc ++ ) {
1317
+ base = mchbar + pmc * MCHBAR_SIZE ;
1318
+ window = ioremap (base , MCHBAR_SIZE );
1319
+ if (!window ) {
1320
+ igen6_printk (KERN_ERR , "Failed to ioremap 0x%llx for mc%d\n" , base , pmc );
1321
+ rc = - ENOMEM ;
1322
+ goto out_unregister_mcis ;
1323
+ }
1324
+
1325
+ if (igen6_imc_absent (window )) {
1326
+ iounmap (window );
1327
+ edac_dbg (2 , "Skip absent mc%d\n" , pmc );
1328
+ continue ;
1329
+ }
1330
+
1331
+ rc = igen6_register_mci (lmc , window , pdev );
1332
+ if (rc )
1333
+ goto out_iounmap ;
1334
+
1335
+ /* Done, if all present MCs are detected and registered. */
1336
+ if (++ lmc >= res_cfg -> num_imc )
1337
+ break ;
1338
+ }
1339
+
1340
+ if (!lmc ) {
1341
+ igen6_printk (KERN_ERR , "No mc found.\n" );
1342
+ return - ENODEV ;
1343
+ }
1344
+
1345
+ if (lmc < res_cfg -> num_imc )
1346
+ igen6_printk (KERN_WARNING , "Expected %d mcs, but only %d detected." ,
1347
+ res_cfg -> num_imc , lmc );
1348
+
1349
+ return 0 ;
1350
+
1351
+ out_iounmap :
1352
+ iounmap (window );
1353
+
1354
+ out_unregister_mcis :
1355
+ igen6_unregister_mcis ();
1356
+
1357
+ return rc ;
1358
+ }
1359
+
1312
1360
static int igen6_mem_slice_setup (u64 mchbar )
1313
1361
{
1314
1362
struct igen6_imc * imc = & igen6_pvt -> imc [0 ];
@@ -1405,7 +1453,7 @@ static void opstate_set(const struct res_config *cfg, const struct pci_device_id
1405
1453
static int igen6_probe (struct pci_dev * pdev , const struct pci_device_id * ent )
1406
1454
{
1407
1455
u64 mchbar ;
1408
- int i , rc ;
1456
+ int rc ;
1409
1457
1410
1458
edac_dbg (2 , "\n" );
1411
1459
@@ -1421,11 +1469,9 @@ static int igen6_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1421
1469
1422
1470
opstate_set (res_cfg , ent );
1423
1471
1424
- for (i = 0 ; i < res_cfg -> num_imc ; i ++ ) {
1425
- rc = igen6_register_mci (i , mchbar , pdev );
1426
- if (rc )
1427
- goto fail2 ;
1428
- }
1472
+ rc = igen6_register_mcis (pdev , mchbar );
1473
+ if (rc )
1474
+ goto fail ;
1429
1475
1430
1476
if (res_cfg -> num_imc > 1 ) {
1431
1477
rc = igen6_mem_slice_setup (mchbar );
0 commit comments