diff options
author | Tim Sell <Timothy.Sell@unisys.com> | 2016-03-02 03:45:04 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-03-02 06:14:07 +0300 |
commit | 12c957dc942c993853fa3f357b9071b8633ef383 (patch) | |
tree | 28f8538a28dc411739e7a2adadb8fe0554e86e8b /drivers/staging/unisys | |
parent | c732623b0bb3631d61203e1e9f87bee34b7fd169 (diff) | |
download | linux-12c957dc942c993853fa3f357b9071b8633ef383.tar.xz |
staging: unisys: visorbus: allow visorhba device to be used for kdump
This patch saves off the create_bus and create_device controlvm messages
for the visorhba device, so that they can be resurrected and used in the
kdump kernel.
After this patch, a crash dump can be generated using:
# service kdump start
# echo 1 > /proc/sys/kernel/sysrq
# echo c > /proc/sysrq-trigger
Signed-off-by: Timothy Sell <timothy.sell@unisys.com>
Signed-off-by: David Kershner <david.kershner@unisys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/unisys')
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchipset.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 166a067e8bb4..55158455c534 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -61,6 +61,7 @@ static int visorchipset_major; static int visorchipset_visorbusregwait = 1; /* default is on */ static int visorchipset_holdchipsetready; static unsigned long controlvm_payload_bytes_buffered; +static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) @@ -859,6 +860,59 @@ enum crash_obj_type { }; static void +save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ) +{ + u32 local_crash_msg_offset; + u16 local_crash_msg_count; + + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_count), + &local_crash_msg_count, sizeof(u16)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { + POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC, + local_crash_msg_count, + POSTCODE_SEVERITY_ERR); + return; + } + + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_offset), + &local_crash_msg_offset, sizeof(u32)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (typ == CRASH_BUS) { + if (visorchannel_write(controlvm_channel, + local_crash_msg_offset, + msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } else { + local_crash_msg_offset += sizeof(struct controlvm_message); + if (visorchannel_write(controlvm_channel, + local_crash_msg_offset, + msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } +} + +static void bus_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) @@ -1118,6 +1172,10 @@ bus_create(struct controlvm_message *inmsg) goto cleanup; } bus_info->visorchannel = visorchannel; + if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { + dump_vhba_bus = bus_no; + save_crash_message(inmsg, CRASH_BUS); + } POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); @@ -1254,6 +1312,10 @@ my_device_create(struct controlvm_message *inmsg) } dev_info->visorchannel = visorchannel; dev_info->channel_type_guid = cmd->create_device.data_type_uuid; + if (uuid_le_cmp(cmd->create_device.data_type_uuid, + spar_vhba_channel_protocol_uuid) == 0) + save_crash_message(inmsg, CRASH_DEV); + POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); cleanup: |