1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * driver for Microchip PQI-based storage controllers |
4 | * Copyright (c) 2019-2023 Microchip Technology Inc. and its subsidiaries |
5 | * Copyright (c) 2016-2018 Microsemi Corporation |
6 | * Copyright (c) 2016 PMC-Sierra, Inc. |
7 | * |
8 | * Questions/Comments/Bugfixes to storagedev@microchip.com |
9 | * |
10 | */ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/pci.h> |
16 | #include <scsi/scsi_device.h> |
17 | #include <asm/unaligned.h> |
18 | #include "smartpqi.h" |
19 | #include "smartpqi_sis.h" |
20 | |
21 | /* legacy SIS interface commands */ |
22 | #define SIS_CMD_GET_ADAPTER_PROPERTIES 0x19 |
23 | #define SIS_CMD_INIT_BASE_STRUCT_ADDRESS 0x1b |
24 | #define SIS_CMD_GET_PQI_CAPABILITIES 0x3000 |
25 | |
26 | /* for submission of legacy SIS commands */ |
27 | #define SIS_REENABLE_SIS_MODE 0x1 |
28 | #define SIS_ENABLE_MSIX 0x40 |
29 | #define SIS_ENABLE_INTX 0x80 |
30 | #define SIS_SOFT_RESET 0x100 |
31 | #define SIS_CMD_READY 0x200 |
32 | #define SIS_TRIGGER_SHUTDOWN 0x800000 |
33 | #define SIS_PQI_RESET_QUIESCE 0x1000000 |
34 | |
35 | #define SIS_CMD_COMPLETE 0x1000 |
36 | #define SIS_CLEAR_CTRL_TO_HOST_DOORBELL 0x1000 |
37 | |
38 | #define SIS_CMD_STATUS_SUCCESS 0x1 |
39 | #define SIS_CMD_COMPLETE_TIMEOUT_SECS 30 |
40 | #define SIS_CMD_COMPLETE_POLL_INTERVAL_MSECS 10 |
41 | |
42 | /* used with SIS_CMD_GET_ADAPTER_PROPERTIES command */ |
43 | #define SIS_EXTENDED_PROPERTIES_SUPPORTED 0x800000 |
44 | #define SIS_SMARTARRAY_FEATURES_SUPPORTED 0x2 |
45 | #define SIS_PQI_MODE_SUPPORTED 0x4 |
46 | #define SIS_PQI_RESET_QUIESCE_SUPPORTED 0x8 |
47 | #define SIS_REQUIRED_EXTENDED_PROPERTIES \ |
48 | (SIS_SMARTARRAY_FEATURES_SUPPORTED | SIS_PQI_MODE_SUPPORTED) |
49 | |
50 | /* used with SIS_CMD_INIT_BASE_STRUCT_ADDRESS command */ |
51 | #define SIS_BASE_STRUCT_REVISION 9 |
52 | #define SIS_BASE_STRUCT_ALIGNMENT 16 |
53 | |
54 | #define SIS_CTRL_KERNEL_FW_TRIAGE 0x3 |
55 | #define SIS_CTRL_KERNEL_UP 0x80 |
56 | #define SIS_CTRL_KERNEL_PANIC 0x100 |
57 | #define SIS_CTRL_READY_TIMEOUT_SECS 180 |
58 | #define SIS_CTRL_READY_RESUME_TIMEOUT_SECS 90 |
59 | #define SIS_CTRL_READY_POLL_INTERVAL_MSECS 10 |
60 | |
61 | enum sis_fw_triage_status { |
62 | FW_TRIAGE_NOT_STARTED = 0, |
63 | FW_TRIAGE_STARTED, |
64 | FW_TRIAGE_COND_INVALID, |
65 | FW_TRIAGE_COMPLETED |
66 | }; |
67 | |
68 | #pragma pack(1) |
69 | |
70 | /* for use with SIS_CMD_INIT_BASE_STRUCT_ADDRESS command */ |
71 | struct sis_base_struct { |
72 | __le32 revision; /* revision of this structure */ |
73 | __le32 flags; /* reserved */ |
74 | __le32 error_buffer_paddr_low; /* lower 32 bits of physical memory */ |
75 | /* buffer for PQI error response */ |
76 | /* data */ |
77 | __le32 error_buffer_paddr_high; /* upper 32 bits of physical */ |
78 | /* memory buffer for PQI */ |
79 | /* error response data */ |
80 | __le32 error_buffer_element_length; /* length of each PQI error */ |
81 | /* response buffer element */ |
82 | /* in bytes */ |
83 | __le32 error_buffer_num_elements; /* total number of PQI error */ |
84 | /* response buffers available */ |
85 | }; |
86 | |
87 | #pragma pack() |
88 | |
89 | unsigned int sis_ctrl_ready_timeout_secs = SIS_CTRL_READY_TIMEOUT_SECS; |
90 | |
91 | static int sis_wait_for_ctrl_ready_with_timeout(struct pqi_ctrl_info *ctrl_info, |
92 | unsigned int timeout_secs) |
93 | { |
94 | unsigned long timeout; |
95 | u32 status; |
96 | |
97 | timeout = (timeout_secs * HZ) + jiffies; |
98 | |
99 | while (1) { |
100 | status = readl(addr: &ctrl_info->registers->sis_firmware_status); |
101 | if (status != ~0) { |
102 | if (status & SIS_CTRL_KERNEL_PANIC) { |
103 | dev_err(&ctrl_info->pci_dev->dev, |
104 | "controller is offline: status code 0x%x\n" , |
105 | readl( |
106 | &ctrl_info->registers->sis_mailbox[7])); |
107 | return -ENODEV; |
108 | } |
109 | if (status & SIS_CTRL_KERNEL_UP) |
110 | break; |
111 | } |
112 | if (time_after(jiffies, timeout)) { |
113 | dev_err(&ctrl_info->pci_dev->dev, |
114 | "controller not ready after %u seconds\n" , |
115 | timeout_secs); |
116 | return -ETIMEDOUT; |
117 | } |
118 | msleep(SIS_CTRL_READY_POLL_INTERVAL_MSECS); |
119 | } |
120 | |
121 | return 0; |
122 | } |
123 | |
124 | int sis_wait_for_ctrl_ready(struct pqi_ctrl_info *ctrl_info) |
125 | { |
126 | return sis_wait_for_ctrl_ready_with_timeout(ctrl_info, |
127 | timeout_secs: sis_ctrl_ready_timeout_secs); |
128 | } |
129 | |
130 | int sis_wait_for_ctrl_ready_resume(struct pqi_ctrl_info *ctrl_info) |
131 | { |
132 | return sis_wait_for_ctrl_ready_with_timeout(ctrl_info, |
133 | SIS_CTRL_READY_RESUME_TIMEOUT_SECS); |
134 | } |
135 | |
136 | bool sis_is_firmware_running(struct pqi_ctrl_info *ctrl_info) |
137 | { |
138 | bool running; |
139 | u32 status; |
140 | |
141 | status = readl(addr: &ctrl_info->registers->sis_firmware_status); |
142 | |
143 | if (status != ~0 && (status & SIS_CTRL_KERNEL_PANIC)) |
144 | running = false; |
145 | else |
146 | running = true; |
147 | |
148 | if (!running) |
149 | dev_err(&ctrl_info->pci_dev->dev, |
150 | "controller is offline: status code 0x%x\n" , |
151 | readl(&ctrl_info->registers->sis_mailbox[7])); |
152 | |
153 | return running; |
154 | } |
155 | |
156 | bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info) |
157 | { |
158 | return readl(addr: &ctrl_info->registers->sis_firmware_status) & |
159 | SIS_CTRL_KERNEL_UP; |
160 | } |
161 | |
162 | u32 sis_get_product_id(struct pqi_ctrl_info *ctrl_info) |
163 | { |
164 | return readl(addr: &ctrl_info->registers->sis_product_identifier); |
165 | } |
166 | |
167 | /* used for passing command parameters/results when issuing SIS commands */ |
168 | struct sis_sync_cmd_params { |
169 | u32 mailbox[6]; /* mailboxes 0-5 */ |
170 | }; |
171 | |
172 | static int sis_send_sync_cmd(struct pqi_ctrl_info *ctrl_info, |
173 | u32 cmd, struct sis_sync_cmd_params *params) |
174 | { |
175 | struct pqi_ctrl_registers __iomem *registers; |
176 | unsigned int i; |
177 | unsigned long timeout; |
178 | u32 doorbell; |
179 | u32 cmd_status; |
180 | |
181 | registers = ctrl_info->registers; |
182 | |
183 | /* Write the command to mailbox 0. */ |
184 | writel(val: cmd, addr: ®isters->sis_mailbox[0]); |
185 | |
186 | /* |
187 | * Write the command parameters to mailboxes 1-4 (mailbox 5 is not used |
188 | * when sending a command to the controller). |
189 | */ |
190 | for (i = 1; i <= 4; i++) |
191 | writel(val: params->mailbox[i], addr: ®isters->sis_mailbox[i]); |
192 | |
193 | /* Clear the command doorbell. */ |
194 | writel(SIS_CLEAR_CTRL_TO_HOST_DOORBELL, |
195 | addr: ®isters->sis_ctrl_to_host_doorbell_clear); |
196 | |
197 | /* Disable doorbell interrupts by masking all interrupts. */ |
198 | writel(val: ~0, addr: ®isters->sis_interrupt_mask); |
199 | usleep_range(min: 1000, max: 2000); |
200 | |
201 | /* |
202 | * Force the completion of the interrupt mask register write before |
203 | * submitting the command. |
204 | */ |
205 | readl(addr: ®isters->sis_interrupt_mask); |
206 | |
207 | /* Submit the command to the controller. */ |
208 | writel(SIS_CMD_READY, addr: ®isters->sis_host_to_ctrl_doorbell); |
209 | |
210 | /* |
211 | * Poll for command completion. Note that the call to msleep() is at |
212 | * the top of the loop in order to give the controller time to start |
213 | * processing the command before we start polling. |
214 | */ |
215 | timeout = (SIS_CMD_COMPLETE_TIMEOUT_SECS * HZ) + jiffies; |
216 | while (1) { |
217 | msleep(SIS_CMD_COMPLETE_POLL_INTERVAL_MSECS); |
218 | doorbell = readl(addr: ®isters->sis_ctrl_to_host_doorbell); |
219 | if (doorbell & SIS_CMD_COMPLETE) |
220 | break; |
221 | if (time_after(jiffies, timeout)) |
222 | return -ETIMEDOUT; |
223 | } |
224 | |
225 | /* Read the command status from mailbox 0. */ |
226 | cmd_status = readl(addr: ®isters->sis_mailbox[0]); |
227 | if (cmd_status != SIS_CMD_STATUS_SUCCESS) { |
228 | dev_err(&ctrl_info->pci_dev->dev, |
229 | "SIS command failed for command 0x%x: status = 0x%x\n" , |
230 | cmd, cmd_status); |
231 | return -EINVAL; |
232 | } |
233 | |
234 | /* |
235 | * The command completed successfully, so save the command status and |
236 | * read the values returned in mailboxes 1-5. |
237 | */ |
238 | params->mailbox[0] = cmd_status; |
239 | for (i = 1; i < ARRAY_SIZE(params->mailbox); i++) |
240 | params->mailbox[i] = readl(addr: ®isters->sis_mailbox[i]); |
241 | |
242 | return 0; |
243 | } |
244 | |
245 | /* |
246 | * This function verifies that we are talking to a controller that speaks PQI. |
247 | */ |
248 | |
249 | int sis_get_ctrl_properties(struct pqi_ctrl_info *ctrl_info) |
250 | { |
251 | int rc; |
252 | u32 properties; |
253 | u32 extended_properties; |
254 | struct sis_sync_cmd_params params; |
255 | |
256 | memset(¶ms, 0, sizeof(params)); |
257 | |
258 | rc = sis_send_sync_cmd(ctrl_info, SIS_CMD_GET_ADAPTER_PROPERTIES, |
259 | params: ¶ms); |
260 | if (rc) |
261 | return rc; |
262 | |
263 | properties = params.mailbox[1]; |
264 | |
265 | if (!(properties & SIS_EXTENDED_PROPERTIES_SUPPORTED)) |
266 | return -ENODEV; |
267 | |
268 | extended_properties = params.mailbox[4]; |
269 | |
270 | if ((extended_properties & SIS_REQUIRED_EXTENDED_PROPERTIES) != |
271 | SIS_REQUIRED_EXTENDED_PROPERTIES) |
272 | return -ENODEV; |
273 | |
274 | if (extended_properties & SIS_PQI_RESET_QUIESCE_SUPPORTED) |
275 | ctrl_info->pqi_reset_quiesce_supported = true; |
276 | |
277 | return 0; |
278 | } |
279 | |
280 | int sis_get_pqi_capabilities(struct pqi_ctrl_info *ctrl_info) |
281 | { |
282 | int rc; |
283 | struct sis_sync_cmd_params params; |
284 | |
285 | memset(¶ms, 0, sizeof(params)); |
286 | |
287 | rc = sis_send_sync_cmd(ctrl_info, SIS_CMD_GET_PQI_CAPABILITIES, |
288 | params: ¶ms); |
289 | if (rc) |
290 | return rc; |
291 | |
292 | ctrl_info->max_sg_entries = params.mailbox[1]; |
293 | ctrl_info->max_transfer_size = params.mailbox[2]; |
294 | ctrl_info->max_outstanding_requests = params.mailbox[3]; |
295 | ctrl_info->config_table_offset = params.mailbox[4]; |
296 | ctrl_info->config_table_length = params.mailbox[5]; |
297 | |
298 | return 0; |
299 | } |
300 | |
301 | int sis_init_base_struct_addr(struct pqi_ctrl_info *ctrl_info) |
302 | { |
303 | int rc; |
304 | void *base_struct_unaligned; |
305 | struct sis_base_struct *base_struct; |
306 | struct sis_sync_cmd_params params; |
307 | unsigned long error_buffer_paddr; |
308 | dma_addr_t bus_address; |
309 | |
310 | base_struct_unaligned = kzalloc(size: sizeof(*base_struct) |
311 | + SIS_BASE_STRUCT_ALIGNMENT - 1, GFP_KERNEL); |
312 | if (!base_struct_unaligned) |
313 | return -ENOMEM; |
314 | |
315 | base_struct = PTR_ALIGN(base_struct_unaligned, |
316 | SIS_BASE_STRUCT_ALIGNMENT); |
317 | error_buffer_paddr = (unsigned long)ctrl_info->error_buffer_dma_handle; |
318 | |
319 | put_unaligned_le32(SIS_BASE_STRUCT_REVISION, p: &base_struct->revision); |
320 | put_unaligned_le32(lower_32_bits(error_buffer_paddr), |
321 | p: &base_struct->error_buffer_paddr_low); |
322 | put_unaligned_le32(upper_32_bits(error_buffer_paddr), |
323 | p: &base_struct->error_buffer_paddr_high); |
324 | put_unaligned_le32(PQI_ERROR_BUFFER_ELEMENT_LENGTH, |
325 | p: &base_struct->error_buffer_element_length); |
326 | put_unaligned_le32(val: ctrl_info->max_io_slots, |
327 | p: &base_struct->error_buffer_num_elements); |
328 | |
329 | bus_address = dma_map_single(&ctrl_info->pci_dev->dev, base_struct, |
330 | sizeof(*base_struct), DMA_TO_DEVICE); |
331 | if (dma_mapping_error(dev: &ctrl_info->pci_dev->dev, dma_addr: bus_address)) { |
332 | rc = -ENOMEM; |
333 | goto out; |
334 | } |
335 | |
336 | memset(¶ms, 0, sizeof(params)); |
337 | params.mailbox[1] = lower_32_bits((u64)bus_address); |
338 | params.mailbox[2] = upper_32_bits((u64)bus_address); |
339 | params.mailbox[3] = sizeof(*base_struct); |
340 | |
341 | rc = sis_send_sync_cmd(ctrl_info, SIS_CMD_INIT_BASE_STRUCT_ADDRESS, |
342 | params: ¶ms); |
343 | |
344 | dma_unmap_single(&ctrl_info->pci_dev->dev, bus_address, |
345 | sizeof(*base_struct), DMA_TO_DEVICE); |
346 | out: |
347 | kfree(objp: base_struct_unaligned); |
348 | |
349 | return rc; |
350 | } |
351 | |
352 | #define SIS_DOORBELL_BIT_CLEAR_TIMEOUT_SECS 30 |
353 | |
354 | static int sis_wait_for_doorbell_bit_to_clear( |
355 | struct pqi_ctrl_info *ctrl_info, u32 bit) |
356 | { |
357 | int rc = 0; |
358 | u32 doorbell_register; |
359 | unsigned long timeout; |
360 | |
361 | timeout = (SIS_DOORBELL_BIT_CLEAR_TIMEOUT_SECS * HZ) + jiffies; |
362 | |
363 | while (1) { |
364 | doorbell_register = |
365 | readl(addr: &ctrl_info->registers->sis_host_to_ctrl_doorbell); |
366 | if ((doorbell_register & bit) == 0) |
367 | break; |
368 | if (readl(addr: &ctrl_info->registers->sis_firmware_status) & |
369 | SIS_CTRL_KERNEL_PANIC) { |
370 | rc = -ENODEV; |
371 | break; |
372 | } |
373 | if (time_after(jiffies, timeout)) { |
374 | dev_err(&ctrl_info->pci_dev->dev, |
375 | "doorbell register bit 0x%x not cleared\n" , |
376 | bit); |
377 | rc = -ETIMEDOUT; |
378 | break; |
379 | } |
380 | usleep_range(min: 1000, max: 2000); |
381 | } |
382 | |
383 | return rc; |
384 | } |
385 | |
386 | static inline int sis_set_doorbell_bit(struct pqi_ctrl_info *ctrl_info, u32 bit) |
387 | { |
388 | writel(val: bit, addr: &ctrl_info->registers->sis_host_to_ctrl_doorbell); |
389 | usleep_range(min: 1000, max: 2000); |
390 | |
391 | return sis_wait_for_doorbell_bit_to_clear(ctrl_info, bit); |
392 | } |
393 | |
394 | void sis_enable_msix(struct pqi_ctrl_info *ctrl_info) |
395 | { |
396 | sis_set_doorbell_bit(ctrl_info, SIS_ENABLE_MSIX); |
397 | } |
398 | |
399 | void sis_enable_intx(struct pqi_ctrl_info *ctrl_info) |
400 | { |
401 | sis_set_doorbell_bit(ctrl_info, SIS_ENABLE_INTX); |
402 | } |
403 | |
404 | void sis_shutdown_ctrl(struct pqi_ctrl_info *ctrl_info, |
405 | enum pqi_ctrl_shutdown_reason ctrl_shutdown_reason) |
406 | { |
407 | if (readl(addr: &ctrl_info->registers->sis_firmware_status) & |
408 | SIS_CTRL_KERNEL_PANIC) |
409 | return; |
410 | |
411 | if (ctrl_info->firmware_triage_supported) |
412 | writel(val: ctrl_shutdown_reason, addr: &ctrl_info->registers->sis_ctrl_shutdown_reason_code); |
413 | |
414 | writel(SIS_TRIGGER_SHUTDOWN, addr: &ctrl_info->registers->sis_host_to_ctrl_doorbell); |
415 | } |
416 | |
417 | int sis_pqi_reset_quiesce(struct pqi_ctrl_info *ctrl_info) |
418 | { |
419 | return sis_set_doorbell_bit(ctrl_info, SIS_PQI_RESET_QUIESCE); |
420 | } |
421 | |
422 | int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info) |
423 | { |
424 | return sis_set_doorbell_bit(ctrl_info, SIS_REENABLE_SIS_MODE); |
425 | } |
426 | |
427 | void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value) |
428 | { |
429 | writel(val: value, addr: &ctrl_info->registers->sis_driver_scratch); |
430 | usleep_range(min: 1000, max: 2000); |
431 | } |
432 | |
433 | u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info) |
434 | { |
435 | return readl(addr: &ctrl_info->registers->sis_driver_scratch); |
436 | } |
437 | |
438 | static inline enum sis_fw_triage_status |
439 | sis_read_firmware_triage_status(struct pqi_ctrl_info *ctrl_info) |
440 | { |
441 | return ((enum sis_fw_triage_status)(readl(addr: &ctrl_info->registers->sis_firmware_status) & |
442 | SIS_CTRL_KERNEL_FW_TRIAGE)); |
443 | } |
444 | |
445 | void sis_soft_reset(struct pqi_ctrl_info *ctrl_info) |
446 | { |
447 | writel(SIS_SOFT_RESET, |
448 | addr: &ctrl_info->registers->sis_host_to_ctrl_doorbell); |
449 | } |
450 | |
451 | #define SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS 300 |
452 | #define SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS 1 |
453 | |
454 | int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info) |
455 | { |
456 | int rc; |
457 | enum sis_fw_triage_status status; |
458 | unsigned long timeout; |
459 | |
460 | timeout = (SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS * HZ) + jiffies; |
461 | while (1) { |
462 | status = sis_read_firmware_triage_status(ctrl_info); |
463 | if (status == FW_TRIAGE_COND_INVALID) { |
464 | dev_err(&ctrl_info->pci_dev->dev, |
465 | "firmware triage condition invalid\n" ); |
466 | rc = -EINVAL; |
467 | break; |
468 | } else if (status == FW_TRIAGE_NOT_STARTED || |
469 | status == FW_TRIAGE_COMPLETED) { |
470 | rc = 0; |
471 | break; |
472 | } |
473 | |
474 | if (time_after(jiffies, timeout)) { |
475 | dev_err(&ctrl_info->pci_dev->dev, |
476 | "timed out waiting for firmware triage status\n" ); |
477 | rc = -ETIMEDOUT; |
478 | break; |
479 | } |
480 | |
481 | ssleep(SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS); |
482 | } |
483 | |
484 | return rc; |
485 | } |
486 | |
487 | void sis_verify_structures(void) |
488 | { |
489 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
490 | revision) != 0x0); |
491 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
492 | flags) != 0x4); |
493 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
494 | error_buffer_paddr_low) != 0x8); |
495 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
496 | error_buffer_paddr_high) != 0xc); |
497 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
498 | error_buffer_element_length) != 0x10); |
499 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
500 | error_buffer_num_elements) != 0x14); |
501 | BUILD_BUG_ON(sizeof(struct sis_base_struct) != 0x18); |
502 | } |
503 | |