diff options
author | Kevin Barnett <kevin.barnett@microsemi.com> | 2016-08-31 15:54:41 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-09-02 06:21:38 -0400 |
commit | ff6abb7383d2eec6c8c988ff661352e66f245686 (patch) | |
tree | df6501219015b5c0c70684eb0ef39ff50223ea5e | |
parent | 14bb215d09de98a8e95fa2bb1b8f35b79672c5df (diff) |
scsi: smartpqi: add kdump support
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi.h | 13 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 35 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_sis.c | 10 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_sis.h | 2 |
4 files changed, 57 insertions, 3 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index 053be6be2077..5f965adfab32 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h | |||
@@ -79,11 +79,13 @@ struct pqi_ctrl_registers { | |||
79 | __le32 sis_ctrl_to_host_doorbell; /* 9Ch */ | 79 | __le32 sis_ctrl_to_host_doorbell; /* 9Ch */ |
80 | u8 reserved3[0xa0 - (0x9c + sizeof(__le32))]; | 80 | u8 reserved3[0xa0 - (0x9c + sizeof(__le32))]; |
81 | __le32 sis_ctrl_to_host_doorbell_clear; /* A0h */ | 81 | __le32 sis_ctrl_to_host_doorbell_clear; /* A0h */ |
82 | u8 reserved4[0xbc - (0xa0 + sizeof(__le32))]; | 82 | u8 reserved4[0xb0 - (0xa0 + sizeof(__le32))]; |
83 | __le32 sis_driver_scratch; /* B0h */ | ||
84 | u8 reserved5[0xbc - (0xb0 + sizeof(__le32))]; | ||
83 | __le32 sis_firmware_status; /* BCh */ | 85 | __le32 sis_firmware_status; /* BCh */ |
84 | u8 reserved5[0x1000 - (0xbc + sizeof(__le32))]; | 86 | u8 reserved6[0x1000 - (0xbc + sizeof(__le32))]; |
85 | __le32 sis_mailbox[8]; /* 1000h */ | 87 | __le32 sis_mailbox[8]; /* 1000h */ |
86 | u8 reserved6[0x4000 - (0x1000 + (sizeof(__le32) * 8))]; | 88 | u8 reserved7[0x4000 - (0x1000 + (sizeof(__le32) * 8))]; |
87 | /* | 89 | /* |
88 | * The PQI spec states that the PQI registers should be at | 90 | * The PQI spec states that the PQI registers should be at |
89 | * offset 0 from the PCIe BAR 0. However, we can't map | 91 | * offset 0 from the PCIe BAR 0. However, we can't map |
@@ -963,6 +965,11 @@ struct pqi_ctrl_info { | |||
963 | struct semaphore lun_reset_sem; | 965 | struct semaphore lun_reset_sem; |
964 | }; | 966 | }; |
965 | 967 | ||
968 | enum pqi_ctrl_mode { | ||
969 | UNKNOWN, | ||
970 | PQI_MODE | ||
971 | }; | ||
972 | |||
966 | /* | 973 | /* |
967 | * assume worst case: SATA queue depth of 31 minus 4 internal firmware commands | 974 | * assume worst case: SATA queue depth of 31 minus 4 internal firmware commands |
968 | */ | 975 | */ |
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index dbc8b40cd8ca..43bfeaca65db 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c | |||
@@ -153,6 +153,18 @@ static inline bool pqi_is_hba_lunid(u8 *scsi3addr) | |||
153 | return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); | 153 | return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); |
154 | } | 154 | } |
155 | 155 | ||
156 | static inline enum pqi_ctrl_mode pqi_get_ctrl_mode( | ||
157 | struct pqi_ctrl_info *ctrl_info) | ||
158 | { | ||
159 | return sis_read_driver_scratch(ctrl_info); | ||
160 | } | ||
161 | |||
162 | static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info *ctrl_info, | ||
163 | enum pqi_ctrl_mode mode) | ||
164 | { | ||
165 | sis_write_driver_scratch(ctrl_info, mode); | ||
166 | } | ||
167 | |||
156 | #define PQI_RESCAN_WORK_INTERVAL (10 * HZ) | 168 | #define PQI_RESCAN_WORK_INTERVAL (10 * HZ) |
157 | 169 | ||
158 | static inline void pqi_schedule_rescan_worker(struct pqi_ctrl_info *ctrl_info) | 170 | static inline void pqi_schedule_rescan_worker(struct pqi_ctrl_info *ctrl_info) |
@@ -5266,10 +5278,30 @@ out: | |||
5266 | return rc; | 5278 | return rc; |
5267 | } | 5279 | } |
5268 | 5280 | ||
5281 | static int pqi_kdump_init(struct pqi_ctrl_info *ctrl_info) | ||
5282 | { | ||
5283 | if (!sis_is_firmware_running(ctrl_info)) | ||
5284 | return -ENXIO; | ||
5285 | |||
5286 | if (pqi_get_ctrl_mode(ctrl_info) == PQI_MODE) { | ||
5287 | sis_disable_msix(ctrl_info); | ||
5288 | if (pqi_reset(ctrl_info) == 0) | ||
5289 | sis_reenable_sis_mode(ctrl_info); | ||
5290 | } | ||
5291 | |||
5292 | return 0; | ||
5293 | } | ||
5294 | |||
5269 | static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) | 5295 | static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) |
5270 | { | 5296 | { |
5271 | int rc; | 5297 | int rc; |
5272 | 5298 | ||
5299 | if (reset_devices) { | ||
5300 | rc = pqi_kdump_init(ctrl_info); | ||
5301 | if (rc) | ||
5302 | return rc; | ||
5303 | } | ||
5304 | |||
5273 | /* | 5305 | /* |
5274 | * When the controller comes out of reset, it is always running | 5306 | * When the controller comes out of reset, it is always running |
5275 | * in legacy SIS mode. This is so that it can be compatible | 5307 | * in legacy SIS mode. This is so that it can be compatible |
@@ -5343,6 +5375,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) | |||
5343 | 5375 | ||
5344 | /* From here on, we are running in PQI mode. */ | 5376 | /* From here on, we are running in PQI mode. */ |
5345 | ctrl_info->pqi_mode_enabled = true; | 5377 | ctrl_info->pqi_mode_enabled = true; |
5378 | pqi_save_ctrl_mode(ctrl_info, PQI_MODE); | ||
5346 | 5379 | ||
5347 | rc = pqi_alloc_admin_queues(ctrl_info); | 5380 | rc = pqi_alloc_admin_queues(ctrl_info); |
5348 | if (rc) { | 5381 | if (rc) { |
@@ -5879,6 +5912,8 @@ static void __attribute__((unused)) verify_structures(void) | |||
5879 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, | 5912 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, |
5880 | sis_ctrl_to_host_doorbell_clear) != 0xa0); | 5913 | sis_ctrl_to_host_doorbell_clear) != 0xa0); |
5881 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, | 5914 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, |
5915 | sis_driver_scratch) != 0xb0); | ||
5916 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, | ||
5882 | sis_firmware_status) != 0xbc); | 5917 | sis_firmware_status) != 0xbc); |
5883 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, | 5918 | BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers, |
5884 | sis_mailbox) != 0x1000); | 5919 | sis_mailbox) != 0x1000); |
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c index 5d416a8aa462..71408f9e8f75 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.c +++ b/drivers/scsi/smartpqi/smartpqi_sis.c | |||
@@ -376,6 +376,16 @@ int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info) | |||
376 | return rc; | 376 | return rc; |
377 | } | 377 | } |
378 | 378 | ||
379 | void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value) | ||
380 | { | ||
381 | writel(value, &ctrl_info->registers->sis_driver_scratch); | ||
382 | } | ||
383 | |||
384 | u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info) | ||
385 | { | ||
386 | return readl(&ctrl_info->registers->sis_driver_scratch); | ||
387 | } | ||
388 | |||
379 | static void __attribute__((unused)) verify_structures(void) | 389 | static void __attribute__((unused)) verify_structures(void) |
380 | { | 390 | { |
381 | BUILD_BUG_ON(offsetof(struct sis_base_struct, | 391 | BUILD_BUG_ON(offsetof(struct sis_base_struct, |
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h index d2ff8d54754b..bd6e7b08338e 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.h +++ b/drivers/scsi/smartpqi/smartpqi_sis.h | |||
@@ -28,5 +28,7 @@ void sis_enable_msix(struct pqi_ctrl_info *ctrl_info); | |||
28 | void sis_disable_msix(struct pqi_ctrl_info *ctrl_info); | 28 | void sis_disable_msix(struct pqi_ctrl_info *ctrl_info); |
29 | void sis_soft_reset(struct pqi_ctrl_info *ctrl_info); | 29 | void sis_soft_reset(struct pqi_ctrl_info *ctrl_info); |
30 | int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info); | 30 | int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info); |
31 | void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value); | ||
32 | u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info); | ||
31 | 33 | ||
32 | #endif /* _SMARTPQI_SIS_H */ | 34 | #endif /* _SMARTPQI_SIS_H */ |