.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module |
---|
2 | 3 | * |
---|
3 | 4 | * This driver supports the memory controllers found on the Intel |
---|
4 | 5 | * processor family Sandy Bridge. |
---|
5 | | - * |
---|
6 | | - * This file may be distributed under the terms of the |
---|
7 | | - * GNU General Public License version 2 only. |
---|
8 | 6 | * |
---|
9 | 7 | * Copyright (c) 2011 by: |
---|
10 | 8 | * Mauro Carvalho Chehab |
---|
.. | .. |
---|
256 | 254 | * FIXME: Implement the error count reads directly |
---|
257 | 255 | */ |
---|
258 | 256 | |
---|
259 | | -static const u32 correrrcnt[] = { |
---|
260 | | - 0x104, 0x108, 0x10c, 0x110, |
---|
261 | | -}; |
---|
262 | | - |
---|
263 | 257 | #define RANK_ODD_OV(reg) GET_BITFIELD(reg, 31, 31) |
---|
264 | 258 | #define RANK_ODD_ERR_CNT(reg) GET_BITFIELD(reg, 16, 30) |
---|
265 | 259 | #define RANK_EVEN_OV(reg) GET_BITFIELD(reg, 15, 15) |
---|
266 | 260 | #define RANK_EVEN_ERR_CNT(reg) GET_BITFIELD(reg, 0, 14) |
---|
267 | 261 | |
---|
| 262 | +#if 0 /* Currently unused*/ |
---|
| 263 | +static const u32 correrrcnt[] = { |
---|
| 264 | + 0x104, 0x108, 0x10c, 0x110, |
---|
| 265 | +}; |
---|
| 266 | + |
---|
268 | 267 | static const u32 correrrthrsld[] = { |
---|
269 | 268 | 0x11c, 0x120, 0x124, 0x128, |
---|
270 | 269 | }; |
---|
| 270 | +#endif |
---|
271 | 271 | |
---|
272 | 272 | #define RANK_ODD_ERR_THRSLD(reg) GET_BITFIELD(reg, 16, 30) |
---|
273 | 273 | #define RANK_EVEN_ERR_THRSLD(reg) GET_BITFIELD(reg, 0, 14) |
---|
.. | .. |
---|
326 | 326 | const struct interleave_pkg *interleave_pkg; |
---|
327 | 327 | u8 max_sad; |
---|
328 | 328 | u8 (*get_node_id)(struct sbridge_pvt *pvt); |
---|
| 329 | + u8 (*get_ha)(u8 bank); |
---|
329 | 330 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); |
---|
330 | 331 | enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr); |
---|
331 | 332 | struct pci_dev *pci_vtd; |
---|
.. | .. |
---|
938 | 939 | |
---|
939 | 940 | static enum dev_type __ibridge_get_width(u32 mtr) |
---|
940 | 941 | { |
---|
941 | | - enum dev_type type; |
---|
| 942 | + enum dev_type type = DEV_UNKNOWN; |
---|
942 | 943 | |
---|
943 | 944 | switch (mtr) { |
---|
944 | | - case 3: |
---|
945 | | - type = DEV_UNKNOWN; |
---|
946 | | - break; |
---|
947 | 945 | case 2: |
---|
948 | 946 | type = DEV_X16; |
---|
949 | 947 | break; |
---|
.. | .. |
---|
1002 | 1000 | return GET_BITFIELD(reg, 0, 2); |
---|
1003 | 1001 | } |
---|
1004 | 1002 | |
---|
| 1003 | +/* |
---|
| 1004 | + * Use the reporting bank number to determine which memory |
---|
| 1005 | + * controller (also known as "ha" for "home agent"). Sandy |
---|
| 1006 | + * Bridge only has one memory controller per socket, so the |
---|
| 1007 | + * answer is always zero. |
---|
| 1008 | + */ |
---|
| 1009 | +static u8 sbridge_get_ha(u8 bank) |
---|
| 1010 | +{ |
---|
| 1011 | + return 0; |
---|
| 1012 | +} |
---|
| 1013 | + |
---|
| 1014 | +/* |
---|
| 1015 | + * On Ivy Bridge, Haswell and Broadwell the error may be in a |
---|
| 1016 | + * home agent bank (7, 8), or one of the per-channel memory |
---|
| 1017 | + * controller banks (9 .. 16). |
---|
| 1018 | + */ |
---|
| 1019 | +static u8 ibridge_get_ha(u8 bank) |
---|
| 1020 | +{ |
---|
| 1021 | + switch (bank) { |
---|
| 1022 | + case 7 ... 8: |
---|
| 1023 | + return bank - 7; |
---|
| 1024 | + case 9 ... 16: |
---|
| 1025 | + return (bank - 9) / 4; |
---|
| 1026 | + default: |
---|
| 1027 | + return 0xff; |
---|
| 1028 | + } |
---|
| 1029 | +} |
---|
| 1030 | + |
---|
| 1031 | +/* Not used, but included for safety/symmetry */ |
---|
| 1032 | +static u8 knl_get_ha(u8 bank) |
---|
| 1033 | +{ |
---|
| 1034 | + return 0xff; |
---|
| 1035 | +} |
---|
1005 | 1036 | |
---|
1006 | 1037 | static u64 haswell_get_tolm(struct sbridge_pvt *pvt) |
---|
1007 | 1038 | { |
---|
.. | .. |
---|
1308 | 1339 | */ |
---|
1309 | 1340 | static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) |
---|
1310 | 1341 | { |
---|
1311 | | - u64 sad_base, sad_size, sad_limit = 0; |
---|
| 1342 | + u64 sad_base, sad_limit = 0; |
---|
1312 | 1343 | u64 tad_base, tad_size, tad_limit, tad_deadspace, tad_livespace; |
---|
1313 | 1344 | int sad_rule = 0; |
---|
1314 | 1345 | int tad_rule = 0; |
---|
.. | .. |
---|
1395 | 1426 | edram_only = KNL_EDRAM_ONLY(dram_rule); |
---|
1396 | 1427 | |
---|
1397 | 1428 | sad_limit = pvt->info.sad_limit(dram_rule)+1; |
---|
1398 | | - sad_size = sad_limit - sad_base; |
---|
1399 | 1429 | |
---|
1400 | 1430 | pci_read_config_dword(pvt->pci_sad0, |
---|
1401 | 1431 | pvt->info.interleave_list[sad_rule], &interleave_reg); |
---|
.. | .. |
---|
1479 | 1509 | sad_actual_size[mc] += tad_size; |
---|
1480 | 1510 | } |
---|
1481 | 1511 | } |
---|
1482 | | - tad_base = tad_limit+1; |
---|
1483 | 1512 | } |
---|
1484 | 1513 | } |
---|
1485 | 1514 | |
---|
.. | .. |
---|
1589 | 1618 | } |
---|
1590 | 1619 | |
---|
1591 | 1620 | for (j = 0; j < max_dimms_per_channel; j++) { |
---|
1592 | | - dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, i, j, 0); |
---|
| 1621 | + dimm = edac_get_dimm(mci, i, j, 0); |
---|
1593 | 1622 | if (pvt->info.type == KNIGHTS_LANDING) { |
---|
1594 | 1623 | pci_read_config_dword(pvt->knl.pci_channel[i], |
---|
1595 | 1624 | knl_mtr_reg, &mtr); |
---|
.. | .. |
---|
2203 | 2232 | limit, |
---|
2204 | 2233 | rir_way, |
---|
2205 | 2234 | idx); |
---|
| 2235 | + |
---|
| 2236 | + return 0; |
---|
| 2237 | +} |
---|
| 2238 | + |
---|
| 2239 | +static int get_memory_error_data_from_mce(struct mem_ctl_info *mci, |
---|
| 2240 | + const struct mce *m, u8 *socket, |
---|
| 2241 | + u8 *ha, long *channel_mask, |
---|
| 2242 | + char *msg) |
---|
| 2243 | +{ |
---|
| 2244 | + u32 reg, channel = GET_BITFIELD(m->status, 0, 3); |
---|
| 2245 | + struct mem_ctl_info *new_mci; |
---|
| 2246 | + struct sbridge_pvt *pvt; |
---|
| 2247 | + struct pci_dev *pci_ha; |
---|
| 2248 | + bool tad0; |
---|
| 2249 | + |
---|
| 2250 | + if (channel >= NUM_CHANNELS) { |
---|
| 2251 | + sprintf(msg, "Invalid channel 0x%x", channel); |
---|
| 2252 | + return -EINVAL; |
---|
| 2253 | + } |
---|
| 2254 | + |
---|
| 2255 | + pvt = mci->pvt_info; |
---|
| 2256 | + if (!pvt->info.get_ha) { |
---|
| 2257 | + sprintf(msg, "No get_ha()"); |
---|
| 2258 | + return -EINVAL; |
---|
| 2259 | + } |
---|
| 2260 | + *ha = pvt->info.get_ha(m->bank); |
---|
| 2261 | + if (*ha != 0 && *ha != 1) { |
---|
| 2262 | + sprintf(msg, "Impossible bank %d", m->bank); |
---|
| 2263 | + return -EINVAL; |
---|
| 2264 | + } |
---|
| 2265 | + |
---|
| 2266 | + *socket = m->socketid; |
---|
| 2267 | + new_mci = get_mci_for_node_id(*socket, *ha); |
---|
| 2268 | + if (!new_mci) { |
---|
| 2269 | + strcpy(msg, "mci socket got corrupted!"); |
---|
| 2270 | + return -EINVAL; |
---|
| 2271 | + } |
---|
| 2272 | + |
---|
| 2273 | + pvt = new_mci->pvt_info; |
---|
| 2274 | + pci_ha = pvt->pci_ha; |
---|
| 2275 | + pci_read_config_dword(pci_ha, tad_dram_rule[0], ®); |
---|
| 2276 | + tad0 = m->addr <= TAD_LIMIT(reg); |
---|
| 2277 | + |
---|
| 2278 | + *channel_mask = 1 << channel; |
---|
| 2279 | + if (pvt->mirror_mode == FULL_MIRRORING || |
---|
| 2280 | + (pvt->mirror_mode == ADDR_RANGE_MIRRORING && tad0)) { |
---|
| 2281 | + *channel_mask |= 1 << ((channel + 2) % 4); |
---|
| 2282 | + pvt->is_cur_addr_mirrored = true; |
---|
| 2283 | + } else { |
---|
| 2284 | + pvt->is_cur_addr_mirrored = false; |
---|
| 2285 | + } |
---|
| 2286 | + |
---|
| 2287 | + if (pvt->is_lockstep) |
---|
| 2288 | + *channel_mask |= 1 << ((channel + 1) % 4); |
---|
2206 | 2289 | |
---|
2207 | 2290 | return 0; |
---|
2208 | 2291 | } |
---|
.. | .. |
---|
2867 | 2950 | struct mem_ctl_info *new_mci; |
---|
2868 | 2951 | struct sbridge_pvt *pvt = mci->pvt_info; |
---|
2869 | 2952 | enum hw_event_mc_err_type tp_event; |
---|
2870 | | - char *type, *optype, msg[256]; |
---|
| 2953 | + char *optype, msg[256]; |
---|
2871 | 2954 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); |
---|
2872 | 2955 | bool overflow = GET_BITFIELD(m->status, 62, 62); |
---|
2873 | 2956 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); |
---|
.. | .. |
---|
2877 | 2960 | u32 errcode = GET_BITFIELD(m->status, 0, 15); |
---|
2878 | 2961 | u32 channel = GET_BITFIELD(m->status, 0, 3); |
---|
2879 | 2962 | u32 optypenum = GET_BITFIELD(m->status, 4, 6); |
---|
| 2963 | + /* |
---|
| 2964 | + * Bits 5-0 of MCi_MISC give the least significant bit that is valid. |
---|
| 2965 | + * A value 6 is for cache line aligned address, a value 12 is for page |
---|
| 2966 | + * aligned address reported by patrol scrubber. |
---|
| 2967 | + */ |
---|
| 2968 | + u32 lsb = GET_BITFIELD(m->misc, 0, 5); |
---|
2880 | 2969 | long channel_mask, first_channel; |
---|
2881 | | - u8 rank, socket, ha; |
---|
| 2970 | + u8 rank = 0xff, socket, ha; |
---|
2882 | 2971 | int rc, dimm; |
---|
2883 | | - char *area_type = NULL; |
---|
| 2972 | + char *area_type = "DRAM"; |
---|
2884 | 2973 | |
---|
2885 | 2974 | if (pvt->info.type != SANDY_BRIDGE) |
---|
2886 | 2975 | recoverable = true; |
---|
.. | .. |
---|
2890 | 2979 | if (uncorrected_error) { |
---|
2891 | 2980 | core_err_cnt = 1; |
---|
2892 | 2981 | if (ripv) { |
---|
2893 | | - type = "FATAL"; |
---|
2894 | | - tp_event = HW_EVENT_ERR_FATAL; |
---|
2895 | | - } else { |
---|
2896 | | - type = "NON_FATAL"; |
---|
2897 | 2982 | tp_event = HW_EVENT_ERR_UNCORRECTED; |
---|
| 2983 | + } else { |
---|
| 2984 | + tp_event = HW_EVENT_ERR_FATAL; |
---|
2898 | 2985 | } |
---|
2899 | 2986 | } else { |
---|
2900 | | - type = "CORRECTED"; |
---|
2901 | 2987 | tp_event = HW_EVENT_ERR_CORRECTED; |
---|
2902 | 2988 | } |
---|
2903 | 2989 | |
---|
.. | .. |
---|
2965 | 3051 | optype, msg); |
---|
2966 | 3052 | } |
---|
2967 | 3053 | return; |
---|
2968 | | - } else { |
---|
| 3054 | + } else if (lsb < 12) { |
---|
2969 | 3055 | rc = get_memory_error_data(mci, m->addr, &socket, &ha, |
---|
2970 | | - &channel_mask, &rank, &area_type, msg); |
---|
| 3056 | + &channel_mask, &rank, |
---|
| 3057 | + &area_type, msg); |
---|
| 3058 | + } else { |
---|
| 3059 | + rc = get_memory_error_data_from_mce(mci, m, &socket, &ha, |
---|
| 3060 | + &channel_mask, msg); |
---|
2971 | 3061 | } |
---|
2972 | 3062 | |
---|
2973 | 3063 | if (rc < 0) |
---|
.. | .. |
---|
2982 | 3072 | |
---|
2983 | 3073 | first_channel = find_first_bit(&channel_mask, NUM_CHANNELS); |
---|
2984 | 3074 | |
---|
2985 | | - if (rank < 4) |
---|
| 3075 | + if (rank == 0xff) |
---|
| 3076 | + dimm = -1; |
---|
| 3077 | + else if (rank < 4) |
---|
2986 | 3078 | dimm = 0; |
---|
2987 | 3079 | else if (rank < 8) |
---|
2988 | 3080 | dimm = 1; |
---|
2989 | 3081 | else |
---|
2990 | 3082 | dimm = 2; |
---|
2991 | | - |
---|
2992 | 3083 | |
---|
2993 | 3084 | /* |
---|
2994 | 3085 | * FIXME: On some memory configurations (mirror, lockstep), the |
---|
.. | .. |
---|
3040 | 3131 | struct mem_ctl_info *mci; |
---|
3041 | 3132 | char *type; |
---|
3042 | 3133 | |
---|
3043 | | - if (edac_get_report_status() == EDAC_REPORTING_DISABLED) |
---|
| 3134 | + if (mce->kflags & MCE_HANDLED_CEC) |
---|
3044 | 3135 | return NOTIFY_DONE; |
---|
3045 | 3136 | |
---|
3046 | 3137 | /* |
---|
.. | .. |
---|
3089 | 3180 | sbridge_mce_output_error(mci, mce); |
---|
3090 | 3181 | |
---|
3091 | 3182 | /* Advice mcelog that the error were handled */ |
---|
3092 | | - return NOTIFY_STOP; |
---|
| 3183 | + mce->kflags |= MCE_HANDLED_EDAC; |
---|
| 3184 | + return NOTIFY_OK; |
---|
3093 | 3185 | } |
---|
3094 | 3186 | |
---|
3095 | 3187 | static struct notifier_block sbridge_mce_dec = { |
---|
.. | .. |
---|
3104 | 3196 | static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) |
---|
3105 | 3197 | { |
---|
3106 | 3198 | struct mem_ctl_info *mci = sbridge_dev->mci; |
---|
3107 | | - struct sbridge_pvt *pvt; |
---|
3108 | 3199 | |
---|
3109 | 3200 | if (unlikely(!mci || !mci->pvt_info)) { |
---|
3110 | 3201 | edac_dbg(0, "MC: dev = %p\n", &sbridge_dev->pdev[0]->dev); |
---|
.. | .. |
---|
3112 | 3203 | sbridge_printk(KERN_ERR, "Couldn't find mci handler\n"); |
---|
3113 | 3204 | return; |
---|
3114 | 3205 | } |
---|
3115 | | - |
---|
3116 | | - pvt = mci->pvt_info; |
---|
3117 | 3206 | |
---|
3118 | 3207 | edac_dbg(0, "MC: mci = %p, dev = %p\n", |
---|
3119 | 3208 | mci, &sbridge_dev->pdev[0]->dev); |
---|
.. | .. |
---|
3176 | 3265 | pvt->info.dram_rule = ibridge_dram_rule; |
---|
3177 | 3266 | pvt->info.get_memory_type = get_memory_type; |
---|
3178 | 3267 | pvt->info.get_node_id = get_node_id; |
---|
| 3268 | + pvt->info.get_ha = ibridge_get_ha; |
---|
3179 | 3269 | pvt->info.rir_limit = rir_limit; |
---|
3180 | 3270 | pvt->info.sad_limit = sad_limit; |
---|
3181 | 3271 | pvt->info.interleave_mode = interleave_mode; |
---|
.. | .. |
---|
3200 | 3290 | pvt->info.dram_rule = sbridge_dram_rule; |
---|
3201 | 3291 | pvt->info.get_memory_type = get_memory_type; |
---|
3202 | 3292 | pvt->info.get_node_id = get_node_id; |
---|
| 3293 | + pvt->info.get_ha = sbridge_get_ha; |
---|
3203 | 3294 | pvt->info.rir_limit = rir_limit; |
---|
3204 | 3295 | pvt->info.sad_limit = sad_limit; |
---|
3205 | 3296 | pvt->info.interleave_mode = interleave_mode; |
---|
.. | .. |
---|
3224 | 3315 | pvt->info.dram_rule = ibridge_dram_rule; |
---|
3225 | 3316 | pvt->info.get_memory_type = haswell_get_memory_type; |
---|
3226 | 3317 | pvt->info.get_node_id = haswell_get_node_id; |
---|
| 3318 | + pvt->info.get_ha = ibridge_get_ha; |
---|
3227 | 3319 | pvt->info.rir_limit = haswell_rir_limit; |
---|
3228 | 3320 | pvt->info.sad_limit = sad_limit; |
---|
3229 | 3321 | pvt->info.interleave_mode = interleave_mode; |
---|
.. | .. |
---|
3248 | 3340 | pvt->info.dram_rule = ibridge_dram_rule; |
---|
3249 | 3341 | pvt->info.get_memory_type = haswell_get_memory_type; |
---|
3250 | 3342 | pvt->info.get_node_id = haswell_get_node_id; |
---|
| 3343 | + pvt->info.get_ha = ibridge_get_ha; |
---|
3251 | 3344 | pvt->info.rir_limit = haswell_rir_limit; |
---|
3252 | 3345 | pvt->info.sad_limit = sad_limit; |
---|
3253 | 3346 | pvt->info.interleave_mode = interleave_mode; |
---|
.. | .. |
---|
3272 | 3365 | pvt->info.dram_rule = knl_dram_rule; |
---|
3273 | 3366 | pvt->info.get_memory_type = knl_get_memory_type; |
---|
3274 | 3367 | pvt->info.get_node_id = knl_get_node_id; |
---|
| 3368 | + pvt->info.get_ha = knl_get_ha; |
---|
3275 | 3369 | pvt->info.rir_limit = NULL; |
---|
3276 | 3370 | pvt->info.sad_limit = knl_sad_limit; |
---|
3277 | 3371 | pvt->info.interleave_mode = knl_interleave_mode; |
---|
.. | .. |
---|
3323 | 3417 | return rc; |
---|
3324 | 3418 | } |
---|
3325 | 3419 | |
---|
3326 | | -#define ICPU(model, table) \ |
---|
3327 | | - { X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table } |
---|
3328 | | - |
---|
3329 | 3420 | static const struct x86_cpu_id sbridge_cpuids[] = { |
---|
3330 | | - ICPU(INTEL_FAM6_SANDYBRIDGE_X, pci_dev_descr_sbridge_table), |
---|
3331 | | - ICPU(INTEL_FAM6_IVYBRIDGE_X, pci_dev_descr_ibridge_table), |
---|
3332 | | - ICPU(INTEL_FAM6_HASWELL_X, pci_dev_descr_haswell_table), |
---|
3333 | | - ICPU(INTEL_FAM6_BROADWELL_X, pci_dev_descr_broadwell_table), |
---|
3334 | | - ICPU(INTEL_FAM6_BROADWELL_XEON_D, pci_dev_descr_broadwell_table), |
---|
3335 | | - ICPU(INTEL_FAM6_XEON_PHI_KNL, pci_dev_descr_knl_table), |
---|
3336 | | - ICPU(INTEL_FAM6_XEON_PHI_KNM, pci_dev_descr_knl_table), |
---|
| 3421 | + X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &pci_dev_descr_sbridge_table), |
---|
| 3422 | + X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &pci_dev_descr_ibridge_table), |
---|
| 3423 | + X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &pci_dev_descr_haswell_table), |
---|
| 3424 | + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &pci_dev_descr_broadwell_table), |
---|
| 3425 | + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &pci_dev_descr_broadwell_table), |
---|
| 3426 | + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &pci_dev_descr_knl_table), |
---|
| 3427 | + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &pci_dev_descr_knl_table), |
---|
3337 | 3428 | { } |
---|
3338 | 3429 | }; |
---|
3339 | 3430 | MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids); |
---|
.. | .. |
---|
3419 | 3510 | if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) |
---|
3420 | 3511 | return -EBUSY; |
---|
3421 | 3512 | |
---|
| 3513 | + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) |
---|
| 3514 | + return -ENODEV; |
---|
| 3515 | + |
---|
3422 | 3516 | id = x86_match_cpu(sbridge_cpuids); |
---|
3423 | 3517 | if (!id) |
---|
3424 | 3518 | return -ENODEV; |
---|
.. | .. |
---|
3430 | 3524 | |
---|
3431 | 3525 | if (rc >= 0) { |
---|
3432 | 3526 | mce_register_decode_chain(&sbridge_mce_dec); |
---|
3433 | | - if (edac_get_report_status() == EDAC_REPORTING_DISABLED) |
---|
3434 | | - sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.\n"); |
---|
3435 | 3527 | return 0; |
---|
3436 | 3528 | } |
---|
3437 | 3529 | |
---|
.. | .. |
---|
3460 | 3552 | |
---|
3461 | 3553 | MODULE_LICENSE("GPL"); |
---|
3462 | 3554 | MODULE_AUTHOR("Mauro Carvalho Chehab"); |
---|
3463 | | -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); |
---|
| 3555 | +MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)"); |
---|
3464 | 3556 | MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - " |
---|
3465 | 3557 | SBRIDGE_REVISION); |
---|