|
16 | 16 | #define DEV_SIZE SZ_2G |
17 | 17 | #define EFFECT(x) (1U << x) |
18 | 18 |
|
| 19 | +#define MOCK_INJECT_DEV_MAX 8 |
| 20 | +#define MOCK_INJECT_TEST_MAX 128 |
| 21 | + |
19 | 22 | static struct cxl_cel_entry mock_cel[] = { |
20 | 23 | { |
21 | 24 | .opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS), |
@@ -45,6 +48,10 @@ static struct cxl_cel_entry mock_cel[] = { |
45 | 48 | .opcode = cpu_to_le16(CXL_MBOX_OP_GET_POISON), |
46 | 49 | .effect = cpu_to_le16(0), |
47 | 50 | }, |
| 51 | + { |
| 52 | + .opcode = cpu_to_le16(CXL_MBOX_OP_INJECT_POISON), |
| 53 | + .effect = cpu_to_le16(0), |
| 54 | + }, |
48 | 55 | }; |
49 | 56 |
|
50 | 57 | /* See CXL 2.0 Table 181 Get Health Info Output Payload */ |
@@ -474,6 +481,7 @@ static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) |
474 | 481 | cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER), |
475 | 482 | .total_capacity = |
476 | 483 | cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER), |
| 484 | + .inject_poison_limit = cpu_to_le16(MOCK_INJECT_DEV_MAX), |
477 | 485 | }; |
478 | 486 |
|
479 | 487 | put_unaligned_le24(CXL_POISON_LIST_MAX, id.poison_list_max_mer); |
@@ -895,6 +903,11 @@ static int mock_health_info(struct cxl_dev_state *cxlds, |
895 | 903 | return 0; |
896 | 904 | } |
897 | 905 |
|
| 906 | +static struct mock_poison { |
| 907 | + struct cxl_dev_state *cxlds; |
| 908 | + u64 dpa; |
| 909 | +} mock_poison_list[MOCK_INJECT_TEST_MAX]; |
| 910 | + |
898 | 911 | static int mock_get_poison(struct cxl_dev_state *cxlds, |
899 | 912 | struct cxl_mbox_cmd *cmd) |
900 | 913 | { |
@@ -923,6 +936,67 @@ static int mock_get_poison(struct cxl_dev_state *cxlds, |
923 | 936 | return 0; |
924 | 937 | } |
925 | 938 |
|
| 939 | +static bool mock_poison_dev_max_injected(struct cxl_dev_state *cxlds) |
| 940 | +{ |
| 941 | + int count = 0; |
| 942 | + |
| 943 | + for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) { |
| 944 | + if (mock_poison_list[i].cxlds == cxlds) |
| 945 | + count++; |
| 946 | + } |
| 947 | + return (count >= MOCK_INJECT_DEV_MAX); |
| 948 | +} |
| 949 | + |
| 950 | +static bool mock_poison_add(struct cxl_dev_state *cxlds, u64 dpa) |
| 951 | +{ |
| 952 | + if (mock_poison_dev_max_injected(cxlds)) { |
| 953 | + dev_dbg(cxlds->dev, |
| 954 | + "Device poison injection limit has been reached: %d\n", |
| 955 | + MOCK_INJECT_DEV_MAX); |
| 956 | + return false; |
| 957 | + } |
| 958 | + |
| 959 | + for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) { |
| 960 | + if (!mock_poison_list[i].cxlds) { |
| 961 | + mock_poison_list[i].cxlds = cxlds; |
| 962 | + mock_poison_list[i].dpa = dpa; |
| 963 | + return true; |
| 964 | + } |
| 965 | + } |
| 966 | + dev_dbg(cxlds->dev, |
| 967 | + "Mock test poison injection limit has been reached: %d\n", |
| 968 | + MOCK_INJECT_TEST_MAX); |
| 969 | + |
| 970 | + return false; |
| 971 | +} |
| 972 | + |
| 973 | +static bool mock_poison_found(struct cxl_dev_state *cxlds, u64 dpa) |
| 974 | +{ |
| 975 | + for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) { |
| 976 | + if (mock_poison_list[i].cxlds == cxlds && |
| 977 | + mock_poison_list[i].dpa == dpa) |
| 978 | + return true; |
| 979 | + } |
| 980 | + return false; |
| 981 | +} |
| 982 | + |
| 983 | +static int mock_inject_poison(struct cxl_dev_state *cxlds, |
| 984 | + struct cxl_mbox_cmd *cmd) |
| 985 | +{ |
| 986 | + struct cxl_mbox_inject_poison *pi = cmd->payload_in; |
| 987 | + u64 dpa = le64_to_cpu(pi->address); |
| 988 | + |
| 989 | + if (mock_poison_found(cxlds, dpa)) { |
| 990 | + /* Not an error to inject poison if already poisoned */ |
| 991 | + dev_dbg(cxlds->dev, "DPA: 0x%llx already poisoned\n", dpa); |
| 992 | + return 0; |
| 993 | + } |
| 994 | + if (!mock_poison_add(cxlds, dpa)) |
| 995 | + return -ENXIO; |
| 996 | + |
| 997 | + return 0; |
| 998 | +} |
| 999 | + |
926 | 1000 | static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd) |
927 | 1001 | { |
928 | 1002 | struct device *dev = cxlds->dev; |
@@ -980,6 +1054,9 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd * |
980 | 1054 | case CXL_MBOX_OP_GET_POISON: |
981 | 1055 | rc = mock_get_poison(cxlds, cmd); |
982 | 1056 | break; |
| 1057 | + case CXL_MBOX_OP_INJECT_POISON: |
| 1058 | + rc = mock_inject_poison(cxlds, cmd); |
| 1059 | + break; |
983 | 1060 | default: |
984 | 1061 | break; |
985 | 1062 | } |
|
0 commit comments