1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include "ifpga_feature_dev.h" 6 7 static int fme_err_get_errors(struct ifpga_fme_hw *fme, u64 *val) 8 { 9 struct feature_fme_err *fme_err 10 = get_fme_feature_ioaddr_by_index(fme, 11 FME_FEATURE_ID_GLOBAL_ERR); 12 struct feature_fme_error0 fme_error0; 13 14 fme_error0.csr = readq(&fme_err->fme_err); 15 *val = fme_error0.csr; 16 17 return 0; 18 } 19 20 static int fme_err_get_first_error(struct ifpga_fme_hw *fme, u64 *val) 21 { 22 struct feature_fme_err *fme_err 23 = get_fme_feature_ioaddr_by_index(fme, 24 FME_FEATURE_ID_GLOBAL_ERR); 25 struct feature_fme_first_error fme_first_err; 26 27 fme_first_err.csr = readq(&fme_err->fme_first_err); 28 *val = fme_first_err.err_reg_status; 29 30 return 0; 31 } 32 33 static int fme_err_get_next_error(struct ifpga_fme_hw *fme, u64 *val) 34 { 35 struct feature_fme_err *fme_err 36 = get_fme_feature_ioaddr_by_index(fme, 37 FME_FEATURE_ID_GLOBAL_ERR); 38 struct feature_fme_next_error fme_next_err; 39 40 fme_next_err.csr = readq(&fme_err->fme_next_err); 41 *val = fme_next_err.err_reg_status; 42 43 return 0; 44 } 45 46 static int fme_err_set_clear(struct ifpga_fme_hw *fme, u64 val) 47 { 48 struct feature_fme_err *fme_err 49 = get_fme_feature_ioaddr_by_index(fme, 50 FME_FEATURE_ID_GLOBAL_ERR); 51 struct feature_fme_error0 fme_error0; 52 struct feature_fme_first_error fme_first_err; 53 struct feature_fme_next_error fme_next_err; 54 int ret = 0; 55 56 spinlock_lock(&fme->lock); 57 writeq(FME_ERROR0_MASK, &fme_err->fme_err_mask); 58 59 fme_error0.csr = readq(&fme_err->fme_err); 60 if (val != fme_error0.csr) { 61 ret = -EBUSY; 62 goto exit; 63 } 64 65 fme_first_err.csr = readq(&fme_err->fme_first_err); 66 fme_next_err.csr = readq(&fme_err->fme_next_err); 67 68 writeq(fme_error0.csr & FME_ERROR0_MASK, &fme_err->fme_err); 69 writeq(fme_first_err.csr & FME_FIRST_ERROR_MASK, 70 &fme_err->fme_first_err); 71 writeq(fme_next_err.csr & FME_NEXT_ERROR_MASK, 72 &fme_err->fme_next_err); 73 74 exit: 75 writeq(FME_ERROR0_MASK_DEFAULT, &fme_err->fme_err_mask); 76 spinlock_unlock(&fme->lock); 77 78 return ret; 79 } 80 81 static int fme_err_get_revision(struct ifpga_fme_hw *fme, u64 *val) 82 { 83 struct feature_fme_err *fme_err 84 = get_fme_feature_ioaddr_by_index(fme, 85 FME_FEATURE_ID_GLOBAL_ERR); 86 struct feature_header header; 87 88 header.csr = readq(&fme_err->header); 89 *val = header.revision; 90 91 return 0; 92 } 93 94 static int fme_err_get_pcie0_errors(struct ifpga_fme_hw *fme, u64 *val) 95 { 96 struct feature_fme_err *fme_err 97 = get_fme_feature_ioaddr_by_index(fme, 98 FME_FEATURE_ID_GLOBAL_ERR); 99 struct feature_fme_pcie0_error pcie0_err; 100 101 pcie0_err.csr = readq(&fme_err->pcie0_err); 102 *val = pcie0_err.csr; 103 104 return 0; 105 } 106 107 static int fme_err_set_pcie0_errors(struct ifpga_fme_hw *fme, u64 val) 108 { 109 struct feature_fme_err *fme_err 110 = get_fme_feature_ioaddr_by_index(fme, 111 FME_FEATURE_ID_GLOBAL_ERR); 112 struct feature_fme_pcie0_error pcie0_err; 113 int ret = 0; 114 115 spinlock_lock(&fme->lock); 116 writeq(FME_PCIE0_ERROR_MASK, &fme_err->pcie0_err_mask); 117 118 pcie0_err.csr = readq(&fme_err->pcie0_err); 119 if (val != pcie0_err.csr) 120 ret = -EBUSY; 121 else 122 writeq(pcie0_err.csr & FME_PCIE0_ERROR_MASK, 123 &fme_err->pcie0_err); 124 125 writeq(0UL, &fme_err->pcie0_err_mask); 126 spinlock_unlock(&fme->lock); 127 128 return ret; 129 } 130 131 static int fme_err_get_pcie1_errors(struct ifpga_fme_hw *fme, u64 *val) 132 { 133 struct feature_fme_err *fme_err 134 = get_fme_feature_ioaddr_by_index(fme, 135 FME_FEATURE_ID_GLOBAL_ERR); 136 struct feature_fme_pcie1_error pcie1_err; 137 138 pcie1_err.csr = readq(&fme_err->pcie1_err); 139 *val = pcie1_err.csr; 140 141 return 0; 142 } 143 144 static int fme_err_set_pcie1_errors(struct ifpga_fme_hw *fme, u64 val) 145 { 146 struct feature_fme_err *fme_err 147 = get_fme_feature_ioaddr_by_index(fme, 148 FME_FEATURE_ID_GLOBAL_ERR); 149 struct feature_fme_pcie1_error pcie1_err; 150 int ret = 0; 151 152 spinlock_lock(&fme->lock); 153 writeq(FME_PCIE1_ERROR_MASK, &fme_err->pcie1_err_mask); 154 155 pcie1_err.csr = readq(&fme_err->pcie1_err); 156 if (val != pcie1_err.csr) 157 ret = -EBUSY; 158 else 159 writeq(pcie1_err.csr & FME_PCIE1_ERROR_MASK, 160 &fme_err->pcie1_err); 161 162 writeq(0UL, &fme_err->pcie1_err_mask); 163 spinlock_unlock(&fme->lock); 164 165 return ret; 166 } 167 168 static int fme_err_get_nonfatal_errors(struct ifpga_fme_hw *fme, u64 *val) 169 { 170 struct feature_fme_err *fme_err 171 = get_fme_feature_ioaddr_by_index(fme, 172 FME_FEATURE_ID_GLOBAL_ERR); 173 struct feature_fme_ras_nonfaterror ras_nonfaterr; 174 175 ras_nonfaterr.csr = readq(&fme_err->ras_nonfaterr); 176 *val = ras_nonfaterr.csr; 177 178 return 0; 179 } 180 181 static int fme_err_get_catfatal_errors(struct ifpga_fme_hw *fme, u64 *val) 182 { 183 struct feature_fme_err *fme_err 184 = get_fme_feature_ioaddr_by_index(fme, 185 FME_FEATURE_ID_GLOBAL_ERR); 186 struct feature_fme_ras_catfaterror ras_catfaterr; 187 188 ras_catfaterr.csr = readq(&fme_err->ras_catfaterr); 189 *val = ras_catfaterr.csr; 190 191 return 0; 192 } 193 194 static int fme_err_get_inject_errors(struct ifpga_fme_hw *fme, u64 *val) 195 { 196 struct feature_fme_err *fme_err 197 = get_fme_feature_ioaddr_by_index(fme, 198 FME_FEATURE_ID_GLOBAL_ERR); 199 struct feature_fme_ras_error_inj ras_error_inj; 200 201 ras_error_inj.csr = readq(&fme_err->ras_error_inj); 202 *val = ras_error_inj.csr & FME_RAS_ERROR_INJ_MASK; 203 204 return 0; 205 } 206 207 static int fme_err_set_inject_errors(struct ifpga_fme_hw *fme, u64 val) 208 { 209 struct feature_fme_err *fme_err 210 = get_fme_feature_ioaddr_by_index(fme, 211 FME_FEATURE_ID_GLOBAL_ERR); 212 struct feature_fme_ras_error_inj ras_error_inj; 213 214 spinlock_lock(&fme->lock); 215 ras_error_inj.csr = readq(&fme_err->ras_error_inj); 216 217 if (val <= FME_RAS_ERROR_INJ_MASK) { 218 ras_error_inj.csr = val; 219 } else { 220 spinlock_unlock(&fme->lock); 221 return -EINVAL; 222 } 223 224 writeq(ras_error_inj.csr, &fme_err->ras_error_inj); 225 spinlock_unlock(&fme->lock); 226 227 return 0; 228 } 229 230 static void fme_error_enable(struct ifpga_fme_hw *fme) 231 { 232 struct feature_fme_err *fme_err 233 = get_fme_feature_ioaddr_by_index(fme, 234 FME_FEATURE_ID_GLOBAL_ERR); 235 236 writeq(FME_ERROR0_MASK_DEFAULT, &fme_err->fme_err_mask); 237 writeq(0UL, &fme_err->pcie0_err_mask); 238 writeq(0UL, &fme_err->pcie1_err_mask); 239 writeq(0UL, &fme_err->ras_nonfat_mask); 240 writeq(0UL, &fme_err->ras_catfat_mask); 241 } 242 243 static int fme_global_error_init(struct ifpga_feature *feature) 244 { 245 struct ifpga_fme_hw *fme = feature->parent; 246 247 fme_error_enable(fme); 248 249 if (feature->ctx_num) 250 fme->capability |= FPGA_FME_CAP_ERR_IRQ; 251 252 return 0; 253 } 254 255 static void fme_global_error_uinit(struct ifpga_feature *feature) 256 { 257 UNUSED(feature); 258 } 259 260 static int fme_err_fme_err_get_prop(struct ifpga_feature *feature, 261 struct feature_prop *prop) 262 { 263 struct ifpga_fme_hw *fme = feature->parent; 264 u16 id = GET_FIELD(PROP_ID, prop->prop_id); 265 266 switch (id) { 267 case 0x1: /* ERRORS */ 268 return fme_err_get_errors(fme, &prop->data); 269 case 0x2: /* FIRST_ERROR */ 270 return fme_err_get_first_error(fme, &prop->data); 271 case 0x3: /* NEXT_ERROR */ 272 return fme_err_get_next_error(fme, &prop->data); 273 } 274 275 return -ENOENT; 276 } 277 278 static int fme_err_root_get_prop(struct ifpga_feature *feature, 279 struct feature_prop *prop) 280 { 281 struct ifpga_fme_hw *fme = feature->parent; 282 u16 id = GET_FIELD(PROP_ID, prop->prop_id); 283 284 switch (id) { 285 case 0x5: /* REVISION */ 286 return fme_err_get_revision(fme, &prop->data); 287 case 0x6: /* PCIE0_ERRORS */ 288 return fme_err_get_pcie0_errors(fme, &prop->data); 289 case 0x7: /* PCIE1_ERRORS */ 290 return fme_err_get_pcie1_errors(fme, &prop->data); 291 case 0x8: /* NONFATAL_ERRORS */ 292 return fme_err_get_nonfatal_errors(fme, &prop->data); 293 case 0x9: /* CATFATAL_ERRORS */ 294 return fme_err_get_catfatal_errors(fme, &prop->data); 295 case 0xa: /* INJECT_ERRORS */ 296 return fme_err_get_inject_errors(fme, &prop->data); 297 case 0xb: /* REVISION*/ 298 return fme_err_get_revision(fme, &prop->data); 299 } 300 301 return -ENOENT; 302 } 303 304 static int fme_global_error_get_prop(struct ifpga_feature *feature, 305 struct feature_prop *prop) 306 { 307 u8 top = GET_FIELD(PROP_TOP, prop->prop_id); 308 u8 sub = GET_FIELD(PROP_SUB, prop->prop_id); 309 310 /* PROP_SUB is never used */ 311 if (sub != PROP_SUB_UNUSED) 312 return -ENOENT; 313 314 switch (top) { 315 case ERR_PROP_TOP_FME_ERR: 316 return fme_err_fme_err_get_prop(feature, prop); 317 case ERR_PROP_TOP_UNUSED: 318 return fme_err_root_get_prop(feature, prop); 319 } 320 321 return -ENOENT; 322 } 323 324 static int fme_err_fme_err_set_prop(struct ifpga_feature *feature, 325 struct feature_prop *prop) 326 { 327 struct ifpga_fme_hw *fme = feature->parent; 328 u16 id = GET_FIELD(PROP_ID, prop->prop_id); 329 330 switch (id) { 331 case 0x4: /* CLEAR */ 332 return fme_err_set_clear(fme, prop->data); 333 } 334 335 return -ENOENT; 336 } 337 338 static int fme_err_root_set_prop(struct ifpga_feature *feature, 339 struct feature_prop *prop) 340 { 341 struct ifpga_fme_hw *fme = feature->parent; 342 u16 id = GET_FIELD(PROP_ID, prop->prop_id); 343 344 switch (id) { 345 case 0x6: /* PCIE0_ERRORS */ 346 return fme_err_set_pcie0_errors(fme, prop->data); 347 case 0x7: /* PCIE1_ERRORS */ 348 return fme_err_set_pcie1_errors(fme, prop->data); 349 case 0xa: /* INJECT_ERRORS */ 350 return fme_err_set_inject_errors(fme, prop->data); 351 } 352 353 return -ENOENT; 354 } 355 356 static int fme_global_error_set_prop(struct ifpga_feature *feature, 357 struct feature_prop *prop) 358 { 359 u8 top = GET_FIELD(PROP_TOP, prop->prop_id); 360 u8 sub = GET_FIELD(PROP_SUB, prop->prop_id); 361 362 /* PROP_SUB is never used */ 363 if (sub != PROP_SUB_UNUSED) 364 return -ENOENT; 365 366 switch (top) { 367 case ERR_PROP_TOP_FME_ERR: 368 return fme_err_fme_err_set_prop(feature, prop); 369 case ERR_PROP_TOP_UNUSED: 370 return fme_err_root_set_prop(feature, prop); 371 } 372 373 return -ENOENT; 374 } 375 376 struct ifpga_feature_ops fme_global_err_ops = { 377 .init = fme_global_error_init, 378 .uinit = fme_global_error_uinit, 379 .get_prop = fme_global_error_get_prop, 380 .set_prop = fme_global_error_set_prop, 381 }; 382