From 1ba00980f6b9151066e8ed19e4eb37e769b3ef70 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 6 Apr 2015 10:27:40 -0400 Subject: staging: unisys: fix kdump support The s-Par drivers used to be out-of-tree, so they needed a parameter to let them know we were going into a dump. This patch removes that code and uses the built-in kernel function instead. Reviewed-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/globals.h | 1 - drivers/staging/unisys/visorchipset/visorchipset_main.c | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index f76e498a36b5..36b21ec3b120 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -36,7 +36,6 @@ extern int visorchipset_serverregwait; extern int visorchipset_clientregwait; extern int visorchipset_testteardown; extern int visorchipset_disable_controlvm; -extern int visorchipset_crash_kernel; extern int visorchipset_holdchipsetready; #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index f2663d2c7530..899bf684cf00 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c #define TEST_VNIC_PHYSITF "eth0" /* physical network itf for @@ -2207,7 +2208,7 @@ visorchipset_init(void) } if (!visorchipset_disable_controlvm) { /* if booting in a crash kernel */ - if (visorchipset_crash_kernel) + if (is_kdump_kernel()) INIT_DELAYED_WORK(&periodic_controlvm_work, setup_crash_devices_work_queue); else @@ -2315,10 +2316,6 @@ module_param_named(disable_controlvm, visorchipset_disable_controlvm, int, MODULE_PARM_DESC(visorchipset_disable_controlvm, "1 to disable polling of controlVm channel"); int visorchipset_disable_controlvm = 0; /* default is off */ -module_param_named(crash_kernel, visorchipset_crash_kernel, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_crash_kernel, - "1 means we are running in crash kernel"); -int visorchipset_crash_kernel = 0; /* default is running in non-crash kernel */ module_param_named(holdchipsetready, visorchipset_holdchipsetready, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_holdchipsetready, -- cgit v1.2.3-55-g7522 From 0a22650b920fa9062e75ea51941a6249a0d16be7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:38 -0400 Subject: staging: unisys: visorchipset: Remove unused NONULLSTR() Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 899bf684cf00..6144a945629f 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -52,14 +52,6 @@ static ulong poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; static ulong most_recent_message_jiffies; /* when we got our last * controlvm message */ -static inline char * -NONULLSTR(char *s) -{ - if (s) - return s; - return ""; -} - static int serverregistered; static int clientregistered; -- cgit v1.2.3-55-g7522 From c1f834eb104d67a57ac745a36ace5e084328bda6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:39 -0400 Subject: staging: unisys: visorchipset: Avoid struct typedef abuse Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorchipset/visorchipset_main.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 6144a945629f..9e142a919982 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -92,17 +92,19 @@ static LIST_HEAD(dev_info_list); static struct visorchannel *controlvm_channel; /* Manages the request payload in the controlvm channel */ -static struct controlvm_payload_info { +struct visor_controlvm_payload_info { u8 __iomem *ptr; /* pointer to base address of payload pool */ u64 offset; /* offset from beginning of controlvm * channel to beginning of payload * pool */ u32 bytes; /* number of bytes in payload pool */ -} controlvm_payload_info; +}; + +static struct visor_controlvm_payload_info controlvm_payload_info; /* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation. */ -static struct livedump_info { +struct visor_livedump_info { struct controlvm_message_header dumpcapture_header; struct controlvm_message_header gettextdump_header; struct controlvm_message_header dumpcomplete_header; @@ -111,7 +113,9 @@ static struct livedump_info { ulong length; atomic_t buffers_in_use; ulong destination; -} livedump_info; +}; + +static struct visor_livedump_info livedump_info; /* The following globals are used to handle the scenario where we are unable to * offload the payload from a controlvm message due to memory requirements. In @@ -1263,7 +1267,7 @@ my_device_destroy(struct controlvm_message *inmsg) */ static int initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, - struct controlvm_payload_info *info) + struct visor_controlvm_payload_info *info) { u8 __iomem *payload = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1272,7 +1276,7 @@ initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; goto cleanup; } - memset(info, 0, sizeof(struct controlvm_payload_info)); + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); if ((offset == 0) || (bytes == 0)) { rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; goto cleanup; @@ -1298,13 +1302,13 @@ cleanup: } static void -destroy_controlvm_payload_info(struct controlvm_payload_info *info) +destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info) { if (info->ptr) { iounmap(info->ptr); info->ptr = NULL; } - memset(info, 0, sizeof(struct controlvm_payload_info)); + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); } static void -- cgit v1.2.3-55-g7522 From f4c11551e7109f0d3a4708a149903e4c75e962d2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:40 -0400 Subject: staging: unisys: visorchipset: Get rid of ugly BOOL/TRUE/FALSE usage Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/parser.c | 24 +++--- drivers/staging/unisys/visorchipset/parser.h | 8 +- drivers/staging/unisys/visorchipset/visorchipset.h | 10 +-- .../unisys/visorchipset/visorchipset_main.c | 98 +++++++++++----------- 4 files changed, 70 insertions(+), 70 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c index d8a2d6f5a75d..b30e4c158b41 100644 --- a/drivers/staging/unisys/visorchipset/parser.c +++ b/drivers/staging/unisys/visorchipset/parser.c @@ -36,13 +36,13 @@ struct parser_context { ulong param_bytes; u8 *curr; ulong bytes_remaining; - BOOL byte_stream; + bool byte_stream; char data[0]; }; static struct parser_context * -parser_init_guts(u64 addr, u32 bytes, BOOL local, - BOOL standard_payload_header, BOOL *retry) +parser_init_guts(u64 addr, u32 bytes, bool local, + bool standard_payload_header, bool *retry) { int allocbytes = sizeof(struct parser_context) + bytes; struct parser_context *rc = NULL; @@ -51,7 +51,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, struct spar_controlvm_parameters_header *phdr = NULL; if (retry) - *retry = FALSE; + *retry = false; if (!standard_payload_header) /* alloc and 0 extra byte to ensure payload is * '\0'-terminated @@ -60,14 +60,14 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, if ((controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) - *retry = TRUE; + *retry = true; rc = NULL; goto cleanup; } ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); if (!ctx) { if (retry) - *retry = TRUE; + *retry = true; rc = NULL; goto cleanup; } @@ -76,7 +76,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, ctx->param_bytes = bytes; ctx->curr = NULL; ctx->bytes_remaining = 0; - ctx->byte_stream = FALSE; + ctx->byte_stream = false; if (local) { void *p; @@ -98,7 +98,7 @@ parser_init_guts(u64 addr, u32 bytes, BOOL local, } } if (!standard_payload_header) { - ctx->byte_stream = TRUE; + ctx->byte_stream = true; rc = ctx; goto cleanup; } @@ -135,9 +135,9 @@ cleanup: } struct parser_context * -parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry) +parser_init(u64 addr, u32 bytes, bool local, bool *retry) { - return parser_init_guts(addr, bytes, local, TRUE, retry); + return parser_init_guts(addr, bytes, local, true, retry); } /* Call this instead of parser_init() if the payload area consists of just @@ -146,9 +146,9 @@ parser_init(u64 addr, u32 bytes, BOOL local, BOOL *retry) * parser_byteStream_get() to obtain the data. */ struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, BOOL *retry) +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) { - return parser_init_guts(addr, bytes, local, FALSE, retry); + return parser_init_guts(addr, bytes, local, false, retry); } /* Obtain '\0'-terminated copy of string in payload area. diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h index 2b903f1beff2..d3b0b33348b3 100644 --- a/drivers/staging/unisys/visorchipset/parser.h +++ b/drivers/staging/unisys/visorchipset/parser.h @@ -30,10 +30,10 @@ typedef enum { PARSERSTRING_NAME, } PARSER_WHICH_STRING; -struct parser_context *parser_init(u64 addr, u32 bytes, BOOL isLocal, - BOOL *tryAgain); -struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, BOOL local, - BOOL *retry); +struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, + bool *tryAgain); +struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, + bool *retry); void parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string); void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index bd46df9ef45a..4c1a74f6a5b8 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -217,19 +217,19 @@ typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (struct controlvm_message *msg, void visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response); -BOOL visorchipset_get_bus_info(ulong bus_no, +bool visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info); -BOOL visorchipset_get_device_info(ulong bus_no, ulong dev_no, +bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, struct visorchipset_device_info *dev_info); -BOOL visorchipset_set_bus_context(ulong bus_no, void *context); -BOOL visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); +bool visorchipset_set_bus_context(ulong bus_no, void *context); +bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); int visorchipset_chipset_ready(void); int visorchipset_chipset_selftest(void); int visorchipset_chipset_notready(void); void visorchipset_save_message(struct controlvm_message *msg, enum crash_obj_type type); void *visorchipset_cache_alloc(struct kmem_cache *pool, - BOOL ok_to_block, char *fn, int ln); + bool ok_to_block, char *fn, int ln); void visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 9e142a919982..8e7885452a72 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -108,7 +108,7 @@ struct visor_livedump_info { struct controlvm_message_header dumpcapture_header; struct controlvm_message_header gettextdump_header; struct controlvm_message_header dumpcomplete_header; - BOOL gettextdump_outstanding; + bool gettextdump_outstanding; u32 crc32; ulong length; atomic_t buffers_in_use; @@ -123,7 +123,7 @@ static struct visor_livedump_info livedump_info; * process it again the next time controlvm_periodic_work() runs. */ static struct controlvm_message controlvm_pending_msg; -static BOOL controlvm_pending_msg_valid = FALSE; +static bool controlvm_pending_msg_valid = false; /* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming) * TRANSMIT_FILE PutFile payloads. @@ -776,7 +776,7 @@ static void bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) { struct visorchipset_bus_info *p = NULL; - BOOL need_clear = FALSE; + bool need_clear = false; p = findbus(&bus_info_list, bus_no); if (!p) @@ -791,7 +791,7 @@ bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) if (cmd_id == CONTROLVM_BUS_CREATE) p->state.created = 1; if (cmd_id == CONTROLVM_BUS_DESTROY) - need_clear = TRUE; + need_clear = true; } if (p->pending_msg_hdr.id == CONTROLVM_INVALID) @@ -840,7 +840,7 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, int response) { struct visorchipset_device_info *p = NULL; - BOOL need_clear = FALSE; + bool need_clear = false; p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) @@ -849,7 +849,7 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, if (cmd_id == CONTROLVM_DEVICE_CREATE) p->state.created = 1; if (cmd_id == CONTROLVM_DEVICE_DESTROY) - need_clear = TRUE; + need_clear = true; } if (p->pending_msg_hdr.id == CONTROLVM_INVALID) @@ -867,9 +867,9 @@ device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, static void bus_epilog(u32 bus_no, u32 cmd, struct controlvm_message_header *msg_hdr, - int response, BOOL need_response) + int response, bool need_response) { - BOOL notified = FALSE; + bool notified = false; struct visorchipset_bus_info *bus_info = findbus(&bus_info_list, bus_no); @@ -900,23 +900,23 @@ bus_epilog(u32 bus_no, * devices */ if (busdev_server_notifiers.bus_create) { (*busdev_server_notifiers.bus_create) (bus_no); - notified = TRUE; + notified = true; } if ((!bus_info->flags.server) /*client */ && busdev_client_notifiers.bus_create) { (*busdev_client_notifiers.bus_create) (bus_no); - notified = TRUE; + notified = true; } break; case CONTROLVM_BUS_DESTROY: if (busdev_server_notifiers.bus_destroy) { (*busdev_server_notifiers.bus_destroy) (bus_no); - notified = TRUE; + notified = true; } if ((!bus_info->flags.server) /*client */ && busdev_client_notifiers.bus_destroy) { (*busdev_client_notifiers.bus_destroy) (bus_no); - notified = TRUE; + notified = true; } break; } @@ -935,10 +935,10 @@ bus_epilog(u32 bus_no, static void device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, struct controlvm_message_header *msg_hdr, int response, - BOOL need_response, BOOL for_visorbus) + bool need_response, bool for_visorbus) { struct visorchipset_busdev_notifiers *notifiers = NULL; - BOOL notified = FALSE; + bool notified = false; struct visorchipset_device_info *dev_info = finddevice(&dev_info_list, bus_no, dev_no); @@ -967,7 +967,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, case CONTROLVM_DEVICE_CREATE: if (notifiers->device_create) { (*notifiers->device_create) (bus_no, dev_no); - notified = TRUE; + notified = true; } break; case CONTROLVM_DEVICE_CHANGESTATE: @@ -978,7 +978,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, if (notifiers->device_resume) { (*notifiers->device_resume) (bus_no, dev_no); - notified = TRUE; + notified = true; } } /* ServerNotReady / ServerLost / SegmentStateStandby */ @@ -991,7 +991,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, if (notifiers->device_pause) { (*notifiers->device_pause) (bus_no, dev_no); - notified = TRUE; + notified = true; } } else if (state.alive == segment_state_paused.alive && state.operating == @@ -1013,7 +1013,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, case CONTROLVM_DEVICE_DESTROY: if (notifiers->device_destroy) { (*notifiers->device_destroy) (bus_no, dev_no); - notified = TRUE; + notified = true; } break; } @@ -1262,7 +1262,7 @@ my_device_destroy(struct controlvm_message *inmsg) /* When provided with the physical address of the controlvm channel * (phys_addr), the offset to the payload area we need to manage * (offset), and the size of this payload area (bytes), fills in the - * controlvm_payload_info struct. Returns TRUE for success or FALSE + * controlvm_payload_info struct. Returns true for success or false * for failure. */ static int @@ -1416,17 +1416,17 @@ chipset_notready(struct controlvm_message_header *msg_hdr) /* This is your "one-stop" shop for grabbing the next message from the * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. */ -static BOOL +static bool read_controlvm_event(struct controlvm_message *msg) { if (visorchannel_signalremove(controlvm_channel, CONTROLVM_QUEUE_EVENT, msg)) { /* got a message */ if (msg->hdr.flags.test_message == 1) - return FALSE; - return TRUE; + return false; + return true; } - return FALSE; + return false; } /* @@ -1637,16 +1637,16 @@ parahotplug_process_message(struct controlvm_message *inmsg) /* Process a controlvm message. * Return result: - * FALSE - this function will return FALSE only in the case where the + * false - this function will return FALSE only in the case where the * controlvm message was NOT processed, but processing must be * retried before reading the next controlvm message; a * scenario where this can occur is when we need to throttle * the allocation of memory in which to copy out controlvm * payload data - * TRUE - processing of the controlvm message completed, + * true - processing of the controlvm message completed, * either successfully or with an error. */ -static BOOL +static bool handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) { struct controlvm_message_packet *cmd = &inmsg.cmd; @@ -1659,7 +1659,7 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) /* create parsing context if necessary */ local_addr = (inmsg.hdr.flags.test_message == 1); if (channel_addr == 0) - return TRUE; + return true; parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_bytes = inmsg.hdr.payload_bytes; @@ -1668,13 +1668,13 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) * makes a difference in how we compute the virtual address. */ if (parm_addr != 0 && parm_bytes != 0) { - BOOL retry = FALSE; + bool retry = false; parser_ctx = parser_init_byte_stream(parm_addr, parm_bytes, local_addr, &retry); if (!parser_ctx && retry) - return FALSE; + return false; } if (!local_addr) { @@ -1741,7 +1741,7 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) parser_done(parser_ctx); parser_ctx = NULL; } - return TRUE; + return true; } static HOSTADDRESS controlvm_get_channel_address(void) @@ -1759,8 +1759,8 @@ static void controlvm_periodic_work(struct work_struct *work) { struct controlvm_message inmsg; - BOOL got_command = FALSE; - BOOL handle_command_failed = FALSE; + bool got_command = false; + bool handle_command_failed = false; static u64 poll_count; /* make sure visorbus server is registered for controlvm callbacks */ @@ -1802,14 +1802,14 @@ controlvm_periodic_work(struct work_struct *work) * rather than reading a new one */ inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = FALSE; + controlvm_pending_msg_valid = false; got_command = true; } else { got_command = read_controlvm_event(&inmsg); } } - handle_command_failed = FALSE; + handle_command_failed = false; while (got_command && (!handle_command_failed)) { most_recent_message_jiffies = jiffies; if (handle_command(inmsg, @@ -1823,9 +1823,9 @@ controlvm_periodic_work(struct work_struct *work) * controlvm msg so we will attempt to * reprocess it on our next loop */ - handle_command_failed = TRUE; + handle_command_failed = true; controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = TRUE; + controlvm_pending_msg_valid = true; } } @@ -1996,60 +1996,60 @@ device_resume_response(ulong bus_no, ulong dev_no, int response) segment_state_running); } -BOOL +bool visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) { void *p = findbus(&bus_info_list, bus_no); if (!p) - return FALSE; + return false; memcpy(bus_info, p, sizeof(struct visorchipset_bus_info)); - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); -BOOL +bool visorchipset_set_bus_context(ulong bus_no, void *context) { struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no); if (!p) - return FALSE; + return false; p->bus_driver_context = context; - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); -BOOL +bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, struct visorchipset_device_info *dev_info) { void *p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) - return FALSE; + return false; memcpy(dev_info, p, sizeof(struct visorchipset_device_info)); - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_get_device_info); -BOOL +bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context) { struct visorchipset_device_info *p = finddevice(&dev_info_list, bus_no, dev_no); if (!p) - return FALSE; + return false; p->bus_driver_context = context; - return TRUE; + return true; } EXPORT_SYMBOL_GPL(visorchipset_set_device_context); /* Generic wrapper function for allocating memory from a kmem_cache pool. */ void * -visorchipset_cache_alloc(struct kmem_cache *pool, BOOL ok_to_block, +visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, char *fn, int ln) { gfp_t gfp; -- cgit v1.2.3-55-g7522 From 52063eca7fd04cb4e8a5b8f0d4f99c5e8816d59e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:41 -0400 Subject: staging: unisys: visorchipset: Do not use confuse size of long with size of u32 struct visorcipset_device_info defines bus_no and dev_no as u32, while the deprecated ulong type is 64 bits. Hence avoid promoting the values to 64 bit just to truncate them again later. Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 35 ++++++----- .../unisys/visorchipset/visorchipset_main.c | 67 +++++++++++----------- 2 files changed, 50 insertions(+), 52 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 4c1a74f6a5b8..3a8aa5614b4b 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -162,12 +162,12 @@ findbus(struct list_head *list, u32 bus_no) * visorchipset.) */ struct visorchipset_busdev_notifiers { - void (*bus_create)(ulong bus_no); - void (*bus_destroy)(ulong bus_no); - void (*device_create)(ulong bus_no, ulong dev_no); - void (*device_destroy)(ulong bus_no, ulong dev_no); - void (*device_pause)(ulong bus_no, ulong dev_no); - void (*device_resume)(ulong bus_no, ulong dev_no); + void (*bus_create)(u32 bus_no); + void (*bus_destroy)(u32 bus_no); + void (*device_create)(u32 bus_no, u32 dev_no); + void (*device_destroy)(u32 bus_no, u32 dev_no); + void (*device_pause)(u32 bus_no, u32 dev_no); + void (*device_resume)(u32 bus_no, u32 dev_no); int (*get_channel_info)(uuid_le type_uuid, ulong *min_size, ulong *max_size); }; @@ -179,12 +179,12 @@ struct visorchipset_busdev_notifiers { * -1 = it failed */ struct visorchipset_busdev_responders { - void (*bus_create)(ulong bus_no, int response); - void (*bus_destroy)(ulong bus_no, int response); - void (*device_create)(ulong bus_no, ulong dev_no, int response); - void (*device_destroy)(ulong bus_no, ulong dev_no, int response); - void (*device_pause)(ulong bus_no, ulong dev_no, int response); - void (*device_resume)(ulong bus_no, ulong dev_no, int response); + void (*bus_create)(u32 bus_no, int response); + void (*bus_destroy)(u32 bus_no, int response); + void (*device_create)(u32 bus_no, u32 dev_no, int response); + void (*device_destroy)(u32 bus_no, u32 dev_no, int response); + void (*device_pause)(u32 bus_no, u32 dev_no, int response); + void (*device_resume)(u32 bus_no, u32 dev_no, int response); }; /** Register functions (in the bus driver) to get called by visorchipset @@ -214,15 +214,14 @@ visorchipset_register_busdev_server( typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (struct controlvm_message *msg, int status); -void visorchipset_device_pause_response(ulong bus_no, ulong dev_no, - int response); +void visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response); -bool visorchipset_get_bus_info(ulong bus_no, +bool visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info); -bool visorchipset_get_device_info(ulong bus_no, ulong dev_no, +bool visorchipset_get_device_info(u32 bus_no, u32 dev_no, struct visorchipset_device_info *dev_info); -bool visorchipset_set_bus_context(ulong bus_no, void *context); -bool visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context); +bool visorchipset_set_bus_context(u32 bus_no, void *context); +bool visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context); int visorchipset_chipset_ready(void); int visorchipset_chipset_selftest(void); int visorchipset_chipset_notready(void); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 8e7885452a72..90e41cb64597 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -49,8 +49,8 @@ * message, we switch back to fast polling mode. */ #define MIN_IDLE_SECONDS 10 -static ulong poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -static ulong most_recent_message_jiffies; /* when we got our last +static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; +static unsigned long most_recent_message_jiffies; /* when we got our last * controlvm message */ static int serverregistered; static int clientregistered; @@ -68,8 +68,8 @@ static struct controlvm_message_header g_del_dump_msg_hdr; static const uuid_le spar_diag_pool_channel_protocol_uuid = SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; /* 0xffffff is an invalid Bus/Device number */ -static ulong g_diagpool_bus_no = 0xffffff; -static ulong g_diagpool_dev_no = 0xffffff; +static u32 g_diagpool_bus_no = 0xffffff; +static u32 g_diagpool_dev_no = 0xffffff; static struct controlvm_message_packet g_devicechangestate_packet; /* Only VNIC and VHBA channels are sent to visorclientbus (aka @@ -110,9 +110,9 @@ struct visor_livedump_info { struct controlvm_message_header dumpcomplete_header; bool gettextdump_outstanding; u32 crc32; - ulong length; + unsigned long length; atomic_t buffers_in_use; - ulong destination; + unsigned long destination; }; static struct visor_livedump_info livedump_info; @@ -219,11 +219,11 @@ static void parahotplug_process_list(void); static struct visorchipset_busdev_notifiers busdev_server_notifiers; static struct visorchipset_busdev_notifiers busdev_client_notifiers; -static void bus_create_response(ulong bus_no, int response); -static void bus_destroy_response(ulong bus_no, int response); -static void device_create_response(ulong bus_no, ulong dev_no, int response); -static void device_destroy_response(ulong bus_no, ulong dev_no, int response); -static void device_resume_response(ulong bus_no, ulong dev_no, int response); +static void bus_create_response(u32 bus_no, int response); +static void bus_destroy_response(u32 bus_no, int response); +static void device_create_response(u32 bus_no, u32 dev_no, int response); +static void device_destroy_response(u32 bus_no, u32 dev_no, int response); +static void device_resume_response(u32 bus_no, u32 dev_no, int response); static struct visorchipset_busdev_responders busdev_responders = { .bus_create = bus_create_response, @@ -773,7 +773,7 @@ visorchipset_save_message(struct controlvm_message *msg, EXPORT_SYMBOL_GPL(visorchipset_save_message); static void -bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) +bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) { struct visorchipset_bus_info *p = NULL; bool need_clear = false; @@ -808,7 +808,7 @@ bus_responder(enum controlvm_id cmd_id, ulong bus_no, int response) static void device_changestate_responder(enum controlvm_id cmd_id, - ulong bus_no, ulong dev_no, int response, + u32 bus_no, u32 dev_no, int response, struct spar_segment_state response_state) { struct visorchipset_device_info *p = NULL; @@ -836,8 +836,7 @@ device_changestate_responder(enum controlvm_id cmd_id, } static void -device_responder(enum controlvm_id cmd_id, ulong bus_no, ulong dev_no, - int response) +device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) { struct visorchipset_device_info *p = NULL; bool need_clear = false; @@ -1033,7 +1032,7 @@ static void bus_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->create_bus.bus_no; + u32 bus_no = cmd->create_bus.bus_no; int rc = CONTROLVM_RESP_SUCCESS; struct visorchipset_bus_info *bus_info = NULL; @@ -1083,7 +1082,7 @@ static void bus_destroy(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->destroy_bus.bus_no; + u32 bus_no = cmd->destroy_bus.bus_no; struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; @@ -1102,7 +1101,7 @@ bus_configure(struct controlvm_message *inmsg, struct parser_context *parser_ctx) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->configure_bus.bus_no; + u32 bus_no = cmd->configure_bus.bus_no; struct visorchipset_bus_info *bus_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; char s[99]; @@ -1142,8 +1141,8 @@ static void my_device_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->create_device.bus_no; - ulong dev_no = cmd->create_device.dev_no; + u32 bus_no = cmd->create_device.bus_no; + u32 dev_no = cmd->create_device.dev_no; struct visorchipset_device_info *dev_info = NULL; struct visorchipset_bus_info *bus_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1212,8 +1211,8 @@ static void my_device_changestate(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->device_change_state.bus_no; - ulong dev_no = cmd->device_change_state.dev_no; + u32 bus_no = cmd->device_change_state.bus_no; + u32 dev_no = cmd->device_change_state.dev_no; struct spar_segment_state state = cmd->device_change_state.state; struct visorchipset_device_info *dev_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1240,8 +1239,8 @@ static void my_device_destroy(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - ulong bus_no = cmd->destroy_device.bus_no; - ulong dev_no = cmd->destroy_device.dev_no; + u32 bus_no = cmd->destroy_device.bus_no; + u32 dev_no = cmd->destroy_device.dev_no; struct visorchipset_device_info *dev_info = NULL; int rc = CONTROLVM_RESP_SUCCESS; @@ -1956,31 +1955,31 @@ cleanup: } static void -bus_create_response(ulong bus_no, int response) +bus_create_response(u32 bus_no, int response) { bus_responder(CONTROLVM_BUS_CREATE, bus_no, response); } static void -bus_destroy_response(ulong bus_no, int response) +bus_destroy_response(u32 bus_no, int response) { bus_responder(CONTROLVM_BUS_DESTROY, bus_no, response); } static void -device_create_response(ulong bus_no, ulong dev_no, int response) +device_create_response(u32 bus_no, u32 dev_no, int response) { device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response); } static void -device_destroy_response(ulong bus_no, ulong dev_no, int response) +device_destroy_response(u32 bus_no, u32 dev_no, int response) { device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response); } void -visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response) +visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, bus_no, dev_no, response, @@ -1989,7 +1988,7 @@ visorchipset_device_pause_response(ulong bus_no, ulong dev_no, int response) EXPORT_SYMBOL_GPL(visorchipset_device_pause_response); static void -device_resume_response(ulong bus_no, ulong dev_no, int response) +device_resume_response(u32 bus_no, u32 dev_no, int response) { device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, bus_no, dev_no, response, @@ -1997,7 +1996,7 @@ device_resume_response(ulong bus_no, ulong dev_no, int response) } bool -visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) +visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info) { void *p = findbus(&bus_info_list, bus_no); @@ -2009,7 +2008,7 @@ visorchipset_get_bus_info(ulong bus_no, struct visorchipset_bus_info *bus_info) EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); bool -visorchipset_set_bus_context(ulong bus_no, void *context) +visorchipset_set_bus_context(u32 bus_no, void *context) { struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no); @@ -2021,7 +2020,7 @@ visorchipset_set_bus_context(ulong bus_no, void *context) EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); bool -visorchipset_get_device_info(ulong bus_no, ulong dev_no, +visorchipset_get_device_info(u32 bus_no, u32 dev_no, struct visorchipset_device_info *dev_info) { void *p = finddevice(&dev_info_list, bus_no, dev_no); @@ -2034,7 +2033,7 @@ visorchipset_get_device_info(ulong bus_no, ulong dev_no, EXPORT_SYMBOL_GPL(visorchipset_get_device_info); bool -visorchipset_set_device_context(ulong bus_no, ulong dev_no, void *context) +visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context) { struct visorchipset_device_info *p = finddevice(&dev_info_list, bus_no, dev_no); -- cgit v1.2.3-55-g7522 From a6e7fe5c042c171d912783a8bf0918b7f68aefe4 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:42 -0400 Subject: staging: unisys: visorchipset: Use correct type for dev_no visorchipset_bus_info.dev_no is only assigned the value of controlvm_message_packet.create_bus.dev_count, which is a u32. No point promoting it to a u64. Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 3a8aa5614b4b..3848de253371 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -141,8 +141,7 @@ struct visorchipset_bus_info { struct controlvm_message_header pending_msg_hdr;/* CONTROLVM MsgHdr */ /** For private use by the bus driver */ void *bus_driver_context; - u64 dev_no; - + u32 dev_no; }; static inline struct visorchipset_bus_info * -- cgit v1.2.3-55-g7522 From ac48c05c678e9917b9f3e9b6e1792675a6a1d672 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:43 -0400 Subject: staging: unisys: visorchipset: Remove unused get_channel_info notifier Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 3848de253371..87b63f0dc36a 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -167,8 +167,6 @@ struct visorchipset_busdev_notifiers { void (*device_destroy)(u32 bus_no, u32 dev_no); void (*device_pause)(u32 bus_no, u32 dev_no); void (*device_resume)(u32 bus_no, u32 dev_no); - int (*get_channel_info)(uuid_le type_uuid, ulong *min_size, - ulong *max_size); }; /* These functions live inside visorchipset, and will be called to indicate -- cgit v1.2.3-55-g7522 From 1d4c1afac4c46723475ec8e10ff7eed3c439393c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Apr 2015 10:28:44 -0400 Subject: staging: unisys: visorchipset: Get rid of ulong usage Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 6 +++--- drivers/staging/unisys/visorchipset/parser.c | 16 ++++++++-------- drivers/staging/unisys/visorchipset/parser.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 203de0b5f607..6fc56896e427 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -60,8 +60,8 @@ visorchipset_release(struct inode *inode, struct file *file) static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { - ulong physaddr = 0; - ulong offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long physaddr = 0; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; GUEST_PHYSICAL_ADDRESS addr = 0; /* sv_enable_dfp(); */ @@ -81,7 +81,7 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) if (addr == 0) { return -ENXIO; } - physaddr = (ulong)addr; + physaddr = (unsigned long)addr; if (remap_pfn_range(vma, vma->vm_start, physaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c index b30e4c158b41..6ca6da8772a8 100644 --- a/drivers/staging/unisys/visorchipset/parser.c +++ b/drivers/staging/unisys/visorchipset/parser.c @@ -29,13 +29,13 @@ * incoming payloads. This serves as a throttling mechanism. */ #define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) -static ulong controlvm_payload_bytes_buffered; +static unsigned long controlvm_payload_bytes_buffered; struct parser_context { - ulong allocbytes; - ulong param_bytes; + unsigned long allocbytes; + unsigned long param_bytes; u8 *curr; - ulong bytes_remaining; + unsigned long bytes_remaining; bool byte_stream; char data[0]; }; @@ -84,7 +84,7 @@ parser_init_guts(u64 addr, u32 bytes, bool local, rc = NULL; goto cleanup; } - p = __va((ulong) (addr)); + p = __va((unsigned long) (addr)); memcpy(ctx->data, p, bytes); } else { rgn = visor_memregion_create(addr, bytes); @@ -165,7 +165,7 @@ parser_simpleString_get(struct parser_context *ctx) /* Obtain a copy of the buffer in the payload area. */ -void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes) +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) { if (!ctx->byte_stream) return NULL; @@ -265,7 +265,7 @@ void * parser_param_get(struct parser_context *ctx, char *nam, int namesize) { u8 *pscan, *pnam = nam; - ulong nscan; + unsigned long nscan; int value_length = -1, orig_value_length = -1; void *value = NULL; int i; @@ -400,7 +400,7 @@ void * parser_string_get(struct parser_context *ctx) { u8 *pscan; - ulong nscan; + unsigned long nscan; int value_length = -1; void *value = NULL; int i; diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h index d3b0b33348b3..73be279bb401 100644 --- a/drivers/staging/unisys/visorchipset/parser.h +++ b/drivers/staging/unisys/visorchipset/parser.h @@ -40,7 +40,7 @@ void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); void *parser_string_get(struct parser_context *ctx); uuid_le parser_id_get(struct parser_context *ctx); char *parser_simpleString_get(struct parser_context *ctx); -void *parser_byte_stream_get(struct parser_context *ctx, ulong *nbytes); +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); void parser_done(struct parser_context *ctx); #endif -- cgit v1.2.3-55-g7522 From b615d628b672c90b377c4167429c0c3b66621ba6 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:38 -0400 Subject: staging: unisys: Move module parameters around and mark static Move the module parameters and make sure they are static. Signed-off-by: Jes Sorensen Tested-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/globals.h | 10 ------- .../unisys/visorchipset/visorchipset_main.c | 31 +++++++++++----------- 2 files changed, 16 insertions(+), 25 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index 36b21ec3b120..0884a68f23cd 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -28,14 +28,4 @@ /* module parameters */ -extern int visorchipset_testvnic; -extern int visorchipset_testvnicclient; -extern int visorchipset_testmsg; -extern int visorchipset_major; -extern int visorchipset_serverregwait; -extern int visorchipset_clientregwait; -extern int visorchipset_testteardown; -extern int visorchipset_disable_controlvm; -extern int visorchipset_holdchipsetready; - #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 90e41cb64597..7720d2c5b0ad 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -44,6 +44,19 @@ #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 +/* + * Module parameters + */ +static int visorchipset_testvnic; +static int visorchipset_testvnicclient; +static int visorchipset_testmsg; +static int visorchipset_major; +static int visorchipset_serverregwait; +static int visorchipset_clientregwait = 1; /* default is on */ +static int visorchipset_testteardown; +static int visorchipset_disable_controlvm; +static int visorchipset_holdchipsetready; + /* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, * we switch to slow polling mode. As soon as we get a controlvm * message, we switch back to fast polling mode. @@ -2280,43 +2293,31 @@ visorchipset_exit(void) module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_testvnic, "1 to test vnic, using dummy VNIC connected via a loopback to a physical ethernet"); -int visorchipset_testvnic = 0; - module_param_named(testvnicclient, visorchipset_testvnicclient, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_testvnicclient, "1 to test vnic, using real VNIC channel attached to a separate IOVM guest"); -int visorchipset_testvnicclient = 0; - module_param_named(testmsg, visorchipset_testmsg, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_testmsg, "1 to manufacture the chipset, bus, and switch messages"); -int visorchipset_testmsg = 0; - module_param_named(major, visorchipset_major, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node"); -int visorchipset_major = 0; - +MODULE_PARM_DESC(visorchipset_major, + "major device number to use for the device node"); module_param_named(serverregwait, visorchipset_serverregwait, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_serverreqwait, "1 to have the module wait for the visor bus to register"); -int visorchipset_serverregwait = 0; /* default is off */ module_param_named(clientregwait, visorchipset_clientregwait, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_clientregwait, "1 to have the module wait for the visorclientbus to register"); -int visorchipset_clientregwait = 1; /* default is on */ module_param_named(testteardown, visorchipset_testteardown, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_testteardown, "1 to test teardown of the chipset, bus, and switch"); -int visorchipset_testteardown = 0; /* default is off */ module_param_named(disable_controlvm, visorchipset_disable_controlvm, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_disable_controlvm, "1 to disable polling of controlVm channel"); -int visorchipset_disable_controlvm = 0; /* default is off */ module_param_named(holdchipsetready, visorchipset_holdchipsetready, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_holdchipsetready, "1 to hold response to CHIPSET_READY"); -int visorchipset_holdchipsetready = 0; /* default is to send CHIPSET_READY - * response immediately */ + module_init(visorchipset_init); module_exit(visorchipset_exit); -- cgit v1.2.3-55-g7522 From 872a5032b28e5d1d420b487104adb84f9406653d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:39 -0400 Subject: staging: unisys: Move MYDRVNAME to visorchipset.h Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/globals.h | 2 -- drivers/staging/unisys/visorchipset/visorchipset.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index 0884a68f23cd..ee7e3b49e516 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -24,8 +24,6 @@ #include "visorchipset_umode.h" #include "version.h" -#define MYDRVNAME "visorchipset" - /* module parameters */ #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 87b63f0dc36a..2c2d3fb47dc3 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -28,6 +28,8 @@ #include "vbusdeviceinfo.h" #include "vbushelper.h" +#define MYDRVNAME "visorchipset" + /** Describes the state from the perspective of which controlvm messages have * been received for a bus or device. */ -- cgit v1.2.3-55-g7522 From 7023638c46b6d1b819b97e397559d10c1d4fcf6f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:40 -0400 Subject: staging: unisys: Eliminate globals.h Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 6 +++-- drivers/staging/unisys/visorchipset/file.h | 2 -- drivers/staging/unisys/visorchipset/globals.h | 29 ---------------------- .../unisys/visorchipset/visorchipset_main.c | 2 +- 4 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/globals.h (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 6fc56896e427..7d8247a46572 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -19,10 +19,12 @@ * communicate with the visorchipset driver using a device/file interface. */ -#include "globals.h" -#include "visorchannel.h" #include #include +#include "version.h" +#include "visorchipset.h" +#include "visorchipset_umode.h" +#include "visorchannel.h" #include "uisutils.h" #include "file.h" diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h index 51f7699b744b..6ff28a1ae86e 100644 --- a/drivers/staging/unisys/visorchipset/file.h +++ b/drivers/staging/unisys/visorchipset/file.h @@ -18,8 +18,6 @@ #ifndef __FILE_H__ #define __FILE_H__ -#include "globals.h" - int visorchipset_file_init(dev_t majorDev, struct visorchannel **pControlVm_channel); void visorchipset_file_cleanup(dev_t major_dev); diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h deleted file mode 100644 index ee7e3b49e516..000000000000 --- a/drivers/staging/unisys/visorchipset/globals.h +++ /dev/null @@ -1,29 +0,0 @@ -/* globals.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHIPSET_GLOBALS_H__ -#define __VISORCHIPSET_GLOBALS_H__ - -#include "diagnostics/appos_subsystems.h" -#include "timskmod.h" -#include "visorchipset.h" -#include "visorchipset_umode.h" -#include "version.h" - -/* module parameters */ - -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 7720d2c5b0ad..767c4953bfb9 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -15,7 +15,7 @@ * details. */ -#include "globals.h" +#include "version.h" #include "visorchipset.h" #include "procobjecttree.h" #include "visorchannel.h" -- cgit v1.2.3-55-g7522 From 5981cc995767803d19e9fe01aa82a0da51fc6c67 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:41 -0400 Subject: staging: unisys: Fix up a few cases of bad formatting Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 7d8247a46572..e63ef2a3a4a9 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -99,7 +99,7 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) } static long visorchipset_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) + unsigned long arg) { s64 adjustment; s64 vrtc_offset; @@ -108,14 +108,14 @@ static long visorchipset_ioctl(struct file *file, unsigned int cmd, case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: /* get the physical rtc offset */ vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); - if (copy_to_user - ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) { + if (copy_to_user((void __user *)arg, &vrtc_offset, + sizeof(vrtc_offset))) { return -EFAULT; } return SUCCESS; case VMCALL_UPDATE_PHYSICAL_TIME: - if (copy_from_user - (&adjustment, (void __user *)arg, sizeof(adjustment))) { + if (copy_from_user(&adjustment, (void __user *)arg, + sizeof(adjustment))) { return -EFAULT; } return issue_vmcall_update_physical_time(adjustment); -- cgit v1.2.3-55-g7522 From b70b9099f06d5ab68cdbe12b6d150f0d7303becf Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:42 -0400 Subject: staging: unisys: Remove some unnecessary parenthesis Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_umode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h index 6cf6eccb3f4a..8af5bf33883c 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_umode.h +++ b/drivers/staging/unisys/visorchipset/visorchipset_umode.h @@ -29,7 +29,7 @@ /** The user-mode program can access the control channel buffer directly * via this memory map. */ -#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET (0x00000000) -#define VISORCHIPSET_MMAP_CONTROLCHANSIZE (0x00400000) /* 4MB */ +#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 +#define VISORCHIPSET_MMAP_CONTROLCHANSIZE 0x00400000 /* 4MB */ #endif /* __VISORCHIPSET_UMODE_H */ -- cgit v1.2.3-55-g7522 From bbd4be301c48adb763eda9631808e316157d6417 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:43 -0400 Subject: staging: unisys: Remove unncessary parenthesis Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 767c4953bfb9..b4e28d21d0c6 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -519,7 +519,7 @@ static ssize_t remaining_steps_store(struct device *dev, static void bus_info_clear(void *v) { - struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) (v); + struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) v; kfree(p->name); p->name = NULL; @@ -535,7 +535,7 @@ static void dev_info_clear(void *v) { struct visorchipset_device_info *p = - (struct visorchipset_device_info *)(v); + (struct visorchipset_device_info *) v; p->state.created = 0; memset(p, 0, sizeof(struct visorchipset_device_info)); -- cgit v1.2.3-55-g7522 From cbc2af3cb5667ff1576b9bf237082f25503a3b8b Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:44 -0400 Subject: staging: unisys: Don't zero struct elements which will be memset away Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index b4e28d21d0c6..90018ac3da36 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -522,12 +522,7 @@ bus_info_clear(void *v) struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) v; kfree(p->name); - p->name = NULL; - kfree(p->description); - p->description = NULL; - - p->state.created = 0; memset(p, 0, sizeof(struct visorchipset_bus_info)); } @@ -537,7 +532,6 @@ dev_info_clear(void *v) struct visorchipset_device_info *p = (struct visorchipset_device_info *) v; - p->state.created = 0; memset(p, 0, sizeof(struct visorchipset_device_info)); } -- cgit v1.2.3-55-g7522 From e82ba62e23bc9d9e57b19fa1a5bdf18fab9a218e Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:45 -0400 Subject: staging: unisys: Do not initialize variables unnecessarily Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../unisys/visorchipset/visorchipset_main.c | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 90018ac3da36..0d3abce9074a 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -782,7 +782,7 @@ EXPORT_SYMBOL_GPL(visorchipset_save_message); static void bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) { - struct visorchipset_bus_info *p = NULL; + struct visorchipset_bus_info *p; bool need_clear = false; p = findbus(&bus_info_list, bus_no); @@ -818,7 +818,7 @@ device_changestate_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response, struct spar_segment_state response_state) { - struct visorchipset_device_info *p = NULL; + struct visorchipset_device_info *p; struct controlvm_message outmsg; p = finddevice(&dev_info_list, bus_no, dev_no); @@ -845,7 +845,7 @@ device_changestate_responder(enum controlvm_id cmd_id, static void device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) { - struct visorchipset_device_info *p = NULL; + struct visorchipset_device_info *p; bool need_clear = false; p = finddevice(&dev_info_list, bus_no, dev_no); @@ -943,7 +943,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, struct controlvm_message_header *msg_hdr, int response, bool need_response, bool for_visorbus) { - struct visorchipset_busdev_notifiers *notifiers = NULL; + struct visorchipset_busdev_notifiers *notifiers; bool notified = false; struct visorchipset_device_info *dev_info = @@ -1041,7 +1041,7 @@ bus_create(struct controlvm_message *inmsg) struct controlvm_message_packet *cmd = &inmsg->cmd; u32 bus_no = cmd->create_bus.bus_no; int rc = CONTROLVM_RESP_SUCCESS; - struct visorchipset_bus_info *bus_info = NULL; + struct visorchipset_bus_info *bus_info; bus_info = findbus(&bus_info_list, bus_no); if (bus_info && (bus_info->state.created == 1)) { @@ -1108,8 +1108,8 @@ bus_configure(struct controlvm_message *inmsg, struct parser_context *parser_ctx) { struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->configure_bus.bus_no; - struct visorchipset_bus_info *bus_info = NULL; + u32 bus_no; + struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; char s[99]; @@ -1150,8 +1150,8 @@ my_device_create(struct controlvm_message *inmsg) struct controlvm_message_packet *cmd = &inmsg->cmd; u32 bus_no = cmd->create_device.bus_no; u32 dev_no = cmd->create_device.dev_no; - struct visorchipset_device_info *dev_info = NULL; - struct visorchipset_bus_info *bus_info = NULL; + struct visorchipset_device_info *dev_info; + struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; dev_info = finddevice(&dev_info_list, bus_no, dev_no); @@ -1221,7 +1221,7 @@ my_device_changestate(struct controlvm_message *inmsg) u32 bus_no = cmd->device_change_state.bus_no; u32 dev_no = cmd->device_change_state.dev_no; struct spar_segment_state state = cmd->device_change_state.state; - struct visorchipset_device_info *dev_info = NULL; + struct visorchipset_device_info *dev_info; int rc = CONTROLVM_RESP_SUCCESS; dev_info = finddevice(&dev_info_list, bus_no, dev_no); @@ -1248,7 +1248,7 @@ my_device_destroy(struct controlvm_message *inmsg) struct controlvm_message_packet *cmd = &inmsg->cmd; u32 bus_no = cmd->destroy_device.bus_no; u32 dev_no = cmd->destroy_device.dev_no; - struct visorchipset_device_info *dev_info = NULL; + struct visorchipset_device_info *dev_info; int rc = CONTROLVM_RESP_SUCCESS; dev_info = finddevice(&dev_info_list, bus_no, dev_no); @@ -1538,8 +1538,8 @@ parahotplug_request_kickoff(struct parahotplug_request *req) static void parahotplug_process_list(void) { - struct list_head *pos = NULL; - struct list_head *tmp = NULL; + struct list_head *pos; + struct list_head *tmp; spin_lock(¶hotplug_request_list_lock); @@ -1570,8 +1570,8 @@ parahotplug_process_list(void) static int parahotplug_request_complete(int id, u16 active) { - struct list_head *pos = NULL; - struct list_head *tmp = NULL; + struct list_head *pos; + struct list_head *tmp; spin_lock(¶hotplug_request_list_lock); @@ -1656,10 +1656,10 @@ static bool handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) { struct controlvm_message_packet *cmd = &inmsg.cmd; - u64 parm_addr = 0; - u32 parm_bytes = 0; + u64 parm_addr; + u32 parm_bytes; struct parser_context *parser_ctx = NULL; - bool local_addr = false; + bool local_addr; struct controlvm_message ackmsg; /* create parsing context if necessary */ -- cgit v1.2.3-55-g7522 From 9421736356cb4035a2ee10a021b8d0e82fd954a0 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:46 -0400 Subject: staging: unisys: Get rid of uint usage Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 0d3abce9074a..9b6c768e57ab 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -2120,7 +2120,7 @@ static ssize_t devicedisabled_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - uint id; + unsigned int id; if (kstrtouint(buf, 10, &id) != 0) return -EINVAL; @@ -2137,7 +2137,7 @@ static ssize_t deviceenabled_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - uint id; + unsigned int id; if (kstrtouint(buf, 10, &id) != 0) return -EINVAL; -- cgit v1.2.3-55-g7522 From be91cd3740cbaa3290ffd5a4cbb197fff7cdbeb2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:47 -0400 Subject: staging: unisys: Remove unused cache object counter kmem_cache statistics are available through SLAB anyway Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 9b6c768e57ab..e33d8866daeb 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -213,8 +213,6 @@ struct putfile_request { int completion_status; }; -static atomic_t visorchipset_cache_buffers_in_use = ATOMIC_INIT(0); - struct parahotplug_request { struct list_head list; int id; @@ -2077,7 +2075,6 @@ visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, if (!p) return NULL; - atomic_inc(&visorchipset_cache_buffers_in_use); return p; } @@ -2089,7 +2086,6 @@ visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln) if (!p) return; - atomic_dec(&visorchipset_cache_buffers_in_use); kmem_cache_free(pool, p); } -- cgit v1.2.3-55-g7522 From 94ac450060e77f5b85bb854f6bb444ecd1d99502 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:48 -0400 Subject: staging: unisys: Don't include timskmod.h Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/parser.h | 1 - drivers/staging/unisys/visorchipset/visorchipset.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h index 73be279bb401..3fe17c0c64d2 100644 --- a/drivers/staging/unisys/visorchipset/parser.h +++ b/drivers/staging/unisys/visorchipset/parser.h @@ -20,7 +20,6 @@ #include -#include "timskmod.h" #include "channel.h" typedef enum { diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 2c2d3fb47dc3..3c57782df96a 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -20,7 +20,6 @@ #include -#include "timskmod.h" #include "channel.h" #include "controlvmchannel.h" #include "parser.h" -- cgit v1.2.3-55-g7522 From f10c55428f9e16361d69073e2e619f38a7a1c438 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:49 -0400 Subject: staging: unisys: Remove a couple of unnecessary blank lines Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 3c57782df96a..53bbc4979edc 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -68,7 +68,6 @@ struct visorchipset_channel_info { u64 n_channel_bytes; uuid_le channel_type_uuid; uuid_le channel_inst_uuid; - }; /** Attributes for a particular Supervisor device. @@ -90,7 +89,6 @@ struct visorchipset_device_info { struct controlvm_message_header pending_msg_hdr;/* CONTROLVM_MESSAGE */ /** For private use by the bus driver */ void *bus_driver_context; - }; static inline struct visorchipset_device_info *finddevice( -- cgit v1.2.3-55-g7522 From 53dfe389c863eddf6aaeeab8afb34ffdd42a2079 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:50 -0400 Subject: staging: unisys: buffer_list_pool isn't used for anything Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorchipset/visorchipset_main.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index e33d8866daeb..69730d190954 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -138,13 +138,6 @@ static struct visor_livedump_info livedump_info; static struct controlvm_message controlvm_pending_msg; static bool controlvm_pending_msg_valid = false; -/* Pool of struct putfile_buffer_entry, for keeping track of pending (incoming) - * TRANSMIT_FILE PutFile payloads. - */ -static struct kmem_cache *putfile_buffer_list_pool; -static const char putfile_buffer_list_pool_name[] = - "controlvm_putfile_buffer_list_pool"; - /* This identifies a data buffer that has been received via a controlvm messages * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. */ @@ -2195,15 +2188,6 @@ visorchipset_init(void) memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header)); - putfile_buffer_list_pool = - kmem_cache_create(putfile_buffer_list_pool_name, - sizeof(struct putfile_buffer_entry), - 0, SLAB_HWCACHE_ALIGN, NULL); - if (!putfile_buffer_list_pool) { - POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR); - rc = -1; - goto cleanup; - } if (!visorchipset_disable_controlvm) { /* if booting in a crash kernel */ if (is_kdump_kernel()) @@ -2262,10 +2246,6 @@ visorchipset_exit(void) periodic_controlvm_workqueue = NULL; destroy_controlvm_payload_info(&controlvm_payload_info); } - if (putfile_buffer_list_pool) { - kmem_cache_destroy(putfile_buffer_list_pool); - putfile_buffer_list_pool = NULL; - } cleanup_controlvm_structures(); -- cgit v1.2.3-55-g7522 From a5aa395da6d1688cc0d8b5239c3a66aa235580a7 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:51 -0400 Subject: staging: unisys: Remove write-only visorchipset_bus_info.dev_no Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 1 - drivers/staging/unisys/visorchipset/visorchipset_main.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 53bbc4979edc..d21fcb027cac 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -140,7 +140,6 @@ struct visorchipset_bus_info { struct controlvm_message_header pending_msg_hdr;/* CONTROLVM MsgHdr */ /** For private use by the bus driver */ void *bus_driver_context; - u32 dev_no; }; static inline struct visorchipset_bus_info * diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 69730d190954..e78ae7bbb72f 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -1051,7 +1051,6 @@ bus_create(struct controlvm_message *inmsg) INIT_LIST_HEAD(&bus_info->entry); bus_info->bus_no = bus_no; - bus_info->dev_no = cmd->create_bus.dev_count; POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO); -- cgit v1.2.3-55-g7522 From 4f66520be923db928b487a5181c6ff8a5590857f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:52 -0400 Subject: staging: unisys: findbus() doesn't need to be inline Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 12 --------- .../unisys/visorchipset/visorchipset_main.c | 31 +++++++++++++++------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index d21fcb027cac..70b9e6ec60d9 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -142,18 +142,6 @@ struct visorchipset_bus_info { void *bus_driver_context; }; -static inline struct visorchipset_bus_info * -findbus(struct list_head *list, u32 bus_no) -{ - struct visorchipset_bus_info *p; - - list_for_each_entry(p, list, entry) { - if (p->bus_no == bus_no) - return p; - } - return NULL; -} - /* These functions will be called from within visorchipset when certain * events happen. (The implementation of these functions is outside of * visorchipset.) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index e78ae7bbb72f..f64756736164 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -526,6 +526,19 @@ dev_info_clear(void *v) memset(p, 0, sizeof(struct visorchipset_device_info)); } +static struct visorchipset_bus_info * +bus_find(struct list_head *list, u32 bus_no) +{ + struct visorchipset_bus_info *p; + + list_for_each_entry(p, list, entry) { + if (p->bus_no == bus_no) + return p; + } + + return NULL; +} + static u8 check_chipset_events(void) { @@ -776,7 +789,7 @@ bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) struct visorchipset_bus_info *p; bool need_clear = false; - p = findbus(&bus_info_list, bus_no); + p = bus_find(&bus_info_list, bus_no); if (!p) return; @@ -866,10 +879,10 @@ bus_epilog(u32 bus_no, u32 cmd, struct controlvm_message_header *msg_hdr, int response, bool need_response) { + struct visorchipset_bus_info *bus_info; bool notified = false; - struct visorchipset_bus_info *bus_info = findbus(&bus_info_list, - bus_no); + bus_info = bus_find(&bus_info_list, bus_no); if (!bus_info) return; @@ -1034,7 +1047,7 @@ bus_create(struct controlvm_message *inmsg) int rc = CONTROLVM_RESP_SUCCESS; struct visorchipset_bus_info *bus_info; - bus_info = findbus(&bus_info_list, bus_no); + bus_info = bus_find(&bus_info_list, bus_no); if (bus_info && (bus_info->state.created == 1)) { POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); @@ -1083,7 +1096,7 @@ bus_destroy(struct controlvm_message *inmsg) struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; - bus_info = findbus(&bus_info_list, bus_no); + bus_info = bus_find(&bus_info_list, bus_no); if (!bus_info) rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; else if (bus_info->state.created == 0) @@ -1107,7 +1120,7 @@ bus_configure(struct controlvm_message *inmsg, POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO); - bus_info = findbus(&bus_info_list, bus_no); + bus_info = bus_find(&bus_info_list, bus_no); if (!bus_info) { POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); @@ -1151,7 +1164,7 @@ my_device_create(struct controlvm_message *inmsg) rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; goto cleanup; } - bus_info = findbus(&bus_info_list, bus_no); + bus_info = bus_find(&bus_info_list, bus_no); if (!bus_info) { POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); @@ -1995,7 +2008,7 @@ device_resume_response(u32 bus_no, u32 dev_no, int response) bool visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info) { - void *p = findbus(&bus_info_list, bus_no); + void *p = bus_find(&bus_info_list, bus_no); if (!p) return false; @@ -2007,7 +2020,7 @@ EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); bool visorchipset_set_bus_context(u32 bus_no, void *context) { - struct visorchipset_bus_info *p = findbus(&bus_info_list, bus_no); + struct visorchipset_bus_info *p = bus_find(&bus_info_list, bus_no); if (!p) return false; -- cgit v1.2.3-55-g7522 From 92b5e8c0ac63fb74171929b98f1fa170a0ff46b2 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:53 -0400 Subject: staging: unisys: Remove unused typedef SPARREPORTEVENT_COMPLETE_FUNC Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 70b9e6ec60d9..59552afc663f 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -194,9 +194,6 @@ visorchipset_register_busdev_server( struct visorchipset_busdev_responders *responders, struct ultra_vbus_deviceinfo *driver_info); -typedef void (*SPARREPORTEVENT_COMPLETE_FUNC) (struct controlvm_message *msg, - int status); - void visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response); bool visorchipset_get_bus_info(u32 bus_no, -- cgit v1.2.3-55-g7522 From d480f6a2b9f5aaf8f34ef74ef471d0e219c45c21 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:54 -0400 Subject: staging: unisys: finddevice() doesn't need to be inline Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 12 -------- .../unisys/visorchipset/visorchipset_main.c | 32 ++++++++++++++++------ 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 59552afc663f..a3fe8b7de341 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -91,18 +91,6 @@ struct visorchipset_device_info { void *bus_driver_context; }; -static inline struct visorchipset_device_info *finddevice( - struct list_head *list, u32 bus_no, u32 dev_no) -{ - struct visorchipset_device_info *p; - - list_for_each_entry(p, list, entry) { - if (p->bus_no == bus_no && p->dev_no == dev_no) - return p; - } - return NULL; -} - static inline void delbusdevices(struct list_head *list, u32 bus_no) { struct visorchipset_device_info *p, *tmp; diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index f64756736164..d1f0d18da10e 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -539,6 +539,19 @@ bus_find(struct list_head *list, u32 bus_no) return NULL; } +static struct visorchipset_device_info * +device_find(struct list_head *list, u32 bus_no, u32 dev_no) +{ + struct visorchipset_device_info *p; + + list_for_each_entry(p, list, entry) { + if (p->bus_no == bus_no && p->dev_no == dev_no) + return p; + } + + return NULL; +} + static u8 check_chipset_events(void) { @@ -825,7 +838,7 @@ device_changestate_responder(enum controlvm_id cmd_id, struct visorchipset_device_info *p; struct controlvm_message outmsg; - p = finddevice(&dev_info_list, bus_no, dev_no); + p = device_find(&dev_info_list, bus_no, dev_no); if (!p) return; if (p->pending_msg_hdr.id == CONTROLVM_INVALID) @@ -852,7 +865,7 @@ device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) struct visorchipset_device_info *p; bool need_clear = false; - p = finddevice(&dev_info_list, bus_no, dev_no); + p = device_find(&dev_info_list, bus_no, dev_no); if (!p) return; if (response >= 0) { @@ -951,7 +964,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, bool notified = false; struct visorchipset_device_info *dev_info = - finddevice(&dev_info_list, bus_no, dev_no); + device_find(&dev_info_list, bus_no, dev_no); char *envp[] = { "SPARSP_DIAGPOOL_PAUSED_STATE = 1", NULL @@ -1157,7 +1170,7 @@ my_device_create(struct controlvm_message *inmsg) struct visorchipset_bus_info *bus_info; int rc = CONTROLVM_RESP_SUCCESS; - dev_info = finddevice(&dev_info_list, bus_no, dev_no); + dev_info = device_find(&dev_info_list, bus_no, dev_no); if (dev_info && (dev_info->state.created == 1)) { POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); @@ -1227,7 +1240,7 @@ my_device_changestate(struct controlvm_message *inmsg) struct visorchipset_device_info *dev_info; int rc = CONTROLVM_RESP_SUCCESS; - dev_info = finddevice(&dev_info_list, bus_no, dev_no); + dev_info = device_find(&dev_info_list, bus_no, dev_no); if (!dev_info) { POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); @@ -1254,7 +1267,7 @@ my_device_destroy(struct controlvm_message *inmsg) struct visorchipset_device_info *dev_info; int rc = CONTROLVM_RESP_SUCCESS; - dev_info = finddevice(&dev_info_list, bus_no, dev_no); + dev_info = device_find(&dev_info_list, bus_no, dev_no); if (!dev_info) rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; else if (dev_info->state.created == 0) @@ -2033,7 +2046,7 @@ bool visorchipset_get_device_info(u32 bus_no, u32 dev_no, struct visorchipset_device_info *dev_info) { - void *p = finddevice(&dev_info_list, bus_no, dev_no); + void *p = device_find(&dev_info_list, bus_no, dev_no); if (!p) return false; @@ -2045,8 +2058,9 @@ EXPORT_SYMBOL_GPL(visorchipset_get_device_info); bool visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context) { - struct visorchipset_device_info *p = - finddevice(&dev_info_list, bus_no, dev_no); + struct visorchipset_device_info *p; + + p = device_find(&dev_info_list, bus_no, dev_no); if (!p) return false; -- cgit v1.2.3-55-g7522 From 28723521a7e909d4fb19a682ad9a3647496fe62b Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:55 -0400 Subject: staging: unisys: delbusdevices() doesn't need to be inline Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 12 ------------ drivers/staging/unisys/visorchipset/visorchipset_main.c | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index a3fe8b7de341..1d66c3766c42 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -91,18 +91,6 @@ struct visorchipset_device_info { void *bus_driver_context; }; -static inline void delbusdevices(struct list_head *list, u32 bus_no) -{ - struct visorchipset_device_info *p, *tmp; - - list_for_each_entry_safe(p, tmp, list, entry) { - if (p->bus_no == bus_no) { - list_del(&p->entry); - kfree(p); - } - } -} - /** Attributes for a particular Supervisor bus. * (For a service partition acting as the server for buses/devices, there * is a 1-to-1 relationship between busses and guest partitions.) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index d1f0d18da10e..9f5c539d959b 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -552,6 +552,18 @@ device_find(struct list_head *list, u32 bus_no, u32 dev_no) return NULL; } +static void busdevices_del(struct list_head *list, u32 bus_no) +{ + struct visorchipset_device_info *p, *tmp; + + list_for_each_entry_safe(p, tmp, list, entry) { + if (p->bus_no == bus_no) { + list_del(&p->entry); + kfree(p); + } + } +} + static u8 check_chipset_events(void) { @@ -810,7 +822,7 @@ bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) if ((cmd_id == CONTROLVM_BUS_CREATE) && (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE))) /* undo the row we just created... */ - delbusdevices(&dev_info_list, bus_no); + busdevices_del(&dev_info_list, bus_no); } else { if (cmd_id == CONTROLVM_BUS_CREATE) p->state.created = 1; @@ -826,7 +838,7 @@ bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) p->pending_msg_hdr.id = CONTROLVM_INVALID; if (need_clear) { bus_info_clear(p); - delbusdevices(&dev_info_list, bus_no); + busdevices_del(&dev_info_list, bus_no); } } -- cgit v1.2.3-55-g7522 From 4eb32b4892bbf5b71f63e468af0c7d660dac6d96 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:56 -0400 Subject: staging: unisys: Avoid some == 0 checks Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index e63ef2a3a4a9..a17027c211a2 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -36,7 +36,7 @@ static struct visorchannel **file_controlvm_channel; void visorchipset_file_cleanup(dev_t major_dev) { - if (file_cdev.ops != NULL) + if (file_cdev.ops) cdev_del(&file_cdev); file_cdev.ops = NULL; unregister_chrdev_region(major_dev, 1); @@ -47,7 +47,7 @@ visorchipset_open(struct inode *inode, struct file *file) { unsigned minor_number = iminor(inode); - if (minor_number != 0) + if (minor_number) return -ENODEV; file->private_data = NULL; return 0; @@ -73,16 +73,16 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) switch (offset) { case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: vma->vm_flags |= VM_IO; - if (*file_controlvm_channel == NULL) { + if (!*file_controlvm_channel) return -ENXIO; - } + visorchannel_read(*file_controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, gp_control_channel), &addr, sizeof(addr)); - if (addr == 0) { + if (!addr) return -ENXIO; - } + physaddr = (unsigned long)addr; if (remap_pfn_range(vma, vma->vm_start, physaddr >> PAGE_SHIFT, -- cgit v1.2.3-55-g7522 From ebec896762ee07c0dce9883865faa2a2d4b20751 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:57 -0400 Subject: staging: unisys: No point in checking != 0 Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../unisys/visorchipset/visorchipset_main.c | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 9f5c539d959b..3b5f3d6ae2ff 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -368,7 +368,7 @@ static ssize_t toolaction_store(struct device *dev, u8 tool_action; int ret; - if (kstrtou8(buf, 10, &tool_action) != 0) + if (kstrtou8(buf, 10, &tool_action)) return -EINVAL; ret = visorchannel_write(controlvm_channel, @@ -402,7 +402,7 @@ static ssize_t boottotool_store(struct device *dev, int val, ret; struct efi_spar_indication efi_spar_indication; - if (kstrtoint(buf, 10, &val) != 0) + if (kstrtoint(buf, 10, &val)) return -EINVAL; efi_spar_indication.boot_to_tool = val; @@ -434,7 +434,7 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, u32 error; int ret; - if (kstrtou32(buf, 10, &error) != 0) + if (kstrtou32(buf, 10, &error)) return -EINVAL; ret = visorchannel_write(controlvm_channel, @@ -464,7 +464,7 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, u32 text_id; int ret; - if (kstrtou32(buf, 10, &text_id) != 0) + if (kstrtou32(buf, 10, &text_id)) return -EINVAL; ret = visorchannel_write(controlvm_channel, @@ -495,7 +495,7 @@ static ssize_t remaining_steps_store(struct device *dev, u16 remaining_steps; int ret; - if (kstrtou16(buf, 10, &remaining_steps) != 0) + if (kstrtou16(buf, 10, &remaining_steps)) return -EINVAL; ret = visorchannel_write(controlvm_channel, @@ -1701,7 +1701,7 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) * within our OS-controlled memory. We need to know that, because it * makes a difference in how we compute the virtual address. */ - if (parm_addr != 0 && parm_bytes != 0) { + if (parm_addr && parm_bytes) { bool retry = false; parser_ctx = @@ -1962,7 +1962,7 @@ setup_crash_devices_work_queue(struct work_struct *work) } /* reuse IOVM create bus message */ - if (local_crash_bus_msg.cmd.create_bus.channel_addr != 0) { + if (local_crash_bus_msg.cmd.create_bus.channel_addr) { bus_create(&local_crash_bus_msg); } else { POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC, @@ -1971,7 +1971,7 @@ setup_crash_devices_work_queue(struct work_struct *work) } /* reuse create device message for storage device */ - if (local_crash_dev_msg.cmd.create_device.channel_addr != 0) { + if (local_crash_dev_msg.cmd.create_device.channel_addr) { my_device_create(&local_crash_dev_msg); } else { POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC, @@ -2129,10 +2129,10 @@ static ssize_t chipsetready_store(struct device *dev, if (sscanf(buf, "%63s", msgtype) != 1) return -EINVAL; - if (strcmp(msgtype, "CALLHOMEDISK_MOUNTED") == 0) { + if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) { chipset_events[0] = 1; return count; - } else if (strcmp(msgtype, "MODULES_LOADED") == 0) { + } else if (!strcmp(msgtype, "MODULES_LOADED")) { chipset_events[1] = 1; return count; } @@ -2149,7 +2149,7 @@ static ssize_t devicedisabled_store(struct device *dev, { unsigned int id; - if (kstrtouint(buf, 10, &id) != 0) + if (kstrtouint(buf, 10, &id)) return -EINVAL; parahotplug_request_complete(id, 0); @@ -2166,7 +2166,7 @@ static ssize_t deviceenabled_store(struct device *dev, { unsigned int id; - if (kstrtouint(buf, 10, &id) != 0) + if (kstrtouint(buf, 10, &id)) return -EINVAL; parahotplug_request_complete(id, 1); @@ -2195,7 +2195,7 @@ visorchipset_init(void) } addr = controlvm_get_channel_address(); - if (addr != 0) { + if (addr) { controlvm_channel = visorchannel_create_with_lock (addr, -- cgit v1.2.3-55-g7522 From 5157d88c9becd6a8cdb2978afaaf63b56b249c51 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:58 -0400 Subject: staging: unisys: Remove write-only variable g_diag_msg_hdr Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 3b5f3d6ae2ff..b733147b4dbb 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -75,7 +75,6 @@ static struct delayed_work periodic_controlvm_work; static struct workqueue_struct *periodic_controlvm_workqueue; static DEFINE_SEMAPHORE(notifier_lock); -static struct controlvm_message_header g_diag_msg_hdr; static struct controlvm_message_header g_chipset_msg_hdr; static struct controlvm_message_header g_del_dump_msg_hdr; static const uuid_le spar_diag_pool_channel_protocol_uuid = @@ -1742,7 +1741,6 @@ handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) /* save the hdr and cmd structures for later use */ /* when sending back the response to Command */ my_device_changestate(&inmsg); - g_diag_msg_hdr = inmsg.hdr; g_devicechangestate_packet = inmsg.cmd; break; } @@ -2220,8 +2218,6 @@ visorchipset_init(void) goto cleanup; } - memset(&g_diag_msg_hdr, 0, sizeof(struct controlvm_message_header)); - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header)); @@ -2287,8 +2283,6 @@ visorchipset_exit(void) cleanup_controlvm_structures(); - memset(&g_diag_msg_hdr, 0, sizeof(struct controlvm_message_header)); - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header)); -- cgit v1.2.3-55-g7522 From 7e61e4c9b34c51913997830682181a24febe810d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 5 May 2015 18:35:59 -0400 Subject: staging: unisys: Remove write-only variable g_del_dump_msg_hdr Signed-off-by: Jes Sorensen Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index b733147b4dbb..5ea6f9e81fba 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -76,7 +76,6 @@ static struct workqueue_struct *periodic_controlvm_workqueue; static DEFINE_SEMAPHORE(notifier_lock); static struct controlvm_message_header g_chipset_msg_hdr; -static struct controlvm_message_header g_del_dump_msg_hdr; static const uuid_le spar_diag_pool_channel_protocol_uuid = SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; /* 0xffffff is an invalid Bus/Device number */ @@ -2220,8 +2219,6 @@ visorchipset_init(void) memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); - memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header)); - if (!visorchipset_disable_controlvm) { /* if booting in a crash kernel */ if (is_kdump_kernel()) @@ -2285,8 +2282,6 @@ visorchipset_exit(void) memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); - memset(&g_del_dump_msg_hdr, 0, sizeof(struct controlvm_message_header)); - visorchannel_destroy(controlvm_channel); visorchipset_file_cleanup(visorchipset_platform_device.dev.devt); -- cgit v1.2.3-55-g7522 From 291603cca7eb52e7c2be4c5e1451de431bd21e73 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Tue, 5 May 2015 18:36:01 -0400 Subject: staging: unisys: Move visorchannel into visorbus visorchannel seems to be a necessary component to visorbus and can never function as a standalone module. Let's treat it like a visorbus feature that is always enabled. Signed-off-by: Don Zickus Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/Kconfig | 1 - drivers/staging/unisys/Makefile | 1 - drivers/staging/unisys/visorbus/Kconfig | 3 +- drivers/staging/unisys/visorbus/Makefile | 2 +- drivers/staging/unisys/visorbus/globals.h | 27 + drivers/staging/unisys/visorbus/visorchannel.h | 76 +++ .../staging/unisys/visorbus/visorchannel_funcs.c | 663 +++++++++++++++++++++ drivers/staging/unisys/visorchannel/visorchannel.h | 76 --- .../unisys/visorchannel/visorchannel_funcs.c | 663 --------------------- drivers/staging/unisys/visorchipset/Kconfig | 1 + drivers/staging/unisys/visorchipset/Makefile | 2 +- 11 files changed, 770 insertions(+), 745 deletions(-) create mode 100644 drivers/staging/unisys/visorbus/globals.h create mode 100644 drivers/staging/unisys/visorbus/visorchannel.h create mode 100644 drivers/staging/unisys/visorbus/visorchannel_funcs.c delete mode 100644 drivers/staging/unisys/visorchannel/visorchannel.h delete mode 100644 drivers/staging/unisys/visorchannel/visorchannel_funcs.c (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index 8d056b55ced7..dbdd4492cf0f 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -10,7 +10,6 @@ menuconfig UNISYSSPAR if UNISYSSPAR source "drivers/staging/unisys/visorutil/Kconfig" -source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" source "drivers/staging/unisys/visorbus/Kconfig" diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index 1ed9d39ff230..b14a4777fd48 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -2,6 +2,5 @@ # Makefile for Unisys SPAR drivers # obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ -obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ diff --git a/drivers/staging/unisys/visorbus/Kconfig b/drivers/staging/unisys/visorbus/Kconfig index 0141528657e2..12cf8f063550 100644 --- a/drivers/staging/unisys/visorbus/Kconfig +++ b/drivers/staging/unisys/visorbus/Kconfig @@ -4,7 +4,6 @@ config UNISYS_VISORBUS tristate "Unisys visorbus driver" - depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHANNEL && UNISYS_VISORCHIPSET + depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHIPSET ---help--- If you say Y here, you will enable the Unisys visorbus driver. - diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile index 60bb96bad239..20d87daf5b00 100644 --- a/drivers/staging/unisys/visorbus/Makefile +++ b/drivers/staging/unisys/visorbus/Makefile @@ -5,9 +5,9 @@ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus.o visorbus-y := visorbus_main.o devmajorminor_attr.o businst_attr.o channel_attr.o +visorbus-y += visorchannel_funcs.o ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/visorchannel ccflags-y += -Idrivers/staging/unisys/visorchipset ccflags-y += -Idrivers/staging/unisys/common-spar/include ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/visorbus/globals.h b/drivers/staging/unisys/visorbus/globals.h new file mode 100644 index 000000000000..0ed8e1d8033a --- /dev/null +++ b/drivers/staging/unisys/visorbus/globals.h @@ -0,0 +1,27 @@ +/* globals.h + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __VISORCHANNEL_GLOBALS_H__ +#define __VISORCHANNEL_GLOBALS_H__ + +#include "timskmod.h" +#include "memregion.h" +#include "version.h" + +#define MYDRVNAME "visorchannel" + +#endif diff --git a/drivers/staging/unisys/visorbus/visorchannel.h b/drivers/staging/unisys/visorbus/visorchannel.h new file mode 100644 index 000000000000..63f1b9760373 --- /dev/null +++ b/drivers/staging/unisys/visorbus/visorchannel.h @@ -0,0 +1,76 @@ +/* visorchannel.h + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __VISORCHANNEL_H__ +#define __VISORCHANNEL_H__ + +#include + +#include "memregion.h" +#include "channel.h" +#ifndef HOSTADDRESS +#define HOSTADDRESS u64 +#endif +#ifndef BOOL +#define BOOL int +#endif + +/* Note that for visorchannel_create() and visorchannel_create_overlapped(), + * and arguments may be 0 if we are a channel CLIENT. + * In this case, the values can simply be read from the channel header. + */ +struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, + ulong channel_bytes, uuid_le guid); +struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, + ulong channel_bytes, + uuid_le guid); +struct visorchannel *visorchannel_create_overlapped_with_lock( + ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_clear(struct visorchannel *channel, ulong offset, + u8 ch, ulong nbytes); +BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); +BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); +int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, + u32 queue); +int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); +HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +uuid_le visorchannel_get_uuid(struct visorchannel *channel); +struct memregion *visorchannel_get_memregion(struct visorchannel *channel); +char *visorchannel_uuid_id(uuid_le *guid, char *s); +void visorchannel_debug(struct visorchannel *channel, int num_queues, + struct seq_file *seq, u32 off); +void visorchannel_dump_section(struct visorchannel *chan, char *s, + int off, int len, struct seq_file *seq); +void __iomem *visorchannel_get_header(struct visorchannel *channel); + +#endif diff --git a/drivers/staging/unisys/visorbus/visorchannel_funcs.c b/drivers/staging/unisys/visorbus/visorchannel_funcs.c new file mode 100644 index 000000000000..9ae5f752bbf5 --- /dev/null +++ b/drivers/staging/unisys/visorbus/visorchannel_funcs.c @@ -0,0 +1,663 @@ +/* visorchannel_funcs.c + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +/* + * This provides Supervisor channel communication primitives, which are + * independent of the mechanism used to access the channel data. All channel + * data is accessed using the memregion abstraction. (memregion has both + * a CM2 implementation and a direct memory implementation.) + */ + +#include "globals.h" +#include "visorchannel.h" +#include + +#define MYDRVNAME "visorchannel" + +struct visorchannel { + struct memregion *memregion; /* from visor_memregion_create() */ + struct channel_header chan_hdr; + uuid_le guid; + ulong size; + BOOL needs_lock; /* channel creator knows if more than one + * thread will be inserting or removing */ + spinlock_t insert_lock; /* protect head writes in chan_hdr */ + spinlock_t remove_lock; /* protect tail writes in chan_hdr */ + + struct { + struct signal_queue_header req_queue; + struct signal_queue_header rsp_queue; + struct signal_queue_header event_queue; + struct signal_queue_header ack_queue; + } safe_uis_queue; +}; + +/* Creates the struct visorchannel abstraction for a data area in memory, + * but does NOT modify this data area. + */ +static struct visorchannel * +visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes, + struct visorchannel *parent, ulong off, uuid_le guid, + BOOL needs_lock) +{ + struct visorchannel *p = NULL; + void *rc = NULL; + + p = kmalloc(sizeof(*p), GFP_KERNEL|__GFP_NORETRY); + if (!p) { + rc = NULL; + goto cleanup; + } + p->memregion = NULL; + p->needs_lock = needs_lock; + spin_lock_init(&p->insert_lock); + spin_lock_init(&p->remove_lock); + + /* prepare chan_hdr (abstraction to read/write channel memory) */ + if (!parent) + p->memregion = + visor_memregion_create(physaddr, + sizeof(struct channel_header)); + else + p->memregion = + visor_memregion_create_overlapped(parent->memregion, + off, sizeof(struct channel_header)); + if (!p->memregion) { + rc = NULL; + goto cleanup; + } + if (visor_memregion_read(p->memregion, 0, &p->chan_hdr, + sizeof(struct channel_header)) < 0) { + rc = NULL; + goto cleanup; + } + if (channel_bytes == 0) + /* we had better be a CLIENT of this channel */ + channel_bytes = (ulong)p->chan_hdr.size; + if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) + /* we had better be a CLIENT of this channel */ + guid = p->chan_hdr.chtype; + if (visor_memregion_resize(p->memregion, channel_bytes) < 0) { + rc = NULL; + goto cleanup; + } + p->size = channel_bytes; + p->guid = guid; + + rc = p; +cleanup: + + if (!rc) { + if (!p) { + visorchannel_destroy(p); + p = NULL; + } + } + return rc; +} + +struct visorchannel * +visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) +{ + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, + FALSE); +} +EXPORT_SYMBOL_GPL(visorchannel_create); + +struct visorchannel * +visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, + uuid_le guid) +{ + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, + TRUE); +} +EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); + +struct visorchannel * +visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, ulong off, + uuid_le guid) +{ + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, + FALSE); +} +EXPORT_SYMBOL_GPL(visorchannel_create_overlapped); + +struct visorchannel * +visorchannel_create_overlapped_with_lock(ulong channel_bytes, + struct visorchannel *parent, ulong off, + uuid_le guid) +{ + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, + TRUE); +} +EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock); + +void +visorchannel_destroy(struct visorchannel *channel) +{ + if (!channel) + return; + if (channel->memregion) { + visor_memregion_destroy(channel->memregion); + channel->memregion = NULL; + } + kfree(channel); +} +EXPORT_SYMBOL_GPL(visorchannel_destroy); + +HOSTADDRESS +visorchannel_get_physaddr(struct visorchannel *channel) +{ + return visor_memregion_get_physaddr(channel->memregion); +} +EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); + +ulong +visorchannel_get_nbytes(struct visorchannel *channel) +{ + return channel->size; +} +EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); + +char * +visorchannel_uuid_id(uuid_le *guid, char *s) +{ + sprintf(s, "%pUL", guid); + return s; +} +EXPORT_SYMBOL_GPL(visorchannel_uuid_id); + +char * +visorchannel_id(struct visorchannel *channel, char *s) +{ + return visorchannel_uuid_id(&channel->guid, s); +} +EXPORT_SYMBOL_GPL(visorchannel_id); + +char * +visorchannel_zoneid(struct visorchannel *channel, char *s) +{ + return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); +} +EXPORT_SYMBOL_GPL(visorchannel_zoneid); + +HOSTADDRESS +visorchannel_get_clientpartition(struct visorchannel *channel) +{ + return channel->chan_hdr.partition_handle; +} +EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); + +uuid_le +visorchannel_get_uuid(struct visorchannel *channel) +{ + return channel->guid; +} +EXPORT_SYMBOL_GPL(visorchannel_get_uuid); + +struct memregion * +visorchannel_get_memregion(struct visorchannel *channel) +{ + return channel->memregion; +} +EXPORT_SYMBOL_GPL(visorchannel_get_memregion); + +int +visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes) +{ + int rc = visor_memregion_read(channel->memregion, offset, + local, nbytes); + if ((rc >= 0) && (offset == 0) && + (nbytes >= sizeof(struct channel_header))) { + memcpy(&channel->chan_hdr, local, + sizeof(struct channel_header)); + } + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_read); + +int +visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes) +{ + if (offset == 0 && nbytes >= sizeof(struct channel_header)) + memcpy(&channel->chan_hdr, local, + sizeof(struct channel_header)); + return visor_memregion_write(channel->memregion, offset, local, nbytes); +} +EXPORT_SYMBOL_GPL(visorchannel_write); + +int +visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, + ulong nbytes) +{ + int rc = -1; + int bufsize = 65536; + int written = 0; + u8 *buf = vmalloc(bufsize); + + if (!buf) + goto cleanup; + + memset(buf, ch, bufsize); + while (nbytes > 0) { + ulong thisbytes = bufsize; + int x = -1; + + if (nbytes < thisbytes) + thisbytes = nbytes; + x = visor_memregion_write(channel->memregion, offset + written, + buf, thisbytes); + if (x < 0) { + rc = x; + goto cleanup; + } + written += thisbytes; + nbytes -= thisbytes; + } + rc = 0; + +cleanup: + if (buf) { + vfree(buf); + buf = NULL; + } + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_clear); + +void __iomem * +visorchannel_get_header(struct visorchannel *channel) +{ + return (void __iomem *)&channel->chan_hdr; +} +EXPORT_SYMBOL_GPL(visorchannel_get_header); + +/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a + * channel header + */ +#define SIG_QUEUE_OFFSET(chan_hdr, q) \ + ((chan_hdr)->ch_space_offset + \ + ((q) * sizeof(struct signal_queue_header))) + +/** Return offset of a specific queue entry (data) from the beginning of a + * channel header + */ +#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ + (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ + ((slot) * (sig_hdr)->signal_size)) + +/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back + * into host memory + */ +#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ + (visor_memregion_write(channel->memregion, \ + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \ + offsetof(struct signal_queue_header, FIELD),\ + &((sig_hdr)->FIELD), \ + sizeof((sig_hdr)->FIELD)) >= 0) + +static BOOL +sig_read_header(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr) +{ + BOOL rc = FALSE; + + if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) + goto cleanup; + + /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ + + if (visor_memregion_read(channel->memregion, + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), + sig_hdr, + sizeof(struct signal_queue_header)) < 0) { + goto cleanup; + } + rc = TRUE; +cleanup: + return rc; +} + +static BOOL +sig_do_data(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr, u32 slot, void *data, + BOOL is_write) +{ + BOOL rc = FALSE; + int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, + sig_hdr, slot); + if (is_write) { + if (visor_memregion_write(channel->memregion, + signal_data_offset, + data, sig_hdr->signal_size) < 0) { + goto cleanup; + } + } else { + if (visor_memregion_read(channel->memregion, signal_data_offset, + data, sig_hdr->signal_size) < 0) { + goto cleanup; + } + } + rc = TRUE; +cleanup: + return rc; +} + +static inline BOOL +sig_read_data(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr, u32 slot, void *data) +{ + return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE); +} + +static inline BOOL +sig_write_data(struct visorchannel *channel, u32 queue, + struct signal_queue_header *sig_hdr, u32 slot, void *data) +{ + return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE); +} + +static inline unsigned char +safe_sig_queue_validate(struct signal_queue_header *psafe_sqh, + struct signal_queue_header *punsafe_sqh, + u32 *phead, u32 *ptail) +{ + if ((*phead >= psafe_sqh->max_slots) || + (*ptail >= psafe_sqh->max_slots)) { + /* Choose 0 or max, maybe based on current tail value */ + *phead = 0; + *ptail = 0; + + /* Sync with client as necessary */ + punsafe_sqh->head = *phead; + punsafe_sqh->tail = *ptail; + + return 0; + } + return 1; +} /* end safe_sig_queue_validate */ + +static BOOL +signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) +{ + struct signal_queue_header sig_hdr; + + if (!sig_read_header(channel, queue, &sig_hdr)) + return FALSE; + if (sig_hdr.head == sig_hdr.tail) + return FALSE; /* no signals to remove */ + + sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; + if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) + return FALSE; + sig_hdr.num_received++; + + /* For each data field in SIGNAL_QUEUE_HEADER that was modified, + * update host memory. + */ + mb(); /* required for channel synch */ + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) + return FALSE; + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) + return FALSE; + return TRUE; +} + +BOOL +visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->remove_lock); + rc = signalremove_inner(channel, queue, msg); + spin_unlock(&channel->remove_lock); + } else { + rc = signalremove_inner(channel, queue, msg); + } + + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_signalremove); + +static BOOL +signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) +{ + struct signal_queue_header sig_hdr; + + if (!sig_read_header(channel, queue, &sig_hdr)) + return FALSE; + + sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); + if (sig_hdr.head == sig_hdr.tail) { + sig_hdr.num_overflows++; + visor_memregion_write(channel->memregion, + SIG_QUEUE_OFFSET(&channel->chan_hdr, + queue) + + offsetof(struct signal_queue_header, + num_overflows), + &(sig_hdr.num_overflows), + sizeof(sig_hdr.num_overflows)); + return FALSE; + } + + if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) + return FALSE; + + sig_hdr.num_sent++; + + /* For each data field in SIGNAL_QUEUE_HEADER that was modified, + * update host memory. + */ + mb(); /* required for channel synch */ + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) + return FALSE; + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) + return FALSE; + + return TRUE; +} + +BOOL +visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->insert_lock); + rc = signalinsert_inner(channel, queue, msg); + spin_unlock(&channel->insert_lock); + } else { + rc = signalinsert_inner(channel, queue, msg); + } + + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_signalinsert); + +int +visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) +{ + struct signal_queue_header sig_hdr; + u32 slots_avail, slots_used; + u32 head, tail; + + if (!sig_read_header(channel, queue, &sig_hdr)) + return 0; + head = sig_hdr.head; + tail = sig_hdr.tail; + if (head < tail) + head = head + sig_hdr.max_slots; + slots_used = (head - tail); + slots_avail = sig_hdr.max_signals - slots_used; + return (int)slots_avail; +} +EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); + +int +visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) +{ + struct signal_queue_header sig_hdr; + + if (!sig_read_header(channel, queue, &sig_hdr)) + return 0; + return (int)sig_hdr.max_signals; +} +EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots); + +static void +sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) +{ + seq_printf(seq, "Signal Queue #%d\n", which); + seq_printf(seq, " VersionId = %lu\n", (ulong)q->version); + seq_printf(seq, " Type = %lu\n", (ulong)q->chtype); + seq_printf(seq, " oSignalBase = %llu\n", + (long long)q->sig_base_offset); + seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size); + seq_printf(seq, " MaxSignalSlots = %lu\n", + (ulong)q->max_slots); + seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals); + seq_printf(seq, " FeatureFlags = %-16.16Lx\n", + (long long)q->features); + seq_printf(seq, " NumSignalsSent = %llu\n", + (long long)q->num_sent); + seq_printf(seq, " NumSignalsReceived = %llu\n", + (long long)q->num_received); + seq_printf(seq, " NumOverflows = %llu\n", + (long long)q->num_overflows); + seq_printf(seq, " Head = %lu\n", (ulong)q->head); + seq_printf(seq, " Tail = %lu\n", (ulong)q->tail); +} + +void +visorchannel_debug(struct visorchannel *channel, int num_queues, + struct seq_file *seq, u32 off) +{ + HOSTADDRESS addr = 0; + ulong nbytes = 0, nbytes_region = 0; + struct memregion *memregion = NULL; + struct channel_header hdr; + struct channel_header *phdr = &hdr; + int i = 0; + int errcode = 0; + + if (!channel) + return; + memregion = channel->memregion; + if (!memregion) + return; + + addr = visor_memregion_get_physaddr(memregion); + nbytes_region = visor_memregion_get_nbytes(memregion); + errcode = visorchannel_read(channel, off, + phdr, sizeof(struct channel_header)); + if (errcode < 0) { + seq_printf(seq, + "Read of channel header failed with errcode=%d)\n", + errcode); + if (off == 0) { + phdr = &channel->chan_hdr; + seq_puts(seq, "(following data may be stale)\n"); + } else { + return; + } + } + nbytes = (ulong)(phdr->size); + seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n", + addr + off, nbytes, nbytes_region); + seq_printf(seq, "Type = %pUL\n", &phdr->chtype); + seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid); + seq_printf(seq, "Signature = 0x%-16.16Lx\n", + (long long)phdr->signature); + seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state); + seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state); + seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot); + seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os); + seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size); + seq_printf(seq, "Size = %llu\n", (long long)phdr->size); + seq_printf(seq, "Features = 0x%-16.16llx\n", + (long long)phdr->features); + seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n", + (long long)phdr->partition_handle); + seq_printf(seq, "Handle = 0x%-16.16llx\n", + (long long)phdr->handle); + seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id); + seq_printf(seq, "oChannelSpace = %llu\n", + (long long)phdr->ch_space_offset); + if ((phdr->ch_space_offset == 0) || (errcode < 0)) + ; + else + for (i = 0; i < num_queues; i++) { + struct signal_queue_header q; + + errcode = visorchannel_read(channel, + off + + phdr->ch_space_offset + + (i * sizeof(q)), + &q, sizeof(q)); + if (errcode < 0) { + seq_printf(seq, + "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n", + i, addr, errcode); + continue; + } + sigqueue_debug(&q, i, seq); + } + seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n", + addr + off, nbytes); +} +EXPORT_SYMBOL_GPL(visorchannel_debug); + +void +visorchannel_dump_section(struct visorchannel *chan, char *s, + int off, int len, struct seq_file *seq) +{ + char *buf, *tbuf, *fmtbuf; + int fmtbufsize = 0; + int i; + int errcode = 0; + + fmtbufsize = 100 * COVQ(len, 16); + buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY); + if (!buf) + return; + fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY); + if (!fmtbuf) + goto fmt_failed; + + errcode = visorchannel_read(chan, off, buf, len); + if (errcode < 0) + goto read_failed; + seq_printf(seq, "channel %s:\n", s); + tbuf = buf; + while (len > 0) { + i = (len < 16) ? len : 16; + hex_dump_to_buffer(tbuf, i, 16, 1, fmtbuf, fmtbufsize, TRUE); + seq_printf(seq, "%s\n", fmtbuf); + tbuf += 16; + len -= 16; + } + +read_failed: + kfree(fmtbuf); +fmt_failed: + kfree(buf); +} +EXPORT_SYMBOL_GPL(visorchannel_dump_section); diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h deleted file mode 100644 index 63f1b9760373..000000000000 --- a/drivers/staging/unisys/visorchannel/visorchannel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* visorchannel.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHANNEL_H__ -#define __VISORCHANNEL_H__ - -#include - -#include "memregion.h" -#include "channel.h" -#ifndef HOSTADDRESS -#define HOSTADDRESS u64 -#endif -#ifndef BOOL -#define BOOL int -#endif - -/* Note that for visorchannel_create() and visorchannel_create_overlapped(), - * and arguments may be 0 if we are a channel CLIENT. - * In this case, the values can simply be read from the channel header. - */ -struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, - ulong channel_bytes, uuid_le guid); -struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, - struct visorchannel *parent, - ulong off, uuid_le guid); -struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, - ulong channel_bytes, - uuid_le guid); -struct visorchannel *visorchannel_create_overlapped_with_lock( - ulong channel_bytes, - struct visorchannel *parent, - ulong off, uuid_le guid); -void visorchannel_destroy(struct visorchannel *channel); -int visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_clear(struct visorchannel *channel, ulong offset, - u8 ch, ulong nbytes); -BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, - void *msg); -BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, - void *msg); -int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, - u32 queue); -int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); -HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); -ulong visorchannel_get_nbytes(struct visorchannel *channel); -char *visorchannel_id(struct visorchannel *channel, char *s); -char *visorchannel_zoneid(struct visorchannel *channel, char *s); -u64 visorchannel_get_clientpartition(struct visorchannel *channel); -uuid_le visorchannel_get_uuid(struct visorchannel *channel); -struct memregion *visorchannel_get_memregion(struct visorchannel *channel); -char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off); -void visorchannel_dump_section(struct visorchannel *chan, char *s, - int off, int len, struct seq_file *seq); -void __iomem *visorchannel_get_header(struct visorchannel *channel); - -#endif diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c deleted file mode 100644 index 9ae5f752bbf5..000000000000 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ /dev/null @@ -1,663 +0,0 @@ -/* visorchannel_funcs.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * This provides Supervisor channel communication primitives, which are - * independent of the mechanism used to access the channel data. All channel - * data is accessed using the memregion abstraction. (memregion has both - * a CM2 implementation and a direct memory implementation.) - */ - -#include "globals.h" -#include "visorchannel.h" -#include - -#define MYDRVNAME "visorchannel" - -struct visorchannel { - struct memregion *memregion; /* from visor_memregion_create() */ - struct channel_header chan_hdr; - uuid_le guid; - ulong size; - BOOL needs_lock; /* channel creator knows if more than one - * thread will be inserting or removing */ - spinlock_t insert_lock; /* protect head writes in chan_hdr */ - spinlock_t remove_lock; /* protect tail writes in chan_hdr */ - - struct { - struct signal_queue_header req_queue; - struct signal_queue_header rsp_queue; - struct signal_queue_header event_queue; - struct signal_queue_header ack_queue; - } safe_uis_queue; -}; - -/* Creates the struct visorchannel abstraction for a data area in memory, - * but does NOT modify this data area. - */ -static struct visorchannel * -visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes, - struct visorchannel *parent, ulong off, uuid_le guid, - BOOL needs_lock) -{ - struct visorchannel *p = NULL; - void *rc = NULL; - - p = kmalloc(sizeof(*p), GFP_KERNEL|__GFP_NORETRY); - if (!p) { - rc = NULL; - goto cleanup; - } - p->memregion = NULL; - p->needs_lock = needs_lock; - spin_lock_init(&p->insert_lock); - spin_lock_init(&p->remove_lock); - - /* prepare chan_hdr (abstraction to read/write channel memory) */ - if (!parent) - p->memregion = - visor_memregion_create(physaddr, - sizeof(struct channel_header)); - else - p->memregion = - visor_memregion_create_overlapped(parent->memregion, - off, sizeof(struct channel_header)); - if (!p->memregion) { - rc = NULL; - goto cleanup; - } - if (visor_memregion_read(p->memregion, 0, &p->chan_hdr, - sizeof(struct channel_header)) < 0) { - rc = NULL; - goto cleanup; - } - if (channel_bytes == 0) - /* we had better be a CLIENT of this channel */ - channel_bytes = (ulong)p->chan_hdr.size; - if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) - /* we had better be a CLIENT of this channel */ - guid = p->chan_hdr.chtype; - if (visor_memregion_resize(p->memregion, channel_bytes) < 0) { - rc = NULL; - goto cleanup; - } - p->size = channel_bytes; - p->guid = guid; - - rc = p; -cleanup: - - if (!rc) { - if (!p) { - visorchannel_destroy(p); - p = NULL; - } - } - return rc; -} - -struct visorchannel * -visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) -{ - return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, - FALSE); -} -EXPORT_SYMBOL_GPL(visorchannel_create); - -struct visorchannel * -visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, - uuid_le guid) -{ - return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, - TRUE); -} -EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); - -struct visorchannel * -visorchannel_create_overlapped(ulong channel_bytes, - struct visorchannel *parent, ulong off, - uuid_le guid) -{ - return visorchannel_create_guts(0, channel_bytes, parent, off, guid, - FALSE); -} -EXPORT_SYMBOL_GPL(visorchannel_create_overlapped); - -struct visorchannel * -visorchannel_create_overlapped_with_lock(ulong channel_bytes, - struct visorchannel *parent, ulong off, - uuid_le guid) -{ - return visorchannel_create_guts(0, channel_bytes, parent, off, guid, - TRUE); -} -EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock); - -void -visorchannel_destroy(struct visorchannel *channel) -{ - if (!channel) - return; - if (channel->memregion) { - visor_memregion_destroy(channel->memregion); - channel->memregion = NULL; - } - kfree(channel); -} -EXPORT_SYMBOL_GPL(visorchannel_destroy); - -HOSTADDRESS -visorchannel_get_physaddr(struct visorchannel *channel) -{ - return visor_memregion_get_physaddr(channel->memregion); -} -EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); - -ulong -visorchannel_get_nbytes(struct visorchannel *channel) -{ - return channel->size; -} -EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); - -char * -visorchannel_uuid_id(uuid_le *guid, char *s) -{ - sprintf(s, "%pUL", guid); - return s; -} -EXPORT_SYMBOL_GPL(visorchannel_uuid_id); - -char * -visorchannel_id(struct visorchannel *channel, char *s) -{ - return visorchannel_uuid_id(&channel->guid, s); -} -EXPORT_SYMBOL_GPL(visorchannel_id); - -char * -visorchannel_zoneid(struct visorchannel *channel, char *s) -{ - return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); -} -EXPORT_SYMBOL_GPL(visorchannel_zoneid); - -HOSTADDRESS -visorchannel_get_clientpartition(struct visorchannel *channel) -{ - return channel->chan_hdr.partition_handle; -} -EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); - -uuid_le -visorchannel_get_uuid(struct visorchannel *channel) -{ - return channel->guid; -} -EXPORT_SYMBOL_GPL(visorchannel_get_uuid); - -struct memregion * -visorchannel_get_memregion(struct visorchannel *channel) -{ - return channel->memregion; -} -EXPORT_SYMBOL_GPL(visorchannel_get_memregion); - -int -visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes) -{ - int rc = visor_memregion_read(channel->memregion, offset, - local, nbytes); - if ((rc >= 0) && (offset == 0) && - (nbytes >= sizeof(struct channel_header))) { - memcpy(&channel->chan_hdr, local, - sizeof(struct channel_header)); - } - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_read); - -int -visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes) -{ - if (offset == 0 && nbytes >= sizeof(struct channel_header)) - memcpy(&channel->chan_hdr, local, - sizeof(struct channel_header)); - return visor_memregion_write(channel->memregion, offset, local, nbytes); -} -EXPORT_SYMBOL_GPL(visorchannel_write); - -int -visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, - ulong nbytes) -{ - int rc = -1; - int bufsize = 65536; - int written = 0; - u8 *buf = vmalloc(bufsize); - - if (!buf) - goto cleanup; - - memset(buf, ch, bufsize); - while (nbytes > 0) { - ulong thisbytes = bufsize; - int x = -1; - - if (nbytes < thisbytes) - thisbytes = nbytes; - x = visor_memregion_write(channel->memregion, offset + written, - buf, thisbytes); - if (x < 0) { - rc = x; - goto cleanup; - } - written += thisbytes; - nbytes -= thisbytes; - } - rc = 0; - -cleanup: - if (buf) { - vfree(buf); - buf = NULL; - } - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_clear); - -void __iomem * -visorchannel_get_header(struct visorchannel *channel) -{ - return (void __iomem *)&channel->chan_hdr; -} -EXPORT_SYMBOL_GPL(visorchannel_get_header); - -/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a - * channel header - */ -#define SIG_QUEUE_OFFSET(chan_hdr, q) \ - ((chan_hdr)->ch_space_offset + \ - ((q) * sizeof(struct signal_queue_header))) - -/** Return offset of a specific queue entry (data) from the beginning of a - * channel header - */ -#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ - (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ - ((slot) * (sig_hdr)->signal_size)) - -/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back - * into host memory - */ -#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ - (visor_memregion_write(channel->memregion, \ - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue)+ \ - offsetof(struct signal_queue_header, FIELD),\ - &((sig_hdr)->FIELD), \ - sizeof((sig_hdr)->FIELD)) >= 0) - -static BOOL -sig_read_header(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr) -{ - BOOL rc = FALSE; - - if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) - goto cleanup; - - /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ - - if (visor_memregion_read(channel->memregion, - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue), - sig_hdr, - sizeof(struct signal_queue_header)) < 0) { - goto cleanup; - } - rc = TRUE; -cleanup: - return rc; -} - -static BOOL -sig_do_data(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr, u32 slot, void *data, - BOOL is_write) -{ - BOOL rc = FALSE; - int signal_data_offset = SIG_DATA_OFFSET(&channel->chan_hdr, queue, - sig_hdr, slot); - if (is_write) { - if (visor_memregion_write(channel->memregion, - signal_data_offset, - data, sig_hdr->signal_size) < 0) { - goto cleanup; - } - } else { - if (visor_memregion_read(channel->memregion, signal_data_offset, - data, sig_hdr->signal_size) < 0) { - goto cleanup; - } - } - rc = TRUE; -cleanup: - return rc; -} - -static inline BOOL -sig_read_data(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr, u32 slot, void *data) -{ - return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE); -} - -static inline BOOL -sig_write_data(struct visorchannel *channel, u32 queue, - struct signal_queue_header *sig_hdr, u32 slot, void *data) -{ - return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE); -} - -static inline unsigned char -safe_sig_queue_validate(struct signal_queue_header *psafe_sqh, - struct signal_queue_header *punsafe_sqh, - u32 *phead, u32 *ptail) -{ - if ((*phead >= psafe_sqh->max_slots) || - (*ptail >= psafe_sqh->max_slots)) { - /* Choose 0 or max, maybe based on current tail value */ - *phead = 0; - *ptail = 0; - - /* Sync with client as necessary */ - punsafe_sqh->head = *phead; - punsafe_sqh->tail = *ptail; - - return 0; - } - return 1; -} /* end safe_sig_queue_validate */ - -static BOOL -signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return FALSE; - if (sig_hdr.head == sig_hdr.tail) - return FALSE; /* no signals to remove */ - - sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; - if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) - return FALSE; - sig_hdr.num_received++; - - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. - */ - mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) - return FALSE; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) - return FALSE; - return TRUE; -} - -BOOL -visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) -{ - BOOL rc; - - if (channel->needs_lock) { - spin_lock(&channel->remove_lock); - rc = signalremove_inner(channel, queue, msg); - spin_unlock(&channel->remove_lock); - } else { - rc = signalremove_inner(channel, queue, msg); - } - - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_signalremove); - -static BOOL -signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return FALSE; - - sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); - if (sig_hdr.head == sig_hdr.tail) { - sig_hdr.num_overflows++; - visor_memregion_write(channel->memregion, - SIG_QUEUE_OFFSET(&channel->chan_hdr, - queue) + - offsetof(struct signal_queue_header, - num_overflows), - &(sig_hdr.num_overflows), - sizeof(sig_hdr.num_overflows)); - return FALSE; - } - - if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) - return FALSE; - - sig_hdr.num_sent++; - - /* For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. - */ - mb(); /* required for channel synch */ - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) - return FALSE; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) - return FALSE; - - return TRUE; -} - -BOOL -visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) -{ - BOOL rc; - - if (channel->needs_lock) { - spin_lock(&channel->insert_lock); - rc = signalinsert_inner(channel, queue, msg); - spin_unlock(&channel->insert_lock); - } else { - rc = signalinsert_inner(channel, queue, msg); - } - - return rc; -} -EXPORT_SYMBOL_GPL(visorchannel_signalinsert); - -int -visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - u32 slots_avail, slots_used; - u32 head, tail; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - head = sig_hdr.head; - tail = sig_hdr.tail; - if (head < tail) - head = head + sig_hdr.max_slots; - slots_used = (head - tail); - slots_avail = sig_hdr.max_signals - slots_used; - return (int)slots_avail; -} -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); - -int -visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) -{ - struct signal_queue_header sig_hdr; - - if (!sig_read_header(channel, queue, &sig_hdr)) - return 0; - return (int)sig_hdr.max_signals; -} -EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots); - -static void -sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) -{ - seq_printf(seq, "Signal Queue #%d\n", which); - seq_printf(seq, " VersionId = %lu\n", (ulong)q->version); - seq_printf(seq, " Type = %lu\n", (ulong)q->chtype); - seq_printf(seq, " oSignalBase = %llu\n", - (long long)q->sig_base_offset); - seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size); - seq_printf(seq, " MaxSignalSlots = %lu\n", - (ulong)q->max_slots); - seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals); - seq_printf(seq, " FeatureFlags = %-16.16Lx\n", - (long long)q->features); - seq_printf(seq, " NumSignalsSent = %llu\n", - (long long)q->num_sent); - seq_printf(seq, " NumSignalsReceived = %llu\n", - (long long)q->num_received); - seq_printf(seq, " NumOverflows = %llu\n", - (long long)q->num_overflows); - seq_printf(seq, " Head = %lu\n", (ulong)q->head); - seq_printf(seq, " Tail = %lu\n", (ulong)q->tail); -} - -void -visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off) -{ - HOSTADDRESS addr = 0; - ulong nbytes = 0, nbytes_region = 0; - struct memregion *memregion = NULL; - struct channel_header hdr; - struct channel_header *phdr = &hdr; - int i = 0; - int errcode = 0; - - if (!channel) - return; - memregion = channel->memregion; - if (!memregion) - return; - - addr = visor_memregion_get_physaddr(memregion); - nbytes_region = visor_memregion_get_nbytes(memregion); - errcode = visorchannel_read(channel, off, - phdr, sizeof(struct channel_header)); - if (errcode < 0) { - seq_printf(seq, - "Read of channel header failed with errcode=%d)\n", - errcode); - if (off == 0) { - phdr = &channel->chan_hdr; - seq_puts(seq, "(following data may be stale)\n"); - } else { - return; - } - } - nbytes = (ulong)(phdr->size); - seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n", - addr + off, nbytes, nbytes_region); - seq_printf(seq, "Type = %pUL\n", &phdr->chtype); - seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid); - seq_printf(seq, "Signature = 0x%-16.16Lx\n", - (long long)phdr->signature); - seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state); - seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state); - seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot); - seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os); - seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size); - seq_printf(seq, "Size = %llu\n", (long long)phdr->size); - seq_printf(seq, "Features = 0x%-16.16llx\n", - (long long)phdr->features); - seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n", - (long long)phdr->partition_handle); - seq_printf(seq, "Handle = 0x%-16.16llx\n", - (long long)phdr->handle); - seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id); - seq_printf(seq, "oChannelSpace = %llu\n", - (long long)phdr->ch_space_offset); - if ((phdr->ch_space_offset == 0) || (errcode < 0)) - ; - else - for (i = 0; i < num_queues; i++) { - struct signal_queue_header q; - - errcode = visorchannel_read(channel, - off + - phdr->ch_space_offset + - (i * sizeof(q)), - &q, sizeof(q)); - if (errcode < 0) { - seq_printf(seq, - "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n", - i, addr, errcode); - continue; - } - sigqueue_debug(&q, i, seq); - } - seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n", - addr + off, nbytes); -} -EXPORT_SYMBOL_GPL(visorchannel_debug); - -void -visorchannel_dump_section(struct visorchannel *chan, char *s, - int off, int len, struct seq_file *seq) -{ - char *buf, *tbuf, *fmtbuf; - int fmtbufsize = 0; - int i; - int errcode = 0; - - fmtbufsize = 100 * COVQ(len, 16); - buf = kmalloc(len, GFP_KERNEL|__GFP_NORETRY); - if (!buf) - return; - fmtbuf = kmalloc(fmtbufsize, GFP_KERNEL|__GFP_NORETRY); - if (!fmtbuf) - goto fmt_failed; - - errcode = visorchannel_read(chan, off, buf, len); - if (errcode < 0) - goto read_failed; - seq_printf(seq, "channel %s:\n", s); - tbuf = buf; - while (len > 0) { - i = (len < 16) ? len : 16; - hex_dump_to_buffer(tbuf, i, 16, 1, fmtbuf, fmtbufsize, TRUE); - seq_printf(seq, "%s\n", fmtbuf); - tbuf += 16; - len -= 16; - } - -read_failed: - kfree(fmtbuf); -fmt_failed: - kfree(buf); -} -EXPORT_SYMBOL_GPL(visorchannel_dump_section); diff --git a/drivers/staging/unisys/visorchipset/Kconfig b/drivers/staging/unisys/visorchipset/Kconfig index b03bfc5c3043..2030592d2023 100644 --- a/drivers/staging/unisys/visorchipset/Kconfig +++ b/drivers/staging/unisys/visorchipset/Kconfig @@ -6,6 +6,7 @@ config UNISYS_VISORCHIPSET tristate "Unisys visorchipset driver" select UNISYS_VISORUTIL select UNISYS_VISORCHANNEL + select UNISYS_VISORBUS ---help--- If you say Y here, you will enable the Unisys visorchipset driver. diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile index 12686906bef3..1bf6699579ec 100644 --- a/drivers/staging/unisys/visorchipset/Makefile +++ b/drivers/staging/unisys/visorchipset/Makefile @@ -8,8 +8,8 @@ visorchipset-y := visorchipset_main.o file.o parser.o ccflags-y += -Idrivers/staging/unisys/include ccflags-y += -Idrivers/staging/unisys/uislib -ccflags-y += -Idrivers/staging/unisys/visorchannel ccflags-y += -Idrivers/staging/unisys/common-spar/include ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels ccflags-y += -Idrivers/staging/unisys/visorutil +ccflags-y += -Idrivers/staging/unisys/visorbus ccflags-y += -Iinclude/generated -- cgit v1.2.3-55-g7522 From f6439218bb0d6e40fdb90a45333b7bce5be2424d Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Tue, 5 May 2015 18:36:02 -0400 Subject: staging: unisys: Dissolve visorchannel.h This header is needed by other drivers and should be in a global namespace. In addition, functionally it is part of visorbus, so roll the contents into that header file. Signed-off-by: Don Zickus Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus.h | 50 +++++++++++++- drivers/staging/unisys/visorbus/visorbus_private.h | 2 +- drivers/staging/unisys/visorbus/visorchannel.h | 76 ---------------------- .../staging/unisys/visorbus/visorchannel_funcs.c | 2 +- drivers/staging/unisys/visorchipset/file.c | 2 +- .../unisys/visorchipset/visorchipset_main.c | 2 +- 6 files changed, 53 insertions(+), 81 deletions(-) delete mode 100644 drivers/staging/unisys/visorbus/visorchannel.h (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorbus/visorbus.h b/drivers/staging/unisys/visorbus/visorbus.h index 856fa3f6419c..3956a3df80eb 100644 --- a/drivers/staging/unisys/visorbus/visorbus.h +++ b/drivers/staging/unisys/visorbus/visorbus.h @@ -35,8 +35,12 @@ #include #include "periodic_work.h" -#include "visorchannel.h" #include "channel.h" +#include "memregion.h" + +#ifndef HOSTADDRESS +#define HOSTADDRESS u64 +#endif struct visor_driver; struct visor_device; @@ -163,4 +167,48 @@ void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); #endif +/* Note that for visorchannel_create() and visorchannel_create_overlapped(), + * and arguments may be 0 if we are a channel CLIENT. + * In this case, the values can simply be read from the channel header. + */ +struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, + ulong channel_bytes, uuid_le guid); +struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, + ulong channel_bytes, + uuid_le guid); +struct visorchannel *visorchannel_create_overlapped_with_lock( + ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_write(struct visorchannel *channel, ulong offset, + void *local, ulong nbytes); +int visorchannel_clear(struct visorchannel *channel, ulong offset, + u8 ch, ulong nbytes); +BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); +BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); +int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, + u32 queue); +int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); +HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +uuid_le visorchannel_get_uuid(struct visorchannel *channel); +struct memregion *visorchannel_get_memregion(struct visorchannel *channel); +char *visorchannel_uuid_id(uuid_le *guid, char *s); +void visorchannel_debug(struct visorchannel *channel, int num_queues, + struct seq_file *seq, u32 off); +void visorchannel_dump_section(struct visorchannel *chan, char *s, + int off, int len, struct seq_file *seq); +void __iomem *visorchannel_get_header(struct visorchannel *channel); + #endif diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 2b61312789da..47ab4887661d 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -21,7 +21,7 @@ #include "timskmod.h" #include "visorbus.h" #include "visorchipset.h" -#include "visorchannel.h" +#include "visorbus.h" #include "version.h" #include "vbuschannel.h" diff --git a/drivers/staging/unisys/visorbus/visorchannel.h b/drivers/staging/unisys/visorbus/visorchannel.h deleted file mode 100644 index 63f1b9760373..000000000000 --- a/drivers/staging/unisys/visorbus/visorchannel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* visorchannel.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHANNEL_H__ -#define __VISORCHANNEL_H__ - -#include - -#include "memregion.h" -#include "channel.h" -#ifndef HOSTADDRESS -#define HOSTADDRESS u64 -#endif -#ifndef BOOL -#define BOOL int -#endif - -/* Note that for visorchannel_create() and visorchannel_create_overlapped(), - * and arguments may be 0 if we are a channel CLIENT. - * In this case, the values can simply be read from the channel header. - */ -struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, - ulong channel_bytes, uuid_le guid); -struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, - struct visorchannel *parent, - ulong off, uuid_le guid); -struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, - ulong channel_bytes, - uuid_le guid); -struct visorchannel *visorchannel_create_overlapped_with_lock( - ulong channel_bytes, - struct visorchannel *parent, - ulong off, uuid_le guid); -void visorchannel_destroy(struct visorchannel *channel); -int visorchannel_read(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_write(struct visorchannel *channel, ulong offset, - void *local, ulong nbytes); -int visorchannel_clear(struct visorchannel *channel, ulong offset, - u8 ch, ulong nbytes); -BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, - void *msg); -BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, - void *msg); -int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, - u32 queue); -int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); -HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); -ulong visorchannel_get_nbytes(struct visorchannel *channel); -char *visorchannel_id(struct visorchannel *channel, char *s); -char *visorchannel_zoneid(struct visorchannel *channel, char *s); -u64 visorchannel_get_clientpartition(struct visorchannel *channel); -uuid_le visorchannel_get_uuid(struct visorchannel *channel); -struct memregion *visorchannel_get_memregion(struct visorchannel *channel); -char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(struct visorchannel *channel, int num_queues, - struct seq_file *seq, u32 off); -void visorchannel_dump_section(struct visorchannel *chan, char *s, - int off, int len, struct seq_file *seq); -void __iomem *visorchannel_get_header(struct visorchannel *channel); - -#endif diff --git a/drivers/staging/unisys/visorbus/visorchannel_funcs.c b/drivers/staging/unisys/visorbus/visorchannel_funcs.c index 9ae5f752bbf5..b61f9549d352 100644 --- a/drivers/staging/unisys/visorbus/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorbus/visorchannel_funcs.c @@ -23,7 +23,7 @@ */ #include "globals.h" -#include "visorchannel.h" +#include "visorbus.h" #include #define MYDRVNAME "visorchannel" diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index a17027c211a2..9822e9d1d6be 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -24,7 +24,7 @@ #include "version.h" #include "visorchipset.h" #include "visorchipset_umode.h" -#include "visorchannel.h" +#include "visorbus.h" #include "uisutils.h" #include "file.h" diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 5ea6f9e81fba..a8448c23a89b 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -18,7 +18,7 @@ #include "version.h" #include "visorchipset.h" #include "procobjecttree.h" -#include "visorchannel.h" +#include "visorbus.h" #include "periodic_work.h" #include "file.h" #include "parser.h" -- cgit v1.2.3-55-g7522 From 98e50b8a5460971aee9bb4ff9786fa158f69cd38 Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Tue, 5 May 2015 18:36:04 -0400 Subject: staging: unisys: Remove unused driver The visorchannel feature is rolled into visorbus now and its headers are public under visorbus.h. Remove the unused driver, the old header file and all the ccflag includes in the Makefile. Also remove VISORCHANNEL from all Kconfigs as it is not needed. Signed-off-by: Don Zickus Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/Kconfig b/drivers/staging/unisys/visorchipset/Kconfig index 2030592d2023..01d9a9a0e904 100644 --- a/drivers/staging/unisys/visorchipset/Kconfig +++ b/drivers/staging/unisys/visorchipset/Kconfig @@ -5,7 +5,6 @@ config UNISYS_VISORCHIPSET tristate "Unisys visorchipset driver" select UNISYS_VISORUTIL - select UNISYS_VISORCHANNEL select UNISYS_VISORBUS ---help--- If you say Y here, you will enable the Unisys visorchipset driver. -- cgit v1.2.3-55-g7522 From d777ba2e69bd2b7304adfabad6d1e495bd1b4f99 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Tue, 5 May 2015 18:36:11 -0400 Subject: staging: unisys: remove visorchipset_umode.h removes visorchipset_umode.h and pass functionality to visorchipset.h Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 1 - drivers/staging/unisys/visorchipset/visorchipset.h | 1 + .../unisys/visorchipset/visorchipset_umode.h | 35 ---------------------- 3 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/visorchipset_umode.h (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 9822e9d1d6be..153f736dd76c 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -23,7 +23,6 @@ #include #include "version.h" #include "visorchipset.h" -#include "visorchipset_umode.h" #include "visorbus.h" #include "uisutils.h" #include "file.h" diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 1d66c3766c42..dcf8a2345a59 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -28,6 +28,7 @@ #include "vbushelper.h" #define MYDRVNAME "visorchipset" +#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 /** Describes the state from the perspective of which controlvm messages have * been received for a bus or device. diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h deleted file mode 100644 index 8af5bf33883c..000000000000 --- a/drivers/staging/unisys/visorchipset/visorchipset_umode.h +++ /dev/null @@ -1,35 +0,0 @@ -/* visorchipset_umode.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/** @file ********************************************************************* - * - * This describes structures needed for the interface between the - * visorchipset driver and a user-mode component that opens the device. - * - ****************************************************************************** - */ - -#ifndef __VISORCHIPSET_UMODE_H -#define __VISORCHIPSET_UMODE_H - -/** The user-mode program can access the control channel buffer directly - * via this memory map. - */ -#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 -#define VISORCHIPSET_MMAP_CONTROLCHANSIZE 0x00400000 /* 4MB */ - -#endif /* __VISORCHIPSET_UMODE_H */ -- cgit v1.2.3-55-g7522 From 95e967569dfd9bbe38bb533650c8a6bfb12f9523 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Tue, 5 May 2015 18:36:12 -0400 Subject: staging: unisys: moving file.h functionality to visorchipset.h this patch simply migrates file.h functionality to visorchipset.h Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/file.c | 5 +++-- drivers/staging/unisys/visorchipset/file.h | 25 ---------------------- drivers/staging/unisys/visorchipset/visorchipset.h | 4 +++- .../unisys/visorchipset/visorchipset_main.c | 1 - 4 files changed, 6 insertions(+), 29 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/file.h (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 153f736dd76c..c0bd4161fb75 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -19,13 +19,14 @@ * communicate with the visorchipset driver using a device/file interface. */ -#include #include +#include + #include "version.h" #include "visorchipset.h" #include "visorbus.h" #include "uisutils.h" -#include "file.h" +#include "visorchipset.h" #define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h deleted file mode 100644 index 6ff28a1ae86e..000000000000 --- a/drivers/staging/unisys/visorchipset/file.h +++ /dev/null @@ -1,25 +0,0 @@ -/* file.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __FILE_H__ -#define __FILE_H__ - -int visorchipset_file_init(dev_t majorDev, - struct visorchannel **pControlVm_channel); -void visorchipset_file_cleanup(dev_t major_dev); - -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index dcf8a2345a59..93763ee8258b 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -188,5 +188,7 @@ void *visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, char *fn, int ln); void visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln); - +int visorchipset_file_init(dev_t majorDev, + struct visorchannel **pControlVm_channel); +void visorchipset_file_cleanup(dev_t major_dev); #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index a8448c23a89b..34ac17b4a6f5 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -20,7 +20,6 @@ #include "procobjecttree.h" #include "visorbus.h" #include "periodic_work.h" -#include "file.h" #include "parser.h" #include "uisutils.h" #include "controlvmcompletionstatus.h" -- cgit v1.2.3-55-g7522 From e3420ed6629530880c6b4dcc584cdfa0736a883a Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Tue, 5 May 2015 18:36:13 -0400 Subject: staging: unisys: remove file.c and pass functionality to visorchipset This patch trasitions the include files and functions from file.c and places them into visorchipset_main.c Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/Makefile | 2 +- drivers/staging/unisys/visorchipset/file.c | 162 --------------------- .../unisys/visorchipset/visorchipset_main.c | 136 ++++++++++++++++- 3 files changed, 136 insertions(+), 164 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/file.c (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile index 1bf6699579ec..6886cb7bd397 100644 --- a/drivers/staging/unisys/visorchipset/Makefile +++ b/drivers/staging/unisys/visorchipset/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset.o -visorchipset-y := visorchipset_main.o file.o parser.o +visorchipset-y := visorchipset_main.o parser.o ccflags-y += -Idrivers/staging/unisys/include ccflags-y += -Idrivers/staging/unisys/uislib diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c deleted file mode 100644 index c0bd4161fb75..000000000000 --- a/drivers/staging/unisys/visorchipset/file.c +++ /dev/null @@ -1,162 +0,0 @@ -/* file.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* This contains the implementation that allows a usermode program to - * communicate with the visorchipset driver using a device/file interface. - */ - -#include -#include - -#include "version.h" -#include "visorchipset.h" -#include "visorbus.h" -#include "uisutils.h" -#include "visorchipset.h" - -#define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c - -static struct cdev file_cdev; -static struct visorchannel **file_controlvm_channel; - -void -visorchipset_file_cleanup(dev_t major_dev) -{ - if (file_cdev.ops) - cdev_del(&file_cdev); - file_cdev.ops = NULL; - unregister_chrdev_region(major_dev, 1); -} - -static int -visorchipset_open(struct inode *inode, struct file *file) -{ - unsigned minor_number = iminor(inode); - - if (minor_number) - return -ENODEV; - file->private_data = NULL; - return 0; -} - -static int -visorchipset_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static int -visorchipset_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned long physaddr = 0; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - GUEST_PHYSICAL_ADDRESS addr = 0; - - /* sv_enable_dfp(); */ - if (offset & (PAGE_SIZE - 1)) - return -ENXIO; /* need aligned offsets */ - - switch (offset) { - case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: - vma->vm_flags |= VM_IO; - if (!*file_controlvm_channel) - return -ENXIO; - - visorchannel_read(*file_controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - gp_control_channel), - &addr, sizeof(addr)); - if (!addr) - return -ENXIO; - - physaddr = (unsigned long)addr; - if (remap_pfn_range(vma, vma->vm_start, - physaddr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - /*pgprot_noncached */ - (vma->vm_page_prot))) { - return -EAGAIN; - } - break; - default: - return -ENOSYS; - } - return 0; -} - -static long visorchipset_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - s64 adjustment; - s64 vrtc_offset; - - switch (cmd) { - case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: - /* get the physical rtc offset */ - vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); - if (copy_to_user((void __user *)arg, &vrtc_offset, - sizeof(vrtc_offset))) { - return -EFAULT; - } - return SUCCESS; - case VMCALL_UPDATE_PHYSICAL_TIME: - if (copy_from_user(&adjustment, (void __user *)arg, - sizeof(adjustment))) { - return -EFAULT; - } - return issue_vmcall_update_physical_time(adjustment); - default: - return -EFAULT; - } -} - -static const struct file_operations visorchipset_fops = { - .owner = THIS_MODULE, - .open = visorchipset_open, - .read = NULL, - .write = NULL, - .unlocked_ioctl = visorchipset_ioctl, - .release = visorchipset_release, - .mmap = visorchipset_mmap, -}; - -int -visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) -{ - int rc = 0; - - file_controlvm_channel = controlvm_channel; - cdev_init(&file_cdev, &visorchipset_fops); - file_cdev.owner = THIS_MODULE; - if (MAJOR(major_dev) == 0) { - rc = alloc_chrdev_region(&major_dev, 0, 1, MYDRVNAME); - /* dynamic major device number registration required */ - if (rc < 0) - return rc; - } else { - /* static major device number registration required */ - rc = register_chrdev_region(major_dev, 1, MYDRVNAME); - if (rc < 0) - return rc; - } - rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1); - if (rc < 0) { - unregister_chrdev_region(major_dev, 1); - return rc; - } - return 0; -} diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 34ac17b4a6f5..d5bd1a11ad88 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -16,7 +16,6 @@ */ #include "version.h" -#include "visorchipset.h" #include "procobjecttree.h" #include "visorbus.h" #include "periodic_work.h" @@ -24,7 +23,10 @@ #include "uisutils.h" #include "controlvmcompletionstatus.h" #include "guestlinuxdebug.h" +#include "visorchipset.h" +#include +#include #include #include #include @@ -56,6 +58,23 @@ static int visorchipset_testteardown; static int visorchipset_disable_controlvm; static int visorchipset_holdchipsetready; +static int +visorchipset_open(struct inode *inode, struct file *file) +{ + unsigned minor_number = iminor(inode); + + if (minor_number) + return -ENODEV; + file->private_data = NULL; + return 0; +} + +static int +visorchipset_release(struct inode *inode, struct file *file) +{ + return 0; +} + /* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, * we switch to slow polling mode. As soon as we get a controlvm * message, we switch back to fast polling mode. @@ -74,6 +93,8 @@ static struct delayed_work periodic_controlvm_work; static struct workqueue_struct *periodic_controlvm_workqueue; static DEFINE_SEMAPHORE(notifier_lock); +static struct cdev file_cdev; +static struct visorchannel **file_controlvm_channel; static struct controlvm_message_header g_chipset_msg_hdr; static const uuid_le spar_diag_pool_channel_protocol_uuid = SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; @@ -2169,6 +2190,110 @@ static ssize_t deviceenabled_store(struct device *dev, return count; } +static int +visorchipset_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long physaddr = 0; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + GUEST_PHYSICAL_ADDRESS addr = 0; + + /* sv_enable_dfp(); */ + if (offset & (PAGE_SIZE - 1)) + return -ENXIO; /* need aligned offsets */ + + switch (offset) { + case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: + vma->vm_flags |= VM_IO; + if (!*file_controlvm_channel) + return -ENXIO; + + visorchannel_read(*file_controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + gp_control_channel), + &addr, sizeof(addr)); + if (!addr) + return -ENXIO; + + physaddr = (unsigned long)addr; + if (remap_pfn_range(vma, vma->vm_start, + physaddr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + /*pgprot_noncached */ + (vma->vm_page_prot))) { + return -EAGAIN; + } + break; + default: + return -ENXIO; + } + return 0; +} + +static long visorchipset_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + s64 adjustment; + s64 vrtc_offset; + + switch (cmd) { + case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: + /* get the physical rtc offset */ + vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); + if (copy_to_user((void __user *)arg, &vrtc_offset, + sizeof(vrtc_offset))) { + return -EFAULT; + } + return SUCCESS; + case VMCALL_UPDATE_PHYSICAL_TIME: + if (copy_from_user(&adjustment, (void __user *)arg, + sizeof(adjustment))) { + return -EFAULT; + } + return issue_vmcall_update_physical_time(adjustment); + default: + return -EFAULT; + } +} + +static const struct file_operations visorchipset_fops = { + .owner = THIS_MODULE, + .open = visorchipset_open, + .read = NULL, + .write = NULL, + .unlocked_ioctl = visorchipset_ioctl, + .release = visorchipset_release, + .mmap = visorchipset_mmap, +}; + +int +visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) +{ + int rc = 0; + + file_controlvm_channel = controlvm_channel; + cdev_init(&file_cdev, &visorchipset_fops); + file_cdev.owner = THIS_MODULE; + if (MAJOR(major_dev) == 0) { + rc = alloc_chrdev_region(&major_dev, 0, 1, MYDRVNAME); + /* dynamic major device number registration required */ + if (rc < 0) + return rc; + } else { + /* static major device number registration required */ + rc = register_chrdev_region(major_dev, 1, MYDRVNAME); + if (rc < 0) + return rc; + } + rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1); + if (rc < 0) { + unregister_chrdev_region(major_dev, 1); + return rc; + } + return 0; +} + + + static int __init visorchipset_init(void) { @@ -2262,6 +2387,15 @@ cleanup: return rc; } +void +visorchipset_file_cleanup(dev_t major_dev) +{ + if (file_cdev.ops) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + unregister_chrdev_region(major_dev, 1); +} + static void visorchipset_exit(void) { -- cgit v1.2.3-55-g7522 From 4616881022a1ea98738966a6cbefab0ea1c085a9 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Tue, 5 May 2015 18:36:14 -0400 Subject: staging: unisys: move parser.[ch] functionality into visorchipset This patch moves includes files and functions from parser.[ch] into visorchipset. Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 2 +- drivers/staging/unisys/visorchipset/Makefile | 2 +- drivers/staging/unisys/visorchipset/parser.c | 430 --------------------- drivers/staging/unisys/visorchipset/parser.h | 45 --- drivers/staging/unisys/visorchipset/visorchipset.h | 24 +- .../unisys/visorchipset/visorchipset_main.c | 411 +++++++++++++++++++- 6 files changed, 432 insertions(+), 482 deletions(-) delete mode 100644 drivers/staging/unisys/visorchipset/parser.c delete mode 100644 drivers/staging/unisys/visorchipset/parser.h (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 13a270dc9b65..d7ca1163c1b1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -2040,7 +2040,7 @@ visorbus_init(void) POSTCODE_LINUX_3(DRIVER_ENTRY_PC, rc, POSTCODE_SEVERITY_INFO); bus_device_info_init(&clientbus_driverinfo, - "clientbus", MYDRVNAME, + "clientbus", "visorbus", VERSION, NULL); /* process module options */ diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile index 6886cb7bd397..e9168d8d69a5 100644 --- a/drivers/staging/unisys/visorchipset/Makefile +++ b/drivers/staging/unisys/visorchipset/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset.o -visorchipset-y := visorchipset_main.o parser.o +visorchipset-y := visorchipset_main.o ccflags-y += -Idrivers/staging/unisys/include ccflags-y += -Idrivers/staging/unisys/uislib diff --git a/drivers/staging/unisys/visorchipset/parser.c b/drivers/staging/unisys/visorchipset/parser.c deleted file mode 100644 index 6ca6da8772a8..000000000000 --- a/drivers/staging/unisys/visorchipset/parser.c +++ /dev/null @@ -1,430 +0,0 @@ -/* parser.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include "parser.h" -#include "memregion.h" -#include "controlvmchannel.h" -#include -#include -#include - -#define MYDRVNAME "visorchipset_parser" -#define CURRENT_FILE_PC VISOR_CHIPSET_PC_parser_c - -/* We will refuse to allocate more than this many bytes to copy data from - * incoming payloads. This serves as a throttling mechanism. - */ -#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) -static unsigned long controlvm_payload_bytes_buffered; - -struct parser_context { - unsigned long allocbytes; - unsigned long param_bytes; - u8 *curr; - unsigned long bytes_remaining; - bool byte_stream; - char data[0]; -}; - -static struct parser_context * -parser_init_guts(u64 addr, u32 bytes, bool local, - bool standard_payload_header, bool *retry) -{ - int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *rc = NULL; - struct parser_context *ctx = NULL; - struct memregion *rgn = NULL; - struct spar_controlvm_parameters_header *phdr = NULL; - - if (retry) - *retry = false; - if (!standard_payload_header) - /* alloc and 0 extra byte to ensure payload is - * '\0'-terminated - */ - allocbytes++; - if ((controlvm_payload_bytes_buffered + bytes) - > MAX_CONTROLVM_PAYLOAD_BYTES) { - if (retry) - *retry = true; - rc = NULL; - goto cleanup; - } - ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); - if (!ctx) { - if (retry) - *retry = true; - rc = NULL; - goto cleanup; - } - - ctx->allocbytes = allocbytes; - ctx->param_bytes = bytes; - ctx->curr = NULL; - ctx->bytes_remaining = 0; - ctx->byte_stream = false; - if (local) { - void *p; - - if (addr > virt_to_phys(high_memory - 1)) { - rc = NULL; - goto cleanup; - } - p = __va((unsigned long) (addr)); - memcpy(ctx->data, p, bytes); - } else { - rgn = visor_memregion_create(addr, bytes); - if (!rgn) { - rc = NULL; - goto cleanup; - } - if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { - rc = NULL; - goto cleanup; - } - } - if (!standard_payload_header) { - ctx->byte_stream = true; - rc = ctx; - goto cleanup; - } - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - if (phdr->total_length != bytes) { - rc = NULL; - goto cleanup; - } - if (phdr->total_length < phdr->header_length) { - rc = NULL; - goto cleanup; - } - if (phdr->header_length < - sizeof(struct spar_controlvm_parameters_header)) { - rc = NULL; - goto cleanup; - } - - rc = ctx; -cleanup: - if (rgn) { - visor_memregion_destroy(rgn); - rgn = NULL; - } - if (rc) { - controlvm_payload_bytes_buffered += ctx->param_bytes; - } else { - if (ctx) { - parser_done(ctx); - ctx = NULL; - } - } - return rc; -} - -struct parser_context * -parser_init(u64 addr, u32 bytes, bool local, bool *retry) -{ - return parser_init_guts(addr, bytes, local, true, retry); -} - -/* Call this instead of parser_init() if the payload area consists of just - * a sequence of bytes, rather than a struct spar_controlvm_parameters_header - * structures. Afterwards, you can call parser_simpleString_get() or - * parser_byteStream_get() to obtain the data. - */ -struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) -{ - return parser_init_guts(addr, bytes, local, false, retry); -} - -/* Obtain '\0'-terminated copy of string in payload area. - */ -char * -parser_simpleString_get(struct parser_context *ctx) -{ - if (!ctx->byte_stream) - return NULL; - return ctx->data; /* note this IS '\0'-terminated, because of - * the num of bytes we alloc+clear in - * parser_init_byteStream() */ -} - -/* Obtain a copy of the buffer in the payload area. - */ -void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) -{ - if (!ctx->byte_stream) - return NULL; - if (nbytes) - *nbytes = ctx->param_bytes; - return (void *)ctx->data; -} - -uuid_le -parser_id_get(struct parser_context *ctx) -{ - struct spar_controlvm_parameters_header *phdr = NULL; - - if (ctx == NULL) - return NULL_UUID_LE; - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - return phdr->id; -} - -void -parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string) -{ - struct spar_controlvm_parameters_header *phdr = NULL; - - if (ctx == NULL) - goto Away; - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - switch (which_string) { - case PARSERSTRING_INITIATOR: - ctx->curr = ctx->data + phdr->initiator_offset; - ctx->bytes_remaining = phdr->initiator_length; - break; - case PARSERSTRING_TARGET: - ctx->curr = ctx->data + phdr->target_offset; - ctx->bytes_remaining = phdr->target_length; - break; - case PARSERSTRING_CONNECTION: - ctx->curr = ctx->data + phdr->connection_offset; - ctx->bytes_remaining = phdr->connection_length; - break; - case PARSERSTRING_NAME: - ctx->curr = ctx->data + phdr->name_offset; - ctx->bytes_remaining = phdr->name_length; - break; - default: - break; - } - -Away: - return; -} - -void -parser_done(struct parser_context *ctx) -{ - if (!ctx) - return; - controlvm_payload_bytes_buffered -= ctx->param_bytes; - kfree(ctx); -} - -/** Return length of string not counting trailing spaces. */ -static int -string_length_no_trail(char *s, int len) -{ - int i = len - 1; - - while (i >= 0) { - if (!isspace(s[i])) - return i + 1; - i--; - } - return 0; -} - -/** Grab the next name and value out of the parameter buffer. - * The entire parameter buffer looks like this: - * =\0 - * =\0 - * ... - * \0 - * If successful, the next value is returned within the supplied - * buffer (the value is always upper-cased), and the corresponding - * is returned within a kmalloc()ed buffer, whose pointer is - * provided as the return value of this function. - * (The total number of bytes allocated is strlen()+1.) - * - * NULL is returned to indicate failure, which can occur for several reasons: - * - all = pairs have already been processed - * - bad parameter - * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within - * the confines of the parameter buffer) - * - the buffer is not large enough to hold the of the next - * parameter - */ -void * -parser_param_get(struct parser_context *ctx, char *nam, int namesize) -{ - u8 *pscan, *pnam = nam; - unsigned long nscan; - int value_length = -1, orig_value_length = -1; - void *value = NULL; - int i; - int closing_quote = 0; - - if (!ctx) - return NULL; - pscan = ctx->curr; - nscan = ctx->bytes_remaining; - if (nscan == 0) - return NULL; - if (*pscan == '\0') - /* This is the normal return point after you have processed - * all of the = pairs in a syntactically-valid - * parameter buffer. - */ - return NULL; - - /* skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - - while (*pscan != ':') { - if (namesize <= 0) - return NULL; - *pnam = toupper(*pscan); - pnam++; - namesize--; - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - if (namesize <= 0) - return NULL; - *pnam = '\0'; - nam[string_length_no_trail(nam, strlen(nam))] = '\0'; - - /* point to char immediately after ":" in ":" */ - pscan++; - nscan--; - /* skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - if (nscan == 0) - return NULL; - if (*pscan == '\'' || *pscan == '"') { - closing_quote = *pscan; - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - - /* look for a separator character, terminator character, or - * end of data - */ - for (i = 0, value_length = -1; i < nscan; i++) { - if (closing_quote) { - if (pscan[i] == '\0') - return NULL; - if (pscan[i] == closing_quote) { - value_length = i; - break; - } - } else - if (pscan[i] == ',' || pscan[i] == ';' - || pscan[i] == '\0') { - value_length = i; - break; - } - } - if (value_length < 0) { - if (closing_quote) - return NULL; - value_length = nscan; - } - orig_value_length = value_length; - if (closing_quote == 0) - value_length = string_length_no_trail(pscan, orig_value_length); - value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); - if (value == NULL) - return NULL; - memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; - - pscan += orig_value_length; - nscan -= orig_value_length; - - /* skip past separator or closing quote */ - if (nscan > 0) { - if (*pscan != '\0') { - pscan++; - nscan--; - } - } - - if (closing_quote && (nscan > 0)) { - /* we still need to skip around the real separator if present */ - /* first, skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - break; - } - if (nscan > 0) { - if (*pscan == ',' || *pscan == ';') { - pscan++; - nscan--; - } else if (*pscan != '\0') { - kfree(value); - value = NULL; - return NULL; - } - } - } - ctx->curr = pscan; - ctx->bytes_remaining = nscan; - return value; -} - -void * -parser_string_get(struct parser_context *ctx) -{ - u8 *pscan; - unsigned long nscan; - int value_length = -1; - void *value = NULL; - int i; - - if (!ctx) - return NULL; - pscan = ctx->curr; - nscan = ctx->bytes_remaining; - if (nscan == 0) - return NULL; - if (!pscan) - return NULL; - for (i = 0, value_length = -1; i < nscan; i++) - if (pscan[i] == '\0') { - value_length = i; - break; - } - if (value_length < 0) /* '\0' was not included in the length */ - value_length = nscan; - value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); - if (value == NULL) - return NULL; - if (value_length > 0) - memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; - return value; -} diff --git a/drivers/staging/unisys/visorchipset/parser.h b/drivers/staging/unisys/visorchipset/parser.h deleted file mode 100644 index 3fe17c0c64d2..000000000000 --- a/drivers/staging/unisys/visorchipset/parser.h +++ /dev/null @@ -1,45 +0,0 @@ -/* parser.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __PARSER_H__ -#define __PARSER_H__ - -#include - -#include "channel.h" - -typedef enum { - PARSERSTRING_INITIATOR, - PARSERSTRING_TARGET, - PARSERSTRING_CONNECTION, - PARSERSTRING_NAME, -} PARSER_WHICH_STRING; - -struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, - bool *tryAgain); -struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, - bool *retry); -void parser_param_start(struct parser_context *ctx, - PARSER_WHICH_STRING which_string); -void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); -void *parser_string_get(struct parser_context *ctx); -uuid_le parser_id_get(struct parser_context *ctx); -char *parser_simpleString_get(struct parser_context *ctx); -void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); -void parser_done(struct parser_context *ctx); - -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 93763ee8258b..264a3e9226ea 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -22,17 +22,37 @@ #include "channel.h" #include "controlvmchannel.h" -#include "parser.h" #include "procobjecttree.h" #include "vbusdeviceinfo.h" #include "vbushelper.h" -#define MYDRVNAME "visorchipset" #define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 /** Describes the state from the perspective of which controlvm messages have * been received for a bus or device. */ + +enum PARSER_WHICH_STRING { + PARSERSTRING_INITIATOR, + PARSERSTRING_TARGET, + PARSERSTRING_CONNECTION, + PARSERSTRING_NAME, +}; + +struct visorchannel; +struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, + bool *tryAgain); +struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, + bool *retry); +void parser_param_start(struct parser_context *ctx, + PARSER_WHICH_STRING which_string); +void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); +void *parser_string_get(struct parser_context *ctx); +uuid_le parser_id_get(struct parser_context *ctx); +char *parser_simpleString_get(struct parser_context *ctx); +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); +void parser_done(struct parser_context *ctx); + struct visorchipset_state { u32 created:1; u32 attached:1; diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index d5bd1a11ad88..dc9f1dc18306 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -15,16 +15,19 @@ * details. */ +#include "memregion.h" +#include "controlvmchannel.h" #include "version.h" #include "procobjecttree.h" #include "visorbus.h" #include "periodic_work.h" -#include "parser.h" #include "uisutils.h" #include "controlvmcompletionstatus.h" #include "guestlinuxdebug.h" #include "visorchipset.h" + +#include #include #include #include @@ -45,6 +48,7 @@ #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) /* * Module parameters */ @@ -57,6 +61,7 @@ static int visorchipset_clientregwait = 1; /* default is on */ static int visorchipset_testteardown; static int visorchipset_disable_controlvm; static int visorchipset_holdchipsetready; +static unsigned long controlvm_payload_bytes_buffered; static int visorchipset_open(struct inode *inode, struct file *file) @@ -89,6 +94,15 @@ static int clientregistered; #define MAX_CHIPSET_EVENTS 2 static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 }; +struct parser_context { + unsigned long allocbytes; + unsigned long param_bytes; + u8 *curr; + unsigned long bytes_remaining; + bool byte_stream; + char data[0]; +}; + static struct delayed_work periodic_controlvm_work; static struct workqueue_struct *periodic_controlvm_workqueue; static DEFINE_SEMAPHORE(notifier_lock); @@ -367,6 +381,397 @@ static void controlvm_respond_physdev_changestate( struct controlvm_message_header *msg_hdr, int response, struct spar_segment_state state); + +static struct parser_context * +parser_init_guts(u64 addr, u32 bytes, bool local, + bool standard_payload_header, bool *retry) +{ + int allocbytes = sizeof(struct parser_context) + bytes; + struct parser_context *rc = NULL; + struct parser_context *ctx = NULL; + struct memregion *rgn = NULL; + struct spar_controlvm_parameters_header *phdr = NULL; + + if (retry) + *retry = false; + if (!standard_payload_header) + /* alloc and 0 extra byte to ensure payload is + * '\0'-terminated + */ + allocbytes++; + if ((controlvm_payload_bytes_buffered + bytes) + > MAX_CONTROLVM_PAYLOAD_BYTES) { + if (retry) + *retry = true; + rc = NULL; + goto cleanup; + } + ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); + if (!ctx) { + if (retry) + *retry = true; + rc = NULL; + goto cleanup; + } + + ctx->allocbytes = allocbytes; + ctx->param_bytes = bytes; + ctx->curr = NULL; + ctx->bytes_remaining = 0; + ctx->byte_stream = false; + if (local) { + void *p; + + if (addr > virt_to_phys(high_memory - 1)) { + rc = NULL; + goto cleanup; + } + p = __va((unsigned long) (addr)); + memcpy(ctx->data, p, bytes); + } else { + rgn = visor_memregion_create(addr, bytes); + if (!rgn) { + rc = NULL; + goto cleanup; + } + if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { + rc = NULL; + goto cleanup; + } + } + if (!standard_payload_header) { + ctx->byte_stream = true; + rc = ctx; + goto cleanup; + } + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + if (phdr->total_length != bytes) { + rc = NULL; + goto cleanup; + } + if (phdr->total_length < phdr->header_length) { + rc = NULL; + goto cleanup; + } + if (phdr->header_length < + sizeof(struct spar_controlvm_parameters_header)) { + rc = NULL; + goto cleanup; + } + + rc = ctx; +cleanup: + if (rgn) { + visor_memregion_destroy(rgn); + rgn = NULL; + } + if (rc) { + controlvm_payload_bytes_buffered += ctx->param_bytes; + } else { + if (ctx) { + parser_done(ctx); + ctx = NULL; + } + } + return rc; +} + +struct parser_context * +parser_init(u64 addr, u32 bytes, bool local, bool *retry) +{ + return parser_init_guts(addr, bytes, local, true, retry); +} + +/* Call this instead of parser_init() if the payload area consists of just + * a sequence of bytes, rather than a struct spar_controlvm_parameters_header + * structures. Afterwards, you can call parser_simpleString_get() or + * parser_byteStream_get() to obtain the data. + */ +struct parser_context * +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) +{ + return parser_init_guts(addr, bytes, local, false, retry); +} + +/* Obtain '\0'-terminated copy of string in payload area. + */ +char * +parser_simpleString_get(struct parser_context *ctx) +{ + if (!ctx->byte_stream) + return NULL; + return ctx->data; /* note this IS '\0'-terminated, because of + * the num of bytes we alloc+clear in + * parser_init_byteStream() */ +} + +/* Obtain a copy of the buffer in the payload area. + */ +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) +{ + if (!ctx->byte_stream) + return NULL; + if (nbytes) + *nbytes = ctx->param_bytes; + return (void *)ctx->data; +} + +uuid_le +parser_id_get(struct parser_context *ctx) +{ + struct spar_controlvm_parameters_header *phdr = NULL; + + if (ctx == NULL) + return NULL_UUID_LE; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + return phdr->id; +} + +void +parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string) +{ + struct spar_controlvm_parameters_header *phdr = NULL; + + if (ctx == NULL) + goto Away; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + switch (which_string) { + case PARSERSTRING_INITIATOR: + ctx->curr = ctx->data + phdr->initiator_offset; + ctx->bytes_remaining = phdr->initiator_length; + break; + case PARSERSTRING_TARGET: + ctx->curr = ctx->data + phdr->target_offset; + ctx->bytes_remaining = phdr->target_length; + break; + case PARSERSTRING_CONNECTION: + ctx->curr = ctx->data + phdr->connection_offset; + ctx->bytes_remaining = phdr->connection_length; + break; + case PARSERSTRING_NAME: + ctx->curr = ctx->data + phdr->name_offset; + ctx->bytes_remaining = phdr->name_length; + break; + default: + break; + } + +Away: + return; +} + +void +parser_done(struct parser_context *ctx) +{ + if (!ctx) + return; + controlvm_payload_bytes_buffered -= ctx->param_bytes; + kfree(ctx); +} + +/** Return length of string not counting trailing spaces. */ +static int +string_length_no_trail(char *s, int len) +{ + int i = len - 1; + + while (i >= 0) { + if (!isspace(s[i])) + return i + 1; + i--; + } + return 0; +} + +/** Grab the next name and value out of the parameter buffer. + * The entire parameter buffer looks like this: + * =\0 + * =\0 + * ... + * \0 + * If successful, the next value is returned within the supplied + * buffer (the value is always upper-cased), and the corresponding + * is returned within a kmalloc()ed buffer, whose pointer is + * provided as the return value of this function. + * (The total number of bytes allocated is strlen()+1.) + * + * NULL is returned to indicate failure, which can occur for several reasons: + * - all = pairs have already been processed + * - bad parameter + * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within + * the confines of the parameter buffer) + * - the buffer is not large enough to hold the of the next + * parameter + */ +void * +parser_param_get(struct parser_context *ctx, char *nam, int namesize) +{ + u8 *pscan, *pnam = nam; + unsigned long nscan; + int value_length = -1, orig_value_length = -1; + void *value = NULL; + int i; + int closing_quote = 0; + + if (!ctx) + return NULL; + pscan = ctx->curr; + nscan = ctx->bytes_remaining; + if (nscan == 0) + return NULL; + if (*pscan == '\0') + /* This is the normal return point after you have processed + * all of the = pairs in a syntactically-valid + * parameter buffer. + */ + return NULL; + + /* skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + + while (*pscan != ':') { + if (namesize <= 0) + return NULL; + *pnam = toupper(*pscan); + pnam++; + namesize--; + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + if (namesize <= 0) + return NULL; + *pnam = '\0'; + nam[string_length_no_trail(nam, strlen(nam))] = '\0'; + + /* point to char immediately after ":" in ":" */ + pscan++; + nscan--; + /* skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + if (nscan == 0) + return NULL; + if (*pscan == '\'' || *pscan == '"') { + closing_quote = *pscan; + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + + /* look for a separator character, terminator character, or + * end of data + */ + for (i = 0, value_length = -1; i < nscan; i++) { + if (closing_quote) { + if (pscan[i] == '\0') + return NULL; + if (pscan[i] == closing_quote) { + value_length = i; + break; + } + } else + if (pscan[i] == ',' || pscan[i] == ';' + || pscan[i] == '\0') { + value_length = i; + break; + } + } + if (value_length < 0) { + if (closing_quote) + return NULL; + value_length = nscan; + } + orig_value_length = value_length; + if (closing_quote == 0) + value_length = string_length_no_trail(pscan, orig_value_length); + value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); + if (value == NULL) + return NULL; + memcpy(value, pscan, value_length); + ((u8 *) (value))[value_length] = '\0'; + + pscan += orig_value_length; + nscan -= orig_value_length; + + /* skip past separator or closing quote */ + if (nscan > 0) { + if (*pscan != '\0') { + pscan++; + nscan--; + } + } + + if (closing_quote && (nscan > 0)) { + /* we still need to skip around the real separator if present */ + /* first, skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + break; + } + if (nscan > 0) { + if (*pscan == ',' || *pscan == ';') { + pscan++; + nscan--; + } else if (*pscan != '\0') { + kfree(value); + value = NULL; + return NULL; + } + } + } + ctx->curr = pscan; + ctx->bytes_remaining = nscan; + return value; +} + +void * +parser_string_get(struct parser_context *ctx) +{ + u8 *pscan; + unsigned long nscan; + int value_length = -1; + void *value = NULL; + int i; + + if (!ctx) + return NULL; + pscan = ctx->curr; + nscan = ctx->bytes_remaining; + if (nscan == 0) + return NULL; + if (!pscan) + return NULL; + for (i = 0, value_length = -1; i < nscan; i++) + if (pscan[i] == '\0') { + value_length = i; + break; + } + if (value_length < 0) /* '\0' was not included in the length */ + value_length = nscan; + value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); + if (value == NULL) + return NULL; + if (value_length > 0) + memcpy(value, pscan, value_length); + ((u8 *) (value))[value_length] = '\0'; + return value; +} + + static ssize_t toolaction_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2274,13 +2679,13 @@ visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) cdev_init(&file_cdev, &visorchipset_fops); file_cdev.owner = THIS_MODULE; if (MAJOR(major_dev) == 0) { - rc = alloc_chrdev_region(&major_dev, 0, 1, MYDRVNAME); + rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset"); /* dynamic major device number registration required */ if (rc < 0) return rc; } else { /* static major device number registration required */ - rc = register_chrdev_region(major_dev, 1, MYDRVNAME); + rc = register_chrdev_region(major_dev, 1, "visorchipset"); if (rc < 0) return rc; } -- cgit v1.2.3-55-g7522 From c79b28f7332e54903f6c81ff1157cbd3bf761a17 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 5 May 2015 18:36:15 -0400 Subject: staging: unisys: move visorchipset files to visorbus Move visorchipset_main.c and visorchipset.h to visorbus/visorchipset.c and visorbus/visorbus_private.h. This leaves an empty visorchipset directory which can also be destroyed. As a result of this patch the visorchipset init code now calls the visorbus_init() directly. Similarily the visorchipset exit code now cleans up by calling visorbus_exit(). No other functional changes were made. Signed-off-by: Prarit Bhargava Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/Kconfig | 1 - drivers/staging/unisys/Makefile | 1 - drivers/staging/unisys/visorbus/Kconfig | 2 +- drivers/staging/unisys/visorbus/Makefile | 2 +- drivers/staging/unisys/visorbus/visorbus_main.c | 11 +- drivers/staging/unisys/visorbus/visorbus_private.h | 218 ++ drivers/staging/unisys/visorbus/visorchipset.c | 2866 ++++++++++++++++++++ drivers/staging/unisys/visorchipset/Kconfig | 11 - drivers/staging/unisys/visorchipset/Makefile | 15 - drivers/staging/unisys/visorchipset/visorchipset.h | 214 -- .../unisys/visorchipset/visorchipset_main.c | 2863 ------------------- 11 files changed, 3091 insertions(+), 3113 deletions(-) create mode 100644 drivers/staging/unisys/visorbus/visorbus_private.h create mode 100644 drivers/staging/unisys/visorbus/visorchipset.c delete mode 100644 drivers/staging/unisys/visorchipset/Kconfig delete mode 100644 drivers/staging/unisys/visorchipset/Makefile delete mode 100644 drivers/staging/unisys/visorchipset/visorchipset.h delete mode 100644 drivers/staging/unisys/visorchipset/visorchipset_main.c (limited to 'drivers/staging/unisys/visorchipset') diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index dbdd4492cf0f..50223c74eb50 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -10,7 +10,6 @@ menuconfig UNISYSSPAR if UNISYSSPAR source "drivers/staging/unisys/visorutil/Kconfig" -source "drivers/staging/unisys/visorchipset/Kconfig" source "drivers/staging/unisys/visorbus/Kconfig" endif # UNISYSSPAR diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index b14a4777fd48..e0c893a6e870 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -2,5 +2,4 @@ # Makefile for Unisys SPAR drivers # obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ -obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ diff --git a/drivers/staging/unisys/visorbus/Kconfig b/drivers/staging/unisys/visorbus/Kconfig index 12cf8f063550..420c9eee9075 100644 --- a/drivers/staging/unisys/visorbus/Kconfig +++ b/drivers/staging/unisys/visorbus/Kconfig @@ -4,6 +4,6 @@ config UNISYS_VISORBUS tristate "Unisys visorbus driver" - depends on UNISYSSPAR && UNISYS_VISORUTIL && UNISYS_VISORCHIPSET + depends on UNISYSSPAR && UNISYS_VISORUTIL ---help--- If you say Y here, you will enable the Unisys visorbus driver. diff --git a/drivers/staging/unisys/visorbus/Makefile b/drivers/staging/unisys/visorbus/Makefile index 7151690695f5..16d3ff507a0a 100644 --- a/drivers/staging/unisys/visorbus/Makefile +++ b/drivers/staging/unisys/visorbus/Makefile @@ -6,9 +6,9 @@ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus.o visorbus-y := visorbus_main.o visorbus-y += visorchannel.o +visorbus-y += visorchipset.o ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/visorchipset ccflags-y += -Idrivers/staging/unisys/common-spar/include ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels ccflags-y += -Idrivers/staging/unisys/visorutil diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index d7ca1163c1b1..6c939ce503a1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -18,7 +18,7 @@ #include #include "visorbus.h" -#include "visorchipset.h" +#include "visorbus_private.h" #include "version.h" #include "timskmod.h" #include "periodic_work.h" @@ -26,6 +26,8 @@ #include "guestlinuxdebug.h" #include "vbusdeviceinfo.h" +#define MYDRVNAME "visorbus" + /* module parameters */ int visorbus_debug; int visorbus_forcematch; @@ -2033,7 +2035,7 @@ struct channel_size_info { unsigned long max_size; }; -static int __init +int __init visorbus_init(void) { int rc = 0; @@ -2077,7 +2079,7 @@ away: return rc; } -static void +void visorbus_exit(void) { struct list_head *listentry, *listtmp; @@ -2135,9 +2137,6 @@ MODULE_PARM_DESC(visorbus_serialloopbacktest, "non-0 to just create 2 serial devices on the same channel"); int visorbus_serialloopbacktest = 0; -module_init(visorbus_init); -module_exit(visorbus_exit); - MODULE_AUTHOR("Unisys"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Supervisor bus driver for service partition: ver " VERSION); diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h new file mode 100644 index 000000000000..68d770f29115 --- /dev/null +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -0,0 +1,218 @@ +/* visorchipset.h + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef __VISORCHIPSET_H__ +#define __VISORCHIPSET_H__ + +#include + +#include "channel.h" +#include "controlvmchannel.h" +#include "procobjecttree.h" +#include "vbusdeviceinfo.h" +#include "vbushelper.h" + +#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 + +/** Describes the state from the perspective of which controlvm messages have + * been received for a bus or device. + */ + +enum PARSER_WHICH_STRING { + PARSERSTRING_INITIATOR, + PARSERSTRING_TARGET, + PARSERSTRING_CONNECTION, + PARSERSTRING_NAME, +}; + +struct visorchannel; +struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, + bool *tryAgain); +struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, + bool *retry); +void parser_param_start(struct parser_context *ctx, + PARSER_WHICH_STRING which_string); +void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); +void *parser_string_get(struct parser_context *ctx); +uuid_le parser_id_get(struct parser_context *ctx); +char *parser_simpleString_get(struct parser_context *ctx); +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); +void parser_done(struct parser_context *ctx); + +struct visorchipset_state { + u32 created:1; + u32 attached:1; + u32 configured:1; + u32 running:1; + /* Add new fields above. */ + /* Remaining bits in this 32-bit word are unused. */ +}; + +enum visorchipset_addresstype { + /** address is guest physical, but outside of the physical memory + * region that is controlled by the running OS (this is the normal + * address type for Supervisor channels) + */ + ADDRTYPE_LOCALPHYSICAL, + + /** address is guest physical, and withIN the confines of the + * physical memory controlled by the running OS. + */ + ADDRTYPE_LOCALTEST, +}; + +enum crash_obj_type { + CRASH_DEV, + CRASH_BUS, +}; + +/** Attributes for a particular Supervisor channel. + */ +struct visorchipset_channel_info { + enum visorchipset_addresstype addr_type; + HOSTADDRESS channel_addr; + struct irq_info intr; + u64 n_channel_bytes; + uuid_le channel_type_uuid; + uuid_le channel_inst_uuid; +}; + +/** Attributes for a particular Supervisor device. + * Any visorchipset client can query these attributes using + * visorchipset_get_client_device_info() or + * visorchipset_get_server_device_info(). + */ +struct visorchipset_device_info { + struct list_head entry; + u32 bus_no; + u32 dev_no; + uuid_le dev_inst_uuid; + struct visorchipset_state state; + struct visorchipset_channel_info chan_info; + u32 reserved1; /* control_vm_id */ + u64 reserved2; + u32 switch_no; /* when devState.attached==1 */ + u32 internal_port_no; /* when devState.attached==1 */ + struct controlvm_message_header pending_msg_hdr;/* CONTROLVM_MESSAGE */ + /** For private use by the bus driver */ + void *bus_driver_context; +}; + +/** Attributes for a particular Supervisor bus. + * (For a service partition acting as the server for buses/devices, there + * is a 1-to-1 relationship between busses and guest partitions.) + * Any visorchipset client can query these attributes using + * visorchipset_get_client_bus_info() or visorchipset_get_bus_info(). + */ +struct visorchipset_bus_info { + struct list_head entry; + u32 bus_no; + struct visorchipset_state state; + struct visorchipset_channel_info chan_info; + uuid_le partition_uuid; + u64 partition_handle; + u8 *name; /* UTF8 */ + u8 *description; /* UTF8 */ + u64 reserved1; + u32 reserved2; + struct { + u32 server:1; + /* Add new fields above. */ + /* Remaining bits in this 32-bit word are unused. */ + } flags; + struct controlvm_message_header pending_msg_hdr;/* CONTROLVM MsgHdr */ + /** For private use by the bus driver */ + void *bus_driver_context; +}; + +/* These functions will be called from within visorchipset when certain + * events happen. (The implementation of these functions is outside of + * visorchipset.) + */ +struct visorchipset_busdev_notifiers { + void (*bus_create)(u32 bus_no); + void (*bus_destroy)(u32 bus_no); + void (*device_create)(u32 bus_no, u32 dev_no); + void (*device_destroy)(u32 bus_no, u32 dev_no); + void (*device_pause)(u32 bus_no, u32 dev_no); + void (*device_resume)(u32 bus_no, u32 dev_no); +}; + +/* These functions live inside visorchipset, and will be called to indicate + * responses to specific events (by code outside of visorchipset). + * For now, the value for each response is simply either: + * 0 = it worked + * -1 = it failed + */ +struct visorchipset_busdev_responders { + void (*bus_create)(u32 bus_no, int response); + void (*bus_destroy)(u32 bus_no, int response); + void (*device_create)(u32 bus_no, u32 dev_no, int response); + void (*device_destroy)(u32 bus_no, u32 dev_no, int response); + void (*device_pause)(u32 bus_no, u32 dev_no, int response); + void (*device_resume)(u32 bus_no, u32 dev_no, int response); +}; + +/** Register functions (in the bus driver) to get called by visorchipset + * whenever a bus or device appears for which this service partition is + * to be the server for. visorchipset will fill in , to + * indicate functions the bus driver should call to indicate message + * responses. + */ +void +visorchipset_register_busdev_client( + struct visorchipset_busdev_notifiers *notifiers, + struct visorchipset_busdev_responders *responders, + struct ultra_vbus_deviceinfo *driver_info); + +/** Register functions (in the bus driver) to get called by visorchipset + * whenever a bus or device appears for which this service partition is + * to be the client for. visorchipset will fill in , to + * indicate functions the bus driver should call to indicate message + * responses. + */ +void +visorchipset_register_busdev_server( + struct visorchipset_busdev_notifiers *notifiers, + struct visorchipset_busdev_responders *responders, + struct ultra_vbus_deviceinfo *driver_info); + +void visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response); + +bool visorchipset_get_bus_info(u32 bus_no, + struct visorchipset_bus_info *bus_info); +bool visorchipset_get_device_info(u32 bus_no, u32 dev_no, + struct visorchipset_device_info *dev_info); +bool visorchipset_set_bus_context(u32 bus_no, void *context); +bool visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context); +int visorchipset_chipset_ready(void); +int visorchipset_chipset_selftest(void); +int visorchipset_chipset_notready(void); +void visorchipset_save_message(struct controlvm_message *msg, + enum crash_obj_type type); +void *visorchipset_cache_alloc(struct kmem_cache *pool, + bool ok_to_block, char *fn, int ln); +void visorchipset_cache_free(struct kmem_cache *pool, void *p, + char *fn, int ln); +int visorchipset_file_init(dev_t majorDev, + struct visorchannel **pControlVm_channel); +void visorchipset_file_cleanup(dev_t major_dev); + +/* visorbus init and exit functions */ +int __init visorbus_init(void); +void visorbus_exit(void); +#endif diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c new file mode 100644 index 000000000000..f3a2145ac3ce --- /dev/null +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -0,0 +1,2866 @@ +/* visorchipset_main.c + * + * Copyright (C) 2010 - 2013 UNISYS CORPORATION + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#include "memregion.h" +#include "controlvmchannel.h" +#include "version.h" +#include "procobjecttree.h" +#include "visorbus.h" +#include "periodic_work.h" +#include "uisutils.h" +#include "controlvmcompletionstatus.h" +#include "guestlinuxdebug.h" +#include "visorbus_private.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c +#define TEST_VNIC_PHYSITF "eth0" /* physical network itf for + * vnic loopback test */ +#define TEST_VNIC_SWITCHNO 1 +#define TEST_VNIC_BUSNO 9 + +#define MAX_NAME_SIZE 128 +#define MAX_IP_SIZE 50 +#define MAXOUTSTANDINGCHANNELCOMMAND 256 +#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 +#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 + +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) +/* + * Module parameters + */ +static int visorchipset_testvnic; +static int visorchipset_testvnicclient; +static int visorchipset_testmsg; +static int visorchipset_major; +static int visorchipset_serverregwait; +static int visorchipset_clientregwait = 1; /* default is on */ +static int visorchipset_testteardown; +static int visorchipset_disable_controlvm; +static int visorchipset_holdchipsetready; +static unsigned long controlvm_payload_bytes_buffered; + +static int +visorchipset_open(struct inode *inode, struct file *file) +{ + unsigned minor_number = iminor(inode); + + if (minor_number) + return -ENODEV; + file->private_data = NULL; + return 0; +} + +static int +visorchipset_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, +* we switch to slow polling mode. As soon as we get a controlvm +* message, we switch back to fast polling mode. +*/ +#define MIN_IDLE_SECONDS 10 +static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; +static unsigned long most_recent_message_jiffies; /* when we got our last + * controlvm message */ +static int serverregistered; +static int clientregistered; + +#define MAX_CHIPSET_EVENTS 2 +static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 }; + +struct parser_context { + unsigned long allocbytes; + unsigned long param_bytes; + u8 *curr; + unsigned long bytes_remaining; + bool byte_stream; + char data[0]; +}; + +static struct delayed_work periodic_controlvm_work; +static struct workqueue_struct *periodic_controlvm_workqueue; +static DEFINE_SEMAPHORE(notifier_lock); + +static struct cdev file_cdev; +static struct visorchannel **file_controlvm_channel; +static struct controlvm_message_header g_chipset_msg_hdr; +static const uuid_le spar_diag_pool_channel_protocol_uuid = + SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; +/* 0xffffff is an invalid Bus/Device number */ +static u32 g_diagpool_bus_no = 0xffffff; +static u32 g_diagpool_dev_no = 0xffffff; +static struct controlvm_message_packet g_devicechangestate_packet; + +/* Only VNIC and VHBA channels are sent to visorclientbus (aka + * "visorhackbus") + */ +#define FOR_VISORHACKBUS(channel_type_guid) \ + (((uuid_le_cmp(channel_type_guid,\ + spar_vnic_channel_protocol_uuid) == 0) ||\ + (uuid_le_cmp(channel_type_guid,\ + spar_vhba_channel_protocol_uuid) == 0))) +#define FOR_VISORBUS(channel_type_guid) (!(FOR_VISORHACKBUS(channel_type_guid))) + +#define is_diagpool_channel(channel_type_guid) \ + (uuid_le_cmp(channel_type_guid,\ + spar_diag_pool_channel_protocol_uuid) == 0) + +static LIST_HEAD(bus_info_list); +static LIST_HEAD(dev_info_list); + +static struct visorchannel *controlvm_channel; + +/* Manages the request payload in the controlvm channel */ +struct visor_controlvm_payload_info { + u8 __iomem *ptr; /* pointer to base address of payload pool */ + u64 offset; /* offset from beginning of controlvm + * channel to beginning of payload * pool */ + u32 bytes; /* number of bytes in payload pool */ +}; + +static struct visor_controlvm_payload_info controlvm_payload_info; + +/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / + * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation. + */ +struct visor_livedump_info { + struct controlvm_message_header dumpcapture_header; + struct controlvm_message_header gettextdump_header; + struct controlvm_message_header dumpcomplete_header; + bool gettextdump_outstanding; + u32 crc32; + unsigned long length; + atomic_t buffers_in_use; + unsigned long destination; +}; + +static struct visor_livedump_info livedump_info; + +/* The following globals are used to handle the scenario where we are unable to + * offload the payload from a controlvm message due to memory requirements. In + * this scenario, we simply stash the controlvm message, then attempt to + * process it again the next time controlvm_periodic_work() runs. + */ +static struct controlvm_message controlvm_pending_msg; +static bool controlvm_pending_msg_valid; + +/* This identifies a data buffer that has been received via a controlvm messages + * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. + */ +struct putfile_buffer_entry { + struct list_head next; /* putfile_buffer_entry list */ + struct parser_context *parser_ctx; /* points to input data buffer */ +}; + +/* List of struct putfile_request *, via next_putfile_request member. + * Each entry in this list identifies an outstanding TRANSMIT_FILE + * conversation. + */ +static LIST_HEAD(putfile_request_list); + +/* This describes a buffer and its current state of transfer (e.g., how many + * bytes have already been supplied as putfile data, and how many bytes are + * remaining) for a putfile_request. + */ +struct putfile_active_buffer { + /* a payload from a controlvm message, containing a file data buffer */ + struct parser_context *parser_ctx; + /* points within data area of parser_ctx to next byte of data */ + u8 *pnext; + /* # bytes left from to the end of this data buffer */ + size_t bytes_remaining; +}; + +#define PUTFILE_REQUEST_SIG 0x0906101302281211 +/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE + * conversation. Structs of this type are dynamically linked into + * . + */ +struct putfile_request { + u64 sig; /* PUTFILE_REQUEST_SIG */ + + /* header from original TransmitFile request */ + struct controlvm_message_header controlvm_header; + u64 file_request_number; /* from original TransmitFile request */ + + /* link to next struct putfile_request */ + struct list_head next_putfile_request; + + /* most-recent sequence number supplied via a controlvm message */ + u64 data_sequence_number; + + /* head of putfile_buffer_entry list, which describes the data to be + * supplied as putfile data; + * - this list is added to when controlvm messages come in that supply + * file data + * - this list is removed from via the hotplug program that is actually + * consuming these buffers to write as file data */ + struct list_head input_buffer_list; + spinlock_t req_list_lock; /* lock for input_buffer_list */ + + /* waiters for input_buffer_list to go non-empty */ + wait_queue_head_t input_buffer_wq; + + /* data not yet read within current putfile_buffer_entry */ + struct putfile_active_buffer active_buf; + + /* <0 = failed, 0 = in-progress, >0 = successful; */ + /* note that this must be set with req_list_lock, and if you set <0, */ + /* it is your responsibility to also free up all of the other objects */ + /* in this struct (like input_buffer_list, active_buf.parser_ctx) */ + /* before releasing the lock */ + int completion_status; +}; + +struct parahotplug_request { + struct list_head list; + int id; + unsigned long expiration; + struct controlvm_message msg; +}; + +static LIST_HEAD(parahotplug_request_list); +static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ +static void parahotplug_process_list(void); + +/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / + * CONTROLVM_REPORTEVENT. + */ +static struct visorchipset_busdev_notifiers busdev_server_notifiers; +static struct visorchipset_busdev_notifiers busdev_client_notifiers; + +static void bus_create_response(u32 bus_no, int response); +static void bus_destroy_response(u32 bus_no, int response); +static void device_create_response(u32 bus_no, u32 dev_no, int response); +static void device_destroy_response(u32 bus_no, u32 dev_no, int response); +static void device_resume_response(u32 bus_no, u32 dev_no, int response); + +static struct visorchipset_busdev_responders busdev_responders = { + .bus_create = bus_create_response, + .bus_destroy = bus_destroy_response, + .device_create = device_create_response, + .device_destroy = device_destroy_response, + .device_pause = visorchipset_device_pause_response, + .device_resume = device_resume_response, +}; + +/* info for /dev/visorchipset */ +static dev_t major_dev = -1; /**< indicates major num for device */ + +/* prototypes for attributes */ +static ssize_t toolaction_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t toolaction_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_RW(toolaction); + +static ssize_t boottotool_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t boottotool_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count); +static DEVICE_ATTR_RW(boottotool); + +static ssize_t error_show(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t error_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_RW(error); + +static ssize_t textid_show(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t textid_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_RW(textid); + +static ssize_t remaining_steps_show(struct device *dev, + struct device_attribute *attr, char *buf); +static ssize_t remaining_steps_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_RW(remaining_steps); + +static ssize_t chipsetready_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_WO(chipsetready); + +static ssize_t devicedisabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_WO(devicedisabled); + +static ssize_t deviceenabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static DEVICE_ATTR_WO(deviceenabled); + +static struct attribute *visorchipset_install_attrs[] = { + &dev_attr_toolaction.attr, + &dev_attr_boottotool.attr, + &dev_attr_error.attr, + &dev_attr_textid.attr, + &dev_attr_remaining_steps.attr, + NULL +}; + +static struct attribute_group visorchipset_install_group = { + .name = "install", + .attrs = visorchipset_install_attrs +}; + +static struct attribute *visorchipset_guest_attrs[] = { + &dev_attr_chipsetready.attr, + NULL +}; + +static struct attribute_group visorchipset_guest_group = { + .name = "guest", + .attrs = visorchipset_guest_attrs +}; + +static struct attribute *visorchipset_parahotplug_attrs[] = { + &dev_attr_devicedisabled.attr, + &dev_attr_deviceenabled.attr, + NULL +}; + +static struct attribute_group visorchipset_parahotplug_group = { + .name = "parahotplug", + .attrs = visorchipset_parahotplug_attrs +}; + +static const struct attribute_group *visorchipset_dev_groups[] = { + &visorchipset_install_group, + &visorchipset_guest_group, + &visorchipset_parahotplug_group, + NULL +}; + +/* /sys/devices/platform/visorchipset */ +static struct platform_device visorchipset_platform_device = { + .name = "visorchipset", + .id = -1, + .dev.groups = visorchipset_dev_groups, +}; + +/* Function prototypes */ +static void controlvm_respond(struct controlvm_message_header *msg_hdr, + int response); +static void controlvm_respond_chipset_init( + struct controlvm_message_header *msg_hdr, int response, + enum ultra_chipset_feature features); +static void controlvm_respond_physdev_changestate( + struct controlvm_message_header *msg_hdr, int response, + struct spar_segment_state state); + + +static struct parser_context * +parser_init_guts(u64 addr, u32 bytes, bool local, + bool standard_payload_header, bool *retry) +{ + int allocbytes = sizeof(struct parser_context) + bytes; + struct parser_context *rc = NULL; + struct parser_context *ctx = NULL; + struct memregion *rgn = NULL; + struct spar_controlvm_parameters_header *phdr = NULL; + + if (retry) + *retry = false; + if (!standard_payload_header) + /* alloc and 0 extra byte to ensure payload is + * '\0'-terminated + */ + allocbytes++; + if ((controlvm_payload_bytes_buffered + bytes) + > MAX_CONTROLVM_PAYLOAD_BYTES) { + if (retry) + *retry = true; + rc = NULL; + goto cleanup; + } + ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); + if (!ctx) { + if (retry) + *retry = true; + rc = NULL; + goto cleanup; + } + + ctx->allocbytes = allocbytes; + ctx->param_bytes = bytes; + ctx->curr = NULL; + ctx->bytes_remaining = 0; + ctx->byte_stream = false; + if (local) { + void *p; + + if (addr > virt_to_phys(high_memory - 1)) { + rc = NULL; + goto cleanup; + } + p = __va((unsigned long) (addr)); + memcpy(ctx->data, p, bytes); + } else { + rgn = visor_memregion_create(addr, bytes); + if (!rgn) { + rc = NULL; + goto cleanup; + } + if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { + rc = NULL; + goto cleanup; + } + } + if (!standard_payload_header) { + ctx->byte_stream = true; + rc = ctx; + goto cleanup; + } + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + if (phdr->total_length != bytes) { + rc = NULL; + goto cleanup; + } + if (phdr->total_length < phdr->header_length) { + rc = NULL; + goto cleanup; + } + if (phdr->header_length < + sizeof(struct spar_controlvm_parameters_header)) { + rc = NULL; + goto cleanup; + } + + rc = ctx; +cleanup: + if (rgn) { + visor_memregion_destroy(rgn); + rgn = NULL; + } + if (rc) { + controlvm_payload_bytes_buffered += ctx->param_bytes; + } else { + if (ctx) { + parser_done(ctx); + ctx = NULL; + } + } + return rc; +} + +struct parser_context * +parser_init(u64 addr, u32 bytes, bool local, bool *retry) +{ + return parser_init_guts(addr, bytes, local, true, retry); +} + +/* Call this instead of parser_init() if the payload area consists of just + * a sequence of bytes, rather than a struct spar_controlvm_parameters_header + * structures. Afterwards, you can call parser_simpleString_get() or + * parser_byteStream_get() to obtain the data. + */ +struct parser_context * +parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) +{ + return parser_init_guts(addr, bytes, local, false, retry); +} + +/* Obtain '\0'-terminated copy of string in payload area. + */ +char * +parser_simpleString_get(struct parser_context *ctx) +{ + if (!ctx->byte_stream) + return NULL; + return ctx->data; /* note this IS '\0'-terminated, because of + * the num of bytes we alloc+clear in + * parser_init_byteStream() */ +} + +/* Obtain a copy of the buffer in the payload area. + */ +void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) +{ + if (!ctx->byte_stream) + return NULL; + if (nbytes) + *nbytes = ctx->param_bytes; + return (void *)ctx->data; +} + +uuid_le +parser_id_get(struct parser_context *ctx) +{ + struct spar_controlvm_parameters_header *phdr = NULL; + + if (ctx == NULL) + return NULL_UUID_LE; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + return phdr->id; +} + +void +parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string) +{ + struct spar_controlvm_parameters_header *phdr = NULL; + + if (ctx == NULL) + goto Away; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); + switch (which_string) { + case PARSERSTRING_INITIATOR: + ctx->curr = ctx->data + phdr->initiator_offset; + ctx->bytes_remaining = phdr->initiator_length; + break; + case PARSERSTRING_TARGET: + ctx->curr = ctx->data + phdr->target_offset; + ctx->bytes_remaining = phdr->target_length; + break; + case PARSERSTRING_CONNECTION: + ctx->curr = ctx->data + phdr->connection_offset; + ctx->bytes_remaining = phdr->connection_length; + break; + case PARSERSTRING_NAME: + ctx->curr = ctx->data + phdr->name_offset; + ctx->bytes_remaining = phdr->name_length; + break; + default: + break; + } + +Away: + return; +} + +void +parser_done(struct parser_context *ctx) +{ + if (!ctx) + return; + controlvm_payload_bytes_buffered -= ctx->param_bytes; + kfree(ctx); +} + +/** Return length of string not counting trailing spaces. */ +static int +string_length_no_trail(char *s, int len) +{ + int i = len - 1; + + while (i >= 0) { + if (!isspace(s[i])) + return i + 1; + i--; + } + return 0; +} + +/** Grab the next name and value out of the parameter buffer. + * The entire parameter buffer looks like this: + * =\0 + * =\0 + * ... + * \0 + * If successful, the next value is returned within the supplied + * buffer (the value is always upper-cased), and the corresponding + * is returned within a kmalloc()ed buffer, whose pointer is + * provided as the return value of this function. + * (The total number of bytes allocated is strlen()+1.) + * + * NULL is returned to indicate failure, which can occur for several reasons: + * - all = pairs have already been processed + * - bad parameter + * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within + * the confines of the parameter buffer) + * - the buffer is not large enough to hold the of the next + * parameter + */ +void * +parser_param_get(struct parser_context *ctx, char *nam, int namesize) +{ + u8 *pscan, *pnam = nam; + unsigned long nscan; + int value_length = -1, orig_value_length = -1; + void *value = NULL; + int i; + int closing_quote = 0; + + if (!ctx) + return NULL; + pscan = ctx->curr; + nscan = ctx->bytes_remaining; + if (nscan == 0) + return NULL; + if (*pscan == '\0') + /* This is the normal return point after you have processed + * all of the = pairs in a syntactically-valid + * parameter buffer. + */ + return NULL; + + /* skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + + while (*pscan != ':') { + if (namesize <= 0) + return NULL; + *pnam = toupper(*pscan); + pnam++; + namesize--; + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + if (namesize <= 0) + return NULL; + *pnam = '\0'; + nam[string_length_no_trail(nam, strlen(nam))] = '\0'; + + /* point to char immediately after ":" in ":" */ + pscan++; + nscan--; + /* skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + if (nscan == 0) + return NULL; + if (*pscan == '\'' || *pscan == '"') { + closing_quote = *pscan; + pscan++; + nscan--; + if (nscan == 0) + return NULL; + } + + /* look for a separator character, terminator character, or + * end of data + */ + for (i = 0, value_length = -1; i < nscan; i++) { + if (closing_quote) { + if (pscan[i] == '\0') + return NULL; + if (pscan[i] == closing_quote) { + value_length = i; + break; + } + } else + if (pscan[i] == ',' || pscan[i] == ';' + || pscan[i] == '\0') { + value_length = i; + break; + } + } + if (value_length < 0) { + if (closing_quote) + return NULL; + value_length = nscan; + } + orig_value_length = value_length; + if (closing_quote == 0) + value_length = string_length_no_trail(pscan, orig_value_length); + value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); + if (value == NULL) + return NULL; + memcpy(value, pscan, value_length); + ((u8 *) (value))[value_length] = '\0'; + + pscan += orig_value_length; + nscan -= orig_value_length; + + /* skip past separator or closing quote */ + if (nscan > 0) { + if (*pscan != '\0') { + pscan++; + nscan--; + } + } + + if (closing_quote && (nscan > 0)) { + /* we still need to skip around the real separator if present */ + /* first, skip whitespace */ + while (isspace(*pscan)) { + pscan++; + nscan--; + if (nscan == 0) + break; + } + if (nscan > 0) { + if (*pscan == ',' || *pscan == ';') { + pscan++; + nscan--; + } else if (*pscan != '\0') { + kfree(value); + value = NULL; + return NULL; + } + } + } + ctx->curr = pscan; + ctx->bytes_remaining = nscan; + return value; +} + +void * +parser_string_get(struct parser_context *ctx) +{ + u8 *pscan; + unsigned long nscan; + int value_length = -1; + void *value = NULL; + int i; + + if (!ctx) + return NULL; + pscan = ctx->curr; + nscan = ctx->bytes_remaining; + if (nscan == 0) + return NULL; + if (!pscan) + return NULL; + for (i = 0, value_length = -1; i < nscan; i++) + if (pscan[i] == '\0') { + value_length = i; + break; + } + if (value_length < 0) /* '\0' was not included in the length */ + value_length = nscan; + value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); + if (value == NULL) + return NULL; + if (value_length > 0) + memcpy(value, pscan, value_length); + ((u8 *) (value))[value_length] = '\0'; + return value; +} + + +static ssize_t toolaction_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u8 tool_action; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); + return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); +} + +static ssize_t toolaction_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u8 tool_action; + int ret; + + if (kstrtou8(buf, 10, &tool_action)) + return -EINVAL; + + ret = visorchannel_write(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); + + if (ret) + return ret; + return count; +} + +static ssize_t boottotool_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct efi_spar_indication efi_spar_indication; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &efi_spar_indication, + sizeof(struct efi_spar_indication)); + return scnprintf(buf, PAGE_SIZE, "%u\n", + efi_spar_indication.boot_to_tool); +} + +static ssize_t boottotool_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int val, ret; + struct efi_spar_indication efi_spar_indication; + + if (kstrtoint(buf, 10, &val)) + return -EINVAL; + + efi_spar_indication.boot_to_tool = val; + ret = visorchannel_write(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &(efi_spar_indication), + sizeof(struct efi_spar_indication)); + + if (ret) + return ret; + return count; +} + +static ssize_t error_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + u32 error; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", error); +} + +static ssize_t error_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 error; + int ret; + + if (kstrtou32(buf, 10, &error)) + return -EINVAL; + + ret = visorchannel_write(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + if (ret) + return ret; + return count; +} + +static ssize_t textid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + u32 text_id; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); +} + +static ssize_t textid_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 text_id; + int ret; + + if (kstrtou32(buf, 10, &text_id)) + return -EINVAL; + + ret = visorchannel_write(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + if (ret) + return ret; + return count; +} + +static ssize_t remaining_steps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u16 remaining_steps; + + visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); +} + +static ssize_t remaining_steps_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u16 remaining_steps; + int ret; + + if (kstrtou16(buf, 10, &remaining_steps)) + return -EINVAL; + + ret = visorchannel_write(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + if (ret) + return ret; + return count; +} + +static void +bus_info_clear(void *v) +{ + struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) v; + + kfree(p->name); + kfree(p->description); + memset(p, 0, sizeof(struct visorchipset_bus_info)); +} + +static void +dev_info_clear(void *v) +{ + struct visorchipset_device_info *p = + (struct visorchipset_device_info *) v; + + memset(p, 0, sizeof(struct visorchipset_device_info)); +} + +static struct visorchipset_bus_info * +bus_find(struct list_head *list, u32 bus_no) +{ + struct visorchipset_bus_info *p; + + list_for_each_entry(p, list, entry) { + if (p->bus_no == bus_no) + return p; + } + + return NULL; +} + +static struct visorchipset_device_info * +device_find(struct list_head *list, u32 bus_no, u32 dev_no) +{ + struct visorchipset_device_info *p; + + list_for_each_entry(p, list, entry) { + if (p->bus_no == bus_no && p->dev_no == dev_no) + return p; + } + + return NULL; +} + +static void busdevices_del(struct list_head *list, u32 bus_no) +{ + struct visorchipset_device_info *p, *tmp; + + list_for_each_entry_safe(p, tmp, list, entry) { + if (p->bus_no == bus_no) { + list_del(&p->entry); + kfree(p); + } + } +} + +static u8 +check_chipset_events(void) +{ + int i; + u8 send_msg = 1; + /* Check events to determine if response should be sent */ + for (i = 0; i < MAX_CHIPSET_EVENTS; i++) + send_msg &= chipset_events[i]; + return send_msg; +} + +static void +clear_chipset_events(void) +{ + int i; + /* Clear chipset_events */ + for (i = 0; i < MAX_CHIPSET_EVENTS; i++) + chipset_events[i] = 0; +} + +void +visorchipset_register_busdev_server( + struct visorchipset_busdev_notifiers *notifiers, + struct visorchipset_busdev_responders *responders, + struct ultra_vbus_deviceinfo *driver_info) +{ + down(¬ifier_lock); + if (!notifiers) { + memset(&busdev_server_notifiers, 0, + sizeof(busdev_server_notifiers)); + serverregistered = 0; /* clear flag */ + } else { + busdev_server_notifiers = *notifiers; + serverregistered = 1; /* set flag */ + } + if (responders) + *responders = busdev_responders; + if (driver_info) + bus_device_info_init(driver_info, "chipset", "visorchipset", + VERSION, NULL); + + up(¬ifier_lock); +} +EXPORT_SYMBOL_GPL(visorchipset_register_busdev_server); + +void +visorchipset_register_busdev_client( + struct visorchipset_busdev_notifiers *notifiers, + struct visorchipset_busdev_responders *responders, + struct ultra_vbus_deviceinfo *driver_info) +{ + down(¬ifier_lock); + if (!notifiers) { + memset(&busdev_client_notifiers, 0, + sizeof(busdev_client_notifiers)); + clientregistered = 0; /* clear flag */ + } else { + busdev_client_notifiers = *notifiers; + clientregistered = 1; /* set flag */ + } + if (responders) + *responders = busdev_responders; + if (driver_info) + bus_device_info_init(driver_info, "chipset(bolts)", + "visorchipset", VERSION, NULL); + up(¬ifier_lock); +} +EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client); + +static void +cleanup_controlvm_structures(void) +{ + struct visorchipset_bus_info *bi, *tmp_bi; + struct visorchipset_device_info *di, *tmp_di; + + list_for_each_entry_safe(bi, tmp_bi, &bus_info_list, entry) { + bus_info_clear(bi); + list_del(&bi->entry); + kfree(bi); + } + + list_for_each_entry_safe(di, tmp_di, &dev_info_list, entry) { + dev_info_clear(di); + list_del(&di->entry); + kfree(di); + } +} + +static void +chipset_init(struct controlvm_message *inmsg) +{ + static int chipset_inited; + enum ultra_chipset_feature features = 0; + int rc = CONTROLVM_RESP_SUCCESS; + + POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); + if (chipset_inited) { + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + goto cleanup; + } + chipset_inited = 1; + POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); + + /* Set features to indicate we support parahotplug (if Command + * also supports it). */ + features = + inmsg->cmd.init_chipset. + features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; + + /* Set the "reply" bit so Command knows this is a + * features-aware driver. */ + features |= ULTRA_CHIPSET_FEATURE_REPLY; + +cleanup: + if (rc < 0) + cleanup_controlvm_structures(); + if (inmsg->hdr.flags.response_expected) + controlvm_respond_chipset_init(&inmsg->hdr, rc, features); +} + +static void +controlvm_init_response(struct controlvm_message *msg, + struct controlvm_message_header *msg_hdr, int response) +{ + memset(msg, 0, sizeof(struct controlvm_message)); + memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header)); + msg->hdr.payload_bytes = 0; + msg->hdr.payload_vm_offset = 0; + msg->hdr.payload_max_bytes = 0; + if (response < 0) { + msg->hdr.flags.failed = 1; + msg->hdr.completion_status = (u32) (-response); + } +} + +static void +controlvm_respond(struct controlvm_message_header *msg_hdr, int response) +{ + struct controlvm_message outmsg; + + controlvm_init_response(&outmsg, msg_hdr, response); + /* For DiagPool channel DEVICE_CHANGESTATE, we need to send + * back the deviceChangeState structure in the packet. */ + if (msg_hdr->id == CONTROLVM_DEVICE_CHANGESTATE && + g_devicechangestate_packet.device_change_state.bus_no == + g_diagpool_bus_no && + g_devicechangestate_packet.device_change_state.dev_no == + g_diagpool_dev_no) + outmsg.cmd = g_devicechangestate_packet; + if (outmsg.hdr.flags.test_message == 1) + return; + + if (!visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { + return; + } +} + +static void +controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, + int response, + enum ultra_chipset_feature features) +{ + struct controlvm_message outmsg; + + controlvm_init_response(&outmsg, msg_hdr, response); + outmsg.cmd.init_chipset.features = features; + if (!visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { + return; + } +} + +static void controlvm_respond_physdev_changestate( + struct controlvm_message_header *msg_hdr, int response, + struct spar_segment_state state) +{ + struct controlvm_message outmsg; + + controlvm_init_response(&outmsg, msg_hdr, response); + outmsg.cmd.device_change_state.state = state; + outmsg.cmd.device_change_state.flags.phys_device = 1; + if (!visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) { + return; + } +} + +void +visorchipset_save_message(struct controlvm_message *msg, + enum crash_obj_type type) +{ + u32 crash_msg_offset; + u16 crash_msg_count; + + /* get saved message count */ + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_count), + &crash_msg_count, sizeof(u16)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (crash_msg_count != CONTROLVM_CRASHMSG_MAX) { + POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC, + crash_msg_count, + POSTCODE_SEVERITY_ERR); + return; + } + + /* get saved crash message offset */ + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_offset), + &crash_msg_offset, sizeof(u32)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (type == CRASH_BUS) { + if (visorchannel_write(controlvm_channel, + crash_msg_offset, + msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } else { + if (visorchannel_write(controlvm_channel, + crash_msg_offset + + sizeof(struct controlvm_message), msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } +} +EXPORT_SYMBOL_GPL(visorchipset_save_message); + +static void +bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) +{ + struct visorchipset_bus_info *p; + bool need_clear = false; + + p = bus_find(&bus_info_list, bus_no); + if (!p) + return; + + if (response < 0) { + if ((cmd_id == CONTROLVM_BUS_CREATE) && + (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE))) + /* undo the row we just created... */ + busdevices_del(&dev_info_list, bus_no); + } else { + if (cmd_id == CONTROLVM_BUS_CREATE) + p->state.created = 1; + if (cmd_id == CONTROLVM_BUS_DESTROY) + need_clear = true; + } + + if (p->pending_msg_hdr.id == CONTROLVM_INVALID) + return; /* no controlvm response needed */ + if (p->pending_msg_hdr.id != (u32)cmd_id) + return; + controlvm_respond(&p->pending_msg_hdr, response); + p->pending_msg_hdr.id = CONTROLVM_INVALID; + if (need_clear) { + bus_info_clear(p); + busdevices_del(&dev_info_list, bus_no); + } +} + +static void +device_changestate_responder(enum controlvm_id cmd_id, + u32 bus_no, u32 dev_no, int response, + struct spar_segment_state response_state) +{ + struct visorchipset_device_info *p; + struct controlvm_message outmsg; + + p = device_find(&dev_info_list, bus_no, dev_no); + if (!p) + return; + if (p->pending_msg_hdr.id == CONTROLVM_INVALID) + return; /* no controlvm response needed */ + if (p->pending_msg_hdr.id != cmd_id) + return; + + controlvm_init_response(&outmsg, &p->pending_msg_hdr, response); + + outmsg.cmd.device_change_state.bus_no = bus_no; + outmsg.cmd.device_change_state.dev_no = dev_no; + outmsg.cmd.device_change_state.state = response_state; + + if (!visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_REQUEST, &outmsg)) + return; + + p->pending_msg_hdr.id = CONTROLVM_INVALID; +} + +static void +device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) +{ + struct visorchipset_device_info *p; + bool need_clear = false; + + p = device_find(&dev_info_list, bus_no, dev_no); + if (!p) + return; + if (response >= 0) { + if (cmd_id == CONTROLVM_DEVICE_CREATE) + p->state.created = 1; + if (cmd_id == CONTROLVM_DEVICE_DESTROY) + need_clear = true; + } + + if (p->pending_msg_hdr.id == CONTROLVM_INVALID) + return; /* no controlvm response needed */ + + if (p->pending_msg_hdr.id != (u32)cmd_id) + return; + + controlvm_respond(&p->pending_msg_hdr, response); + p->pending_msg_hdr.id = CONTROLVM_INVALID; + if (need_clear) + dev_info_clear(p); +} + +static void +bus_epilog(u32 bus_no, + u32 cmd, struct controlvm_message_header *msg_hdr, + int response, bool need_response) +{ + struct visorchipset_bus_info *bus_info; + bool notified = false; + + bus_info = bus_find(&bus_info_list, bus_no); + + if (!bus_info) + return; + + if (need_response) { + memcpy(&bus_info->pending_msg_hdr, msg_hdr, + sizeof(struct controlvm_message_header)); + } else { + bus_info->pending_msg_hdr.id = CONTROLVM_INVALID; + } + + down(¬ifier_lock); + if (response == CONTROLVM_RESP_SUCCESS) { + switch (cmd) { + case CONTROLVM_BUS_CREATE: + /* We can't tell from the bus_create + * information which of our 2 bus flavors the + * devices on this bus will ultimately end up. + * FORTUNATELY, it turns out it is harmless to + * send the bus_create to both of them. We can + * narrow things down a little bit, though, + * because we know: - BusDev_Server can handle + * either server or client devices + * - BusDev_Client can handle ONLY client + * devices */ + if (busdev_server_notifiers.bus_create) { + (*busdev_server_notifiers.bus_create) (bus_no); + notified = true; + } + if ((!bus_info->flags.server) /*client */ && + busdev_client_notifiers.bus_create) { + (*busdev_client_notifiers.bus_create) (bus_no); + notified = true; + } + break; + case CONTROLVM_BUS_DESTROY: + if (busdev_server_notifiers.bus_destroy) { + (*busdev_server_notifiers.bus_destroy) (bus_no); + notified = true; + } + if ((!bus_info->flags.server) /*client */ && + busdev_client_notifiers.bus_destroy) { + (*busdev_client_notifiers.bus_destroy) (bus_no); + notified = true; + } + break; + } + } + if (notified) + /* The callback function just called above is responsible + * for calling the appropriate visorchipset_busdev_responders + * function, which will call bus_responder() + */ + ; + else + bus_responder(cmd, bus_no, response); + up(¬ifier_lock); +} + +static void +device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, + struct controlvm_message_header *msg_hdr, int response, + bool need_response, bool for_visorbus) +{ + struct visorchipset_busdev_notifiers *notifiers; + bool notified = false; + + struct visorchipset_device_info *dev_info = + device_find(&dev_info_list, bus_no, dev_no); + char *envp[] = { + "SPARSP_DIAGPOOL_PAUSED_STATE = 1", + NULL + }; + + if (!dev_info) + return; + + if (for_visorbus) + notifiers = &busdev_server_notifiers; + else + notifiers = &busdev_client_notifiers; + if (need_response) { + memcpy(&dev_info->pending_msg_hdr, msg_hdr, + sizeof(struct controlvm_message_header)); + } else { + dev_info->pending_msg_hdr.id = CONTROLVM_INVALID; + } + + down(¬ifier_lock); + if (response >= 0) { + switch (cmd) { + case CONTROLVM_DEVICE_CREATE: + if (notifiers->device_create) { + (*notifiers->device_create) (bus_no, dev_no); + notified = true; + } + break; + case CONTROLVM_DEVICE_CHANGESTATE: + /* ServerReady / ServerRunning / SegmentStateRunning */ + if (state.alive == segment_state_running.alive && + state.operating == + segment_state_running.operating) { + if (notifiers->device_resume) { + (*notifiers->device_resume) (bus_no, + dev_no); + notified = true; + } + } + /* ServerNotReady / ServerLost / SegmentStateStandby */ + else if (state.alive == segment_state_standby.alive && + state.operating == + segment_state_standby.operating) { + /* technically this is standby case + * where server is lost + */ + if (notifiers->device_pause) { + (*notifiers->device_pause) (bus_no, + dev_no); + notified = true; + } + } else if (state.alive == segment_state_paused.alive && + state.operating == + segment_state_paused.operating) { + /* this is lite pause where channel is + * still valid just 'pause' of it + */ + if (bus_no == g_diagpool_bus_no && + dev_no == g_diagpool_dev_no) { + /* this will trigger the + * diag_shutdown.sh script in + * the visorchipset hotplug */ + kobject_uevent_env + (&visorchipset_platform_device.dev. + kobj, KOBJ_ONLINE, envp); + } + } + break; + case CONTROLVM_DEVICE_DESTROY: + if (notifiers->device_destroy) { + (*notifiers->device_destroy) (bus_no, dev_no); + notified = true; + } + break; + } + } + if (notified) + /* The callback function just called above is responsible + * for calling the appropriate visorchipset_busdev_responders + * function, which will call device_responder() + */ + ; + else + device_responder(cmd, bus_no, dev_no, response); + up(¬ifier_lock); +} + +static void +bus_create(struct controlvm_message *inmsg) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no = cmd->create_bus.bus_no; + int rc = CONTROLVM_RESP_SUCCESS; + struct visorchipset_bus_info *bus_info; + + bus_info = bus_find(&bus_info_list, bus_no); + if (bus_info && (bus_info->state.created == 1)) { + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + goto cleanup; + } + bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); + if (!bus_info) { + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; + goto cleanup; + } + + INIT_LIST_HEAD(&bus_info->entry); + bus_info->bus_no = bus_no; + + POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO); + + if (inmsg->hdr.flags.test_message == 1) + bus_info->chan_info.addr_type = ADDRTYPE_LOCALTEST; + else + bus_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL; + + bus_info->flags.server = inmsg->hdr.flags.server; + bus_info->chan_info.channel_addr = cmd->create_bus.channel_addr; + bus_info->chan_info.n_channel_bytes = cmd->create_bus.channel_bytes; + bus_info->chan_info.channel_type_uuid = + cmd->create_bus.bus_data_type_uuid; + bus_info->chan_info.channel_inst_uuid = cmd->create_bus.bus_inst_uuid; + + list_add(&bus_info->entry, &bus_info_list); + + POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); + +cleanup: + bus_epilog(bus_no, CONTROLVM_BUS_CREATE, &inmsg->hdr, + rc, inmsg->hdr.flags.response_expected == 1); +} + +static void +bus_destroy(struct controlvm_message *inmsg) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no = cmd->destroy_bus.bus_no; + struct visorchipset_bus_info *bus_info; + int rc = CONTROLVM_RESP_SUCCESS; + + bus_info = bus_find(&bus_info_list, bus_no); + if (!bus_info) + rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; + else if (bus_info->state.created == 0) + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + + bus_epilog(bus_no, CONTROLVM_BUS_DESTROY, &inmsg->hdr, + rc, inmsg->hdr.flags.response_expected == 1); +} + +static void +bus_configure(struct controlvm_message *inmsg, + struct parser_context *parser_ctx) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no; + struct visorchipset_bus_info *bus_info; + int rc = CONTROLVM_RESP_SUCCESS; + char s[99]; + + bus_no = cmd->configure_bus.bus_no; + POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no, + POSTCODE_SEVERITY_INFO); + + bus_info = bus_find(&bus_info_list, bus_no); + if (!bus_info) { + POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; + } else if (bus_info->state.created == 0) { + POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; + } else if (bus_info->pending_msg_hdr.id != CONTROLVM_INVALID) { + POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; + } else { + bus_info->partition_handle = cmd->configure_bus.guest_handle; + bus_info->partition_uuid = parser_id_get(parser_ctx); + parser_param_start(parser_ctx, PARSERSTRING_NAME); + bus_info->name = parser_string_get(parser_ctx); + + visorchannel_uuid_id(&bus_info->partition_uuid, s); + POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no, + POSTCODE_SEVERITY_INFO); + } + bus_epilog(bus_no, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr, + rc, inmsg->hdr.flags.response_expected == 1); +} + +static void +my_device_create(struct controlvm_message *inmsg) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no = cmd->create_device.bus_no; + u32 dev_no = cmd->create_device.dev_no; + struct visorchipset_device_info *dev_info; + struct visorchipset_bus_info *bus_info; + int rc = CONTROLVM_RESP_SUCCESS; + + dev_info = device_find(&dev_info_list, bus_no, dev_no); + if (dev_info && (dev_info->state.created == 1)) { + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + goto cleanup; + } + bus_info = bus_find(&bus_info_list, bus_no); + if (!bus_info) { + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; + goto cleanup; + } + if (bus_info->state.created == 0) { + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; + goto cleanup; + } + dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); + if (!dev_info) { + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; + goto cleanup; + } + + INIT_LIST_HEAD(&dev_info->entry); + dev_info->bus_no = bus_no; + dev_info->dev_no = dev_no; + dev_info->dev_inst_uuid = cmd->create_device.dev_inst_uuid; + POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, + POSTCODE_SEVERITY_INFO); + + if (inmsg->hdr.flags.test_message == 1) + dev_info->chan_info.addr_type = ADDRTYPE_LOCALTEST; + else + dev_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL; + dev_info->chan_info.channel_addr = cmd->create_device.channel_addr; + dev_info->chan_info.n_channel_bytes = cmd->create_device.channel_bytes; + dev_info->chan_info.channel_type_uuid = + cmd->create_device.data_type_uuid; + dev_info->chan_info.intr = cmd->create_device.intr; + list_add(&dev_info->entry, &dev_info_list); + POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, + POSTCODE_SEVERITY_INFO); +cleanup: + /* get the bus and devNo for DiagPool channel */ + if (dev_info && + is_diagpool_channel(dev_info->chan_info.channel_type_uuid)) { + g_diagpool_bus_no = bus_no; + g_diagpool_dev_no = dev_no; + } + device_epilog(bus_no, dev_no, segment_state_running, + CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc, + inmsg->hdr.flags.response_expected == 1, + FOR_VISORBUS(dev_info->chan_info.channel_type_uuid)); +} + +static void +my_device_changestate(struct controlvm_message *inmsg) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no = cmd->device_change_state.bus_no; + u32 dev_no = cmd->device_change_state.dev_no; + struct spar_segment_state state = cmd->device_change_state.state; + struct visorchipset_device_info *dev_info; + int rc = CONTROLVM_RESP_SUCCESS; + + dev_info = device_find(&dev_info_list, bus_no, dev_no); + if (!dev_info) { + POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; + } else if (dev_info->state.created == 0) { + POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; + } + if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info) + device_epilog(bus_no, dev_no, state, + CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc, + inmsg->hdr.flags.response_expected == 1, + FOR_VISORBUS( + dev_info->chan_info.channel_type_uuid)); +} + +static void +my_device_destroy(struct controlvm_message *inmsg) +{ + struct controlvm_message_packet *cmd = &inmsg->cmd; + u32 bus_no = cmd->destroy_device.bus_no; + u32 dev_no = cmd->destroy_device.dev_no; + struct visorchipset_device_info *dev_info; + int rc = CONTROLVM_RESP_SUCCESS; + + dev_info = device_find(&dev_info_list, bus_no, dev_no); + if (!dev_info) + rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; + else if (dev_info->state.created == 0) + rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; + + if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info) + device_epilog(bus_no, dev_no, segment_state_running, + CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc, + inmsg->hdr.flags.response_expected == 1, + FOR_VISORBUS( + dev_info->chan_info.channel_type_uuid)); +} + +/* When provided with the physical address of the controlvm channel + * (phys_addr), the offset to the payload area we need to manage + * (offset), and the size of this payload area (bytes), fills in the + * controlvm_payload_info struct. Returns true for success or false + * for failure. + */ +static int +initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, + struct visor_controlvm_payload_info *info) +{ + u8 __iomem *payload = NULL; + int rc = CONTROLVM_RESP_SUCCESS; + + if (!info) { + rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + goto cleanup; + } + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); + if ((offset == 0) || (bytes == 0)) { + rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + goto cleanup; + } + payload = ioremap_cache(phys_addr + offset, bytes); + if (!payload) { + rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; + goto cleanup; + } + + info->offset = offset; + info->bytes = bytes; + info->ptr = payload; + +cleanup: + if (rc < 0) { + if (payload) { + iounmap(payload); + payload = NULL; + } + } + return rc; +} + +static void +destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info) +{ + if (info->ptr) { + iounmap(info->ptr); + info->ptr = NULL; + } + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); +} + +static void +initialize_controlvm_payload(void) +{ + HOSTADDRESS phys_addr = visorchannel_get_physaddr(controlvm_channel); + u64 payload_offset = 0; + u32 payload_bytes = 0; + + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + request_payload_offset), + &payload_offset, sizeof(payload_offset)) < 0) { + POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + request_payload_bytes), + &payload_bytes, sizeof(payload_bytes)) < 0) { + POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + initialize_controlvm_payload_info(phys_addr, + payload_offset, payload_bytes, + &controlvm_payload_info); +} + +/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. + * Returns CONTROLVM_RESP_xxx code. + */ +int +visorchipset_chipset_ready(void) +{ + kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE); + return CONTROLVM_RESP_SUCCESS; +} +EXPORT_SYMBOL_GPL(visorchipset_chipset_ready); + +int +visorchipset_chipset_selftest(void) +{ + char env_selftest[20]; + char *envp[] = { env_selftest, NULL }; + + sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); + kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, + envp); + return CONTROLVM_RESP_SUCCESS; +} +EXPORT_SYMBOL_GPL(visorchipset_chipset_selftest); + +/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. + * Returns CONTROLVM_RESP_xxx code. + */ +int +visorchipset_chipset_notready(void) +{ + kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE); + return CONTROLVM_RESP_SUCCESS; +} +EXPORT_SYMBOL_GPL(visorchipset_chipset_notready); + +static void +chipset_ready(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_ready(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready) + controlvm_respond(msg_hdr, rc); + if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) { + /* Send CHIPSET_READY response when all modules have been loaded + * and disks mounted for the partition + */ + g_chipset_msg_hdr = *msg_hdr; + } +} + +static void +chipset_selftest(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_selftest(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected) + controlvm_respond(msg_hdr, rc); +} + +static void +chipset_notready(struct controlvm_message_header *msg_hdr) +{ + int rc = visorchipset_chipset_notready(); + + if (rc != CONTROLVM_RESP_SUCCESS) + rc = -rc; + if (msg_hdr->flags.response_expected) + controlvm_respond(msg_hdr, rc); +} + +/* This is your "one-stop" shop for grabbing the next message from the + * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. + */ +static bool +read_controlvm_event(struct controlvm_message *msg) +{ + if (visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_EVENT, msg)) { + /* got a message */ + if (msg->hdr.flags.test_message == 1) + return false; + return true; + } + return false; +} + +/* + * The general parahotplug flow works as follows. The visorchipset + * driver receives a DEVICE_CHANGESTATE message from Command + * specifying a physical device to enable or disable. The CONTROLVM + * message handler calls parahotplug_process_message, which then adds + * the message to a global list and kicks off a udev event which + * causes a user level script to enable or disable the specified + * device. The udev script then writes to + * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write + * to get called, at which point the appropriate CONTROLVM message is + * retrieved from the list and responded to. + */ + +#define PARAHOTPLUG_TIMEOUT_MS 2000 + +/* + * Generate unique int to match an outstanding CONTROLVM message with a + * udev script /proc response + */ +static int +parahotplug_next_id(void) +{ + static atomic_t id = ATOMIC_INIT(0); + + return atomic_inc_return(&id); +} + +/* + * Returns the time (in jiffies) when a CONTROLVM message on the list + * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future + */ +static unsigned long +parahotplug_next_expiration(void) +{ + return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); +} + +/* + * Create a parahotplug_request, which is basically a wrapper for a + * CONTROLVM_MESSAGE that we can stick on a list + */ +static struct parahotplug_request * +parahotplug_request_create(struct controlvm_message *msg) +{ + struct parahotplug_request *req; + + req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY); + if (!req) + return NULL; + + req->id = parahotplug_next_id(); + req->expiration = parahotplug_next_expiration(); + req->msg = *msg; + + return req; +} + +/* + * Free a parahotplug_request. + */ +static void +parahotplug_request_destroy(struct parahotplug_request *req) +{ + kfree(req); +} + +/* + * Cause uevent to run the user level script to do the disable/enable + * specified in (the CONTROLVM message in) the specified + * parahotplug_request + */ +static void +parahotplug_request_kickoff(struct parahotplug_request *req) +{ + struct controlvm_message_packet *cmd = &req->msg.cmd; + char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], + env_func[40]; + char *envp[] = { + env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL + }; + + sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); + sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); + sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", + cmd->device_change_state.state.active); + sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", + cmd->device_change_state.bus_no); + sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", + cmd->device_change_state.dev_no >> 3); + sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", + cmd->device_change_state.dev_no & 0x7); + + kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, + envp); +} + +/* + * Remove any request from the list that's been on there too long and + * respond with an error. + */ +static void +parahotplug_process_list(void) +{ + struct list_head *pos; + struct list_head *tmp; + + spin_lock(¶hotplug_request_list_lock); + + list_for_each_safe(pos, tmp, ¶hotplug_request_list) { + struct parahotplug_request *req = + list_entry(pos, struct parahotplug_request, list); + + if (!time_after_eq(jiffies, req->expiration)) + continue; + + list_del(pos); + if (req->msg.hdr.flags.response_expected) + controlvm_respond_physdev_changestate( + &req->msg.hdr, + CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, + req->msg.cmd.device_change_state.state); + parahotplug_request_destroy(req); + } + + spin_unlock(¶hotplug_request_list_lock); +} + +/* + * Called from the /proc handler, which means the user script has + * finished the enable/disable. Find the matching identifier, and + * respond to the CONTROLVM message with success. + */ +static int +parahotplug_request_complete(int id, u16 active) +{ + struct list_head *pos; + struct list_head *tmp; + + spin_lock(¶hotplug_request_list_lock); + + /* Look for a request matching "id". */ + list_for_each_safe(pos, tmp, ¶hotplug_request_list) { + struct parahotplug_request *req = + list_entry(pos, struct parahotplug_request, list); + if (req->id == id) { + /* Found a match. Remove it from the list and + * respond. + */ + list_del(pos); + spin_unlock(¶hotplug_request_list_lock); + req->msg.cmd.device_change_state.state.active = active; + if (req->msg.hdr.flags.response_expected) + controlvm_respond_physdev_changestate( + &req->msg.hdr, CONTROLVM_RESP_SUCCESS, + req->msg.cmd.device_change_state.state); + parahotplug_request_destroy(req); + return 0; + } + } + + spin_unlock(¶hotplug_request_list_lock); + return -1; +} + +/* + * Enables or disables a PCI device by kicking off a udev script + */ +static void +parahotplug_process_message(struct controlvm_message *inmsg) +{ + struct parahotplug_request *req; + + req = parahotplug_request_create(inmsg); + + if (!req) + return; + + if (inmsg->cmd.device_change_state.state.active) { + /* For enable messages, just respond with success + * right away. This is a bit of a hack, but there are + * issues with the early enable messages we get (with + * either the udev script not detecting that the device + * is up, or not getting called at all). Fortunately + * the messages that get lost don't matter anyway, as + * devices are automatically enabled at + * initialization. + */ + parahotplug_request_kickoff(req); + controlvm_respond_physdev_changestate(&inmsg->hdr, + CONTROLVM_RESP_SUCCESS, + inmsg->cmd.device_change_state.state); + parahotplug_request_destroy(req); + } else { + /* For disable messages, add the request to the + * request list before kicking off the udev script. It + * won't get responded to until the script has + * indicated it's done. + */ + spin_lock(¶hotplug_request_list_lock); + list_add_tail(&req->list, ¶hotplug_request_list); + spin_unlock(¶hotplug_request_list_lock); + + parahotplug_request_kickoff(req); + } +} + +/* Process a controlvm message. + * Return result: + * false - this function will return FALSE only in the case where the + * controlvm message was NOT processed, but processing must be + * retried before reading the next controlvm message; a + * scenario where this can occur is when we need to throttle + * the allocation of memory in which to copy out controlvm + * payload data + * true - processing of the controlvm message completed, + * either successfully or with an error. + */ +static bool +handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) +{ + struct controlvm_message_packet *cmd = &inmsg.cmd; + u64 parm_addr; + u32 parm_bytes; + struct parser_context *parser_ctx = NULL; + bool local_addr; + struct controlvm_message ackmsg; + + /* create parsing context if necessary */ + local_addr = (inmsg.hdr.flags.test_message == 1); + if (channel_addr == 0) + return true; + parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; + parm_bytes = inmsg.hdr.payload_bytes; + + /* Parameter and channel addresses within test messages actually lie + * within our OS-controlled memory. We need to know that, because it + * makes a difference in how we compute the virtual address. + */ + if (parm_addr && parm_bytes) { + bool retry = false; + + parser_ctx = + parser_init_byte_stream(parm_addr, parm_bytes, + local_addr, &retry); + if (!parser_ctx && retry) + return false; + } + + if (!local_addr) { + controlvm_init_response(&ackmsg, &inmsg.hdr, + CONTROLVM_RESP_SUCCESS); + if (controlvm_channel) + visorchannel_signalinsert(controlvm_channel, + CONTROLVM_QUEUE_ACK, + &ackmsg); + } + switch (inmsg.hdr.id) { + case CONTROLVM_CHIPSET_INIT: + chipset_init(&inmsg); + break; + case CONTROLVM_BUS_CREATE: + bus_create(&inmsg); + break; + case CONTROLVM_BUS_DESTROY: + bus_destroy(&inmsg); + break; + case CONTROLVM_BUS_CONFIGURE: + bus_configure(&inmsg, parser_ctx); + break; + case CONTROLVM_DEVICE_CREATE: + my_device_create(&inmsg); + break; + case CONTROLVM_DEVICE_CHANGESTATE: + if (cmd->device_change_state.flags.phys_device) { + parahotplug_process_message(&inmsg); + } else { + /* save the hdr and cmd structures for later use */ + /* when sending back the response to Command */ + my_device_changestate(&inmsg); + g_devicechangestate_packet = inmsg.cmd; + break; + } + break; + case CONTROLVM_DEVICE_DESTROY: + my_device_destroy(&inmsg); + break; + case CONTROLVM_DEVICE_CONFIGURE: + /* no op for now, just send a respond that we passed */ + if (inmsg.hdr.flags.response_expected) + controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); + break; + case CONTROLVM_CHIPSET_READY: + chipset_ready(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_SELFTEST: + chipset_selftest(&inmsg.hdr); + break; + case CONTROLVM_CHIPSET_STOP: + chipset_notready(&inmsg.hdr); + break; + default: + if (inmsg.hdr.flags.response_expected) + controlvm_respond(&inmsg.hdr, + -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); + break; + } + + if (parser_ctx) { + parser_done(parser_ctx); + parser_ctx = NULL; + } + return true; +} + +static HOSTADDRESS controlvm_get_channel_address(void) +{ + u64 addr = 0; + u32 size = 0; + + if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size))) + return 0; + + return addr; +} + +static void +controlvm_periodic_work(struct work_struct *work) +{ + struct controlvm_message inmsg; + bool got_command = false; + bool handle_command_failed = false; + static u64 poll_count; + + /* make sure visorbus server is registered for controlvm callbacks */ + if (visorchipset_serverregwait && !serverregistered) + goto cleanup; + /* make sure visorclientbus server is regsitered for controlvm + * callbacks + */ + if (visorchipset_clientregwait && !clientregistered) + goto cleanup; + + poll_count++; + if (poll_count >= 250) + ; /* keep going */ + else + goto cleanup; + + /* Check events to determine if response to CHIPSET_READY + * should be sent + */ + if (visorchipset_holdchipsetready && + (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) { + if (check_chipset_events() == 1) { + controlvm_respond(&g_chipset_msg_hdr, 0); + clear_chipset_events(); + memset(&g_chipset_msg_hdr, 0, + sizeof(struct controlvm_message_header)); + } + } + + while (visorchannel_signalremove(controlvm_channel, + CONTROLVM_QUEUE_RESPONSE, + &inmsg)) + ; + if (!got_command) { + if (controlvm_pending_msg_valid) { + /* we throttled processing of a prior + * msg, so try to process it again + * rather than reading a new one + */ + inmsg = controlvm_pending_msg; + controlvm_pending_msg_valid = false; + got_command = true; + } else { + got_command = read_controlvm_event(&inmsg); + } + } + + handle_command_failed = false; + while (got_command && (!handle_command_failed)) { + most_recent_message_jiffies = jiffies; + if (handle_command(inmsg, + visorchannel_get_physaddr + (controlvm_channel))) + got_command = read_controlvm_event(&inmsg); + else { + /* this is a scenario where throttling + * is required, but probably NOT an + * error...; we stash the current + * controlvm msg so we will attempt to + * reprocess it on our next loop + */ + handle_command_failed = true; + controlvm_pending_msg = inmsg; + controlvm_pending_msg_valid = true; + } + } + + /* parahotplug_worker */ + parahotplug_process_list(); + +cleanup: + + if (time_after(jiffies, + most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { + /* it's been longer than MIN_IDLE_SECONDS since we + * processed our last controlvm message; slow down the + * polling + */ + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + } else { + if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + } + + queue_delayed_work(periodic_controlvm_workqueue, + &periodic_controlvm_work, poll_jiffies); +} + +static void +setup_crash_devices_work_queue(struct work_struct *work) +{ + struct controlvm_message local_crash_bus_msg; + struct controlvm_message local_crash_dev_msg; + struct controlvm_message msg; + u32 local_crash_msg_offset; + u16 local_crash_msg_count; + + /* make sure visorbus server is registered for controlvm callbacks */ + if (visorchipset_serverregwait && !serverregistered) + goto cleanup; + + /* make sure visorclientbus server is regsitered for controlvm + * callbacks + */ + if (visorchipset_clientregwait && !clientregistered) + goto cleanup; + + POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); + + /* send init chipset msg */ + msg.hdr.id = CONTROLVM_CHIPSET_INIT; + msg.cmd.init_chipset.bus_count = 23; + msg.cmd.init_chipset.switch_count = 0; + + chipset_init(&msg); + + /* get saved message 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; + } + + /* get saved crash message offset */ + 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; + } + + /* read create device message for storage bus offset */ + if (visorchannel_read(controlvm_channel, + local_crash_msg_offset, + &local_crash_bus_msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + /* read create device message for storage device */ + if (visorchannel_read(controlvm_channel, + local_crash_msg_offset + + sizeof(struct controlvm_message), + &local_crash_dev_msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + /* reuse IOVM create bus message */ + if (local_crash_bus_msg.cmd.create_bus.channel_addr) { + bus_create(&local_crash_bus_msg); + } else { + POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + /* reuse create device message for storage device */ + if (local_crash_dev_msg.cmd.create_device.channel_addr) { + my_device_create(&local_crash_dev_msg); + } else { + POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); + return; + +cleanup: + + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + + queue_delayed_work(periodic_controlvm_workqueue, + &periodic_controlvm_work, poll_jiffies); +} + +static void +bus_create_response(u32 bus_no, int response) +{ + bus_responder(CONTROLVM_BUS_CREATE, bus_no, response); +} + +static void +bus_destroy_response(u32 bus_no, int response) +{ + bus_responder(CONTROLVM_BUS_DESTROY, bus_no, response); +} + +static void +device_create_response(u32 bus_no, u32 dev_no, int response) +{ + device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response); +} + +static void +device_destroy_response(u32 bus_no, u32 dev_no, int response) +{ + device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response); +} + +void +visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response) +{ + device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, + bus_no, dev_no, response, + segment_state_standby); +} +EXPORT_SYMBOL_GPL(visorchipset_device_pause_response); + +static void +device_resume_response(u32 bus_no, u32 dev_no, int response) +{ + device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, + bus_no, dev_no, response, + segment_state_running); +} + +bool +visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info) +{ + void *p = bus_find(&bus_info_list, bus_no); + + if (!p) + return false; + memcpy(bus_info, p, sizeof(struct visorchipset_bus_info)); + return true; +} +EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); + +bool +visorchipset_set_bus_context(u32 bus_no, void *context) +{ + struct visorchipset_bus_info *p = bus_find(&bus_info_list, bus_no); + + if (!p) + return false; + p->bus_driver_context = context; + return true; +} +EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); + +bool +visorchipset_get_device_info(u32 bus_no, u32 dev_no, + struct visorchipset_device_info *dev_info) +{ + void *p = device_find(&dev_info_list, bus_no, dev_no); + + if (!p) + return false; + memcpy(dev_info, p, sizeof(struct visorchipset_device_info)); + return true; +} +EXPORT_SYMBOL_GPL(visorchipset_get_device_info); + +bool +visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context) +{ + struct visorchipset_device_info *p; + + p = device_find(&dev_info_list, bus_no, dev_no); + + if (!p) + return false; + p->bus_driver_context = context; + return true; +} +EXPORT_SYMBOL_GPL(visorchipset_set_device_context); + +/* Generic wrapper function for allocating memory from a kmem_cache pool. + */ +void * +visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, + char *fn, int ln) +{ + gfp_t gfp; + void *p; + + if (ok_to_block) + gfp = GFP_KERNEL; + else + gfp = GFP_ATOMIC; + /* __GFP_NORETRY means "ok to fail", meaning + * kmem_cache_alloc() can return NULL, implying the caller CAN + * cope with failure. If you do NOT specify __GFP_NORETRY, + * Linux will go to extreme measures to get memory for you + * (like, invoke oom killer), which will probably cripple the + * system. + */ + gfp |= __GFP_NORETRY; + p = kmem_cache_alloc(pool, gfp); + if (!p) + return NULL; + + return p; +} + +/* Generic wrapper function for freeing memory from a kmem_cache pool. + */ +void +visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln) +{ + if (!p) + return; + + kmem_cache_free(pool, p); +} + +static ssize_t chipsetready_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char msgtype[64]; + + if (sscanf(buf, "%63s", msgtype) != 1) + return -EINVAL; + + if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) { + chipset_events[0] = 1; + return count; + } else if (!strcmp(msgtype, "MODULES_LOADED")) { + chipset_events[1] = 1; + return count; + } + return -EINVAL; +} + +/* The parahotplug/devicedisabled interface gets called by our support script + * when an SR-IOV device has been shut down. The ID is passed to the script + * and then passed back when the device has been removed. + */ +static ssize_t devicedisabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + parahotplug_request_complete(id, 0); + return count; +} + +/* The parahotplug/deviceenabled interface gets called by our support script + * when an SR-IOV device has been recovered. The ID is passed to the script + * and then passed back when the device has been brought back up. + */ +static ssize_t deviceenabled_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int id; + + if (kstrtouint(buf, 10, &id)) + return -EINVAL; + + parahotplug_request_complete(id, 1); + return count; +} + +static int +visorchipset_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long physaddr = 0; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + GUEST_PHYSICAL_ADDRESS addr = 0; + + /* sv_enable_dfp(); */ + if (offset & (PAGE_SIZE - 1)) + return -ENXIO; /* need aligned offsets */ + + switch (offset) { + case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: + vma->vm_flags |= VM_IO; + if (!*file_controlvm_channel) + return -ENXIO; + + visorchannel_read(*file_controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + gp_control_channel), + &addr, sizeof(addr)); + if (!addr) + return -ENXIO; + + physaddr = (unsigned long)addr; + if (remap_pfn_range(vma, vma->vm_start, + physaddr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + /*pgprot_noncached */ + (vma->vm_page_prot))) { + return -EAGAIN; + } + break; + default: + return -ENXIO; + } + return 0; +} + +static long visorchipset_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + s64 adjustment; + s64 vrtc_offset; + + switch (cmd) { + case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: + /* get the physical rtc offset */ + vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); + if (copy_to_user((void __user *)arg, &vrtc_offset, + sizeof(vrtc_offset))) { + return -EFAULT; + } + return SUCCESS; + case VMCALL_UPDATE_PHYSICAL_TIME: + if (copy_from_user(&adjustment, (void __user *)arg, + sizeof(adjustment))) { + return -EFAULT; + } + return issue_vmcall_update_physical_time(adjustment); + default: + return -EFAULT; + } +} + +static const struct file_operations visorchipset_fops = { + .owner = THIS_MODULE, + .open = visorchipset_open, + .read = NULL, + .write = NULL, + .unlocked_ioctl = visorchipset_ioctl, + .release = visorchipset_release, + .mmap = visorchipset_mmap, +}; + +int +visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) +{ + int rc = 0; + + file_controlvm_channel = controlvm_channel; + cdev_init(&file_cdev, &visorchipset_fops); + file_cdev.owner = THIS_MODULE; + if (MAJOR(major_dev) == 0) { + rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset"); + /* dynamic major device number registration required */ + if (rc < 0) + return rc; + } else { + /* static major device number registration required */ + rc = register_chrdev_region(major_dev, 1, "visorchipset"); + if (rc < 0) + return rc; + } + rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1); + if (rc < 0) { + unregister_chrdev_region(major_dev, 1); + return rc; + } + return 0; +} + + + +static int __init +visorchipset_init(void) +{ + int rc = 0, x = 0; + HOSTADDRESS addr; + + if (!unisys_spar_platform) + return -ENODEV; + + memset(&busdev_server_notifiers, 0, sizeof(busdev_server_notifiers)); + memset(&busdev_client_notifiers, 0, sizeof(busdev_client_notifiers)); + memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); + memset(&livedump_info, 0, sizeof(livedump_info)); + atomic_set(&livedump_info.buffers_in_use, 0); + + if (visorchipset_testvnic) { + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, x, DIAG_SEVERITY_ERR); + rc = x; + goto cleanup; + } + + addr = controlvm_get_channel_address(); + if (addr) { + controlvm_channel = + visorchannel_create_with_lock + (addr, + sizeof(struct spar_controlvm_channel_protocol), + spar_controlvm_channel_protocol_uuid); + if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT( + visorchannel_get_header(controlvm_channel))) { + initialize_controlvm_payload(); + } else { + visorchannel_destroy(controlvm_channel); + controlvm_channel = NULL; + return -ENODEV; + } + } else { + return -ENODEV; + } + + major_dev = MKDEV(visorchipset_major, 0); + rc = visorchipset_file_init(major_dev, &controlvm_channel); + if (rc < 0) { + POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR); + goto cleanup; + } + + memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); + + if (!visorchipset_disable_controlvm) { + /* if booting in a crash kernel */ + if (is_kdump_kernel()) + INIT_DELAYED_WORK(&periodic_controlvm_work, + setup_crash_devices_work_queue); + else + INIT_DELAYED_WORK(&periodic_controlvm_work, + controlvm_periodic_work); + periodic_controlvm_workqueue = + create_singlethread_workqueue("visorchipset_controlvm"); + + if (!periodic_controlvm_workqueue) { + POSTCODE_LINUX_2(CREATE_WORKQUEUE_FAILED_PC, + DIAG_SEVERITY_ERR); + rc = -ENOMEM; + goto cleanup; + } + most_recent_message_jiffies = jiffies; + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + rc = queue_delayed_work(periodic_controlvm_workqueue, + &periodic_controlvm_work, poll_jiffies); + if (rc < 0) { + POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, + DIAG_SEVERITY_ERR); + goto cleanup; + } + } + + visorchipset_platform_device.dev.devt = major_dev; + if (platform_device_register(&visorchipset_platform_device) < 0) { + POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR); + rc = -1; + goto cleanup; + } + POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO); + + rc = visorbus_init(); +cleanup: + if (rc) { + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, + POSTCODE_SEVERITY_ERR); + } + return rc; +} + +void +visorchipset_file_cleanup(dev_t major_dev) +{ + if (file_cdev.ops) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + unregister_chrdev_region(major_dev, 1); +} + +static void +visorchipset_exit(void) +{ + POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO); + + visorbus_exit(); + + if (visorchipset_disable_controlvm) { + ; + } else { + cancel_delayed_work(&periodic_controlvm_work); + flush_workqueue(periodic_controlvm_workqueue); + destroy_workqueue(periodic_controlvm_workqueue); + periodic_controlvm_workqueue = NULL; + destroy_controlvm_payload_info(&controlvm_payload_info); + } + + cleanup_controlvm_structures(); + + memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); + + visorchannel_destroy(controlvm_channel); + + visorchipset_file_cleanup(visorchipset_platform_device.dev.devt); + POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO); +} + +module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_testvnic, "1 to test vnic, using dummy VNIC connected via a loopback to a physical ethernet"); +module_param_named(testvnicclient, visorchipset_testvnicclient, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_testvnicclient, "1 to test vnic, using real VNIC channel attached to a separate IOVM guest"); +module_param_named(testmsg, visorchipset_testmsg, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_testmsg, + "1 to manufacture the chipset, bus, and switch messages"); +module_param_named(major, visorchipset_major, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_major, + "major device number to use for the device node"); +module_param_named(serverregwait, visorchipset_serverregwait, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_serverreqwait, + "1 to have the module wait for the visor bus to register"); +module_param_named(clientregwait, visorchipset_clientregwait, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_clientregwait, "1 to have the module wait for the visorclientbus to register"); +module_param_named(testteardown, visorchipset_testteardown, int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_testteardown, + "1 to test teardown of the chipset, bus, and switch"); +module_param_named(disable_controlvm, visorchipset_disable_controlvm, int, + S_IRUGO); +MODULE_PARM_DESC(visorchipset_disable_controlvm, + "1 to disable polling of controlVm channel"); +module_param_named(holdchipsetready, visorchipset_holdchipsetready, + int, S_IRUGO); +MODULE_PARM_DESC(visorchipset_holdchipsetready, + "1 to hold response to CHIPSET_READY"); + +module_init(visorchipset_init); +module_exit(visorchipset_exit); + +MODULE_AUTHOR("Unisys"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver " + VERSION); +MODULE_VERSION(VERSION); diff --git a/drivers/staging/unisys/visorchipset/Kconfig b/drivers/staging/unisys/visorchipset/Kconfig deleted file mode 100644 index 01d9a9a0e904..000000000000 --- a/drivers/staging/unisys/visorchipset/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -# -# Unisys visorchipset configuration -# - -config UNISYS_VISORCHIPSET - tristate "Unisys visorchipset driver" - select UNISYS_VISORUTIL - select UNISYS_VISORBUS - ---help--- - If you say Y here, you will enable the Unisys visorchipset driver. - diff --git a/drivers/staging/unisys/visorchipset/Makefile b/drivers/staging/unisys/visorchipset/Makefile deleted file mode 100644 index e9168d8d69a5..000000000000 --- a/drivers/staging/unisys/visorchipset/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for Unisys visorchipset -# - -obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset.o - -visorchipset-y := visorchipset_main.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/uislib -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels -ccflags-y += -Idrivers/staging/unisys/visorutil -ccflags-y += -Idrivers/staging/unisys/visorbus -ccflags-y += -Iinclude/generated diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h deleted file mode 100644 index 264a3e9226ea..000000000000 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ /dev/null @@ -1,214 +0,0 @@ -/* visorchipset.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHIPSET_H__ -#define __VISORCHIPSET_H__ - -#include - -#include "channel.h" -#include "controlvmchannel.h" -#include "procobjecttree.h" -#include "vbusdeviceinfo.h" -#include "vbushelper.h" - -#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 - -/** Describes the state from the perspective of which controlvm messages have - * been received for a bus or device. - */ - -enum PARSER_WHICH_STRING { - PARSERSTRING_INITIATOR, - PARSERSTRING_TARGET, - PARSERSTRING_CONNECTION, - PARSERSTRING_NAME, -}; - -struct visorchannel; -struct parser_context *parser_init(u64 addr, u32 bytes, bool isLocal, - bool *tryAgain); -struct parser_context *parser_init_byte_stream(u64 addr, u32 bytes, bool local, - bool *retry); -void parser_param_start(struct parser_context *ctx, - PARSER_WHICH_STRING which_string); -void *parser_param_get(struct parser_context *ctx, char *nam, int namesize); -void *parser_string_get(struct parser_context *ctx); -uuid_le parser_id_get(struct parser_context *ctx); -char *parser_simpleString_get(struct parser_context *ctx); -void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes); -void parser_done(struct parser_context *ctx); - -struct visorchipset_state { - u32 created:1; - u32 attached:1; - u32 configured:1; - u32 running:1; - /* Add new fields above. */ - /* Remaining bits in this 32-bit word are unused. */ -}; - -enum visorchipset_addresstype { - /** address is guest physical, but outside of the physical memory - * region that is controlled by the running OS (this is the normal - * address type for Supervisor channels) - */ - ADDRTYPE_LOCALPHYSICAL, - - /** address is guest physical, and withIN the confines of the - * physical memory controlled by the running OS. - */ - ADDRTYPE_LOCALTEST, -}; - -enum crash_obj_type { - CRASH_DEV, - CRASH_BUS, -}; - -/** Attributes for a particular Supervisor channel. - */ -struct visorchipset_channel_info { - enum visorchipset_addresstype addr_type; - HOSTADDRESS channel_addr; - struct irq_info intr; - u64 n_channel_bytes; - uuid_le channel_type_uuid; - uuid_le channel_inst_uuid; -}; - -/** Attributes for a particular Supervisor device. - * Any visorchipset client can query these attributes using - * visorchipset_get_client_device_info() or - * visorchipset_get_server_device_info(). - */ -struct visorchipset_device_info { - struct list_head entry; - u32 bus_no; - u32 dev_no; - uuid_le dev_inst_uuid; - struct visorchipset_state state; - struct visorchipset_channel_info chan_info; - u32 reserved1; /* control_vm_id */ - u64 reserved2; - u32 switch_no; /* when devState.attached==1 */ - u32 internal_port_no; /* when devState.attached==1 */ - struct controlvm_message_header pending_msg_hdr;/* CONTROLVM_MESSAGE */ - /** For private use by the bus driver */ - void *bus_driver_context; -}; - -/** Attributes for a particular Supervisor bus. - * (For a service partition acting as the server for buses/devices, there - * is a 1-to-1 relationship between busses and guest partitions.) - * Any visorchipset client can query these attributes using - * visorchipset_get_client_bus_info() or visorchipset_get_bus_info(). - */ -struct visorchipset_bus_info { - struct list_head entry; - u32 bus_no; - struct visorchipset_state state; - struct visorchipset_channel_info chan_info; - uuid_le partition_uuid; - u64 partition_handle; - u8 *name; /* UTF8 */ - u8 *description; /* UTF8 */ - u64 reserved1; - u32 reserved2; - struct { - u32 server:1; - /* Add new fields above. */ - /* Remaining bits in this 32-bit word are unused. */ - } flags; - struct controlvm_message_header pending_msg_hdr;/* CONTROLVM MsgHdr */ - /** For private use by the bus driver */ - void *bus_driver_context; -}; - -/* These functions will be called from within visorchipset when certain - * events happen. (The implementation of these functions is outside of - * visorchipset.) - */ -struct visorchipset_busdev_notifiers { - void (*bus_create)(u32 bus_no); - void (*bus_destroy)(u32 bus_no); - void (*device_create)(u32 bus_no, u32 dev_no); - void (*device_destroy)(u32 bus_no, u32 dev_no); - void (*device_pause)(u32 bus_no, u32 dev_no); - void (*device_resume)(u32 bus_no, u32 dev_no); -}; - -/* These functions live inside visorchipset, and will be called to indicate - * responses to specific events (by code outside of visorchipset). - * For now, the value for each response is simply either: - * 0 = it worked - * -1 = it failed - */ -struct visorchipset_busdev_responders { - void (*bus_create)(u32 bus_no, int response); - void (*bus_destroy)(u32 bus_no, int response); - void (*device_create)(u32 bus_no, u32 dev_no, int response); - void (*device_destroy)(u32 bus_no, u32 dev_no, int response); - void (*device_pause)(u32 bus_no, u32 dev_no, int response); - void (*device_resume)(u32 bus_no, u32 dev_no, int response); -}; - -/** Register functions (in the bus driver) to get called by visorchipset - * whenever a bus or device appears for which this service partition is - * to be the server for. visorchipset will fill in , to - * indicate functions the bus driver should call to indicate message - * responses. - */ -void -visorchipset_register_busdev_client( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info); - -/** Register functions (in the bus driver) to get called by visorchipset - * whenever a bus or device appears for which this service partition is - * to be the client for. visorchipset will fill in , to - * indicate functions the bus driver should call to indicate message - * responses. - */ -void -visorchipset_register_busdev_server( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info); - -void visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response); - -bool visorchipset_get_bus_info(u32 bus_no, - struct visorchipset_bus_info *bus_info); -bool visorchipset_get_device_info(u32 bus_no, u32 dev_no, - struct visorchipset_device_info *dev_info); -bool visorchipset_set_bus_context(u32 bus_no, void *context); -bool visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context); -int visorchipset_chipset_ready(void); -int visorchipset_chipset_selftest(void); -int visorchipset_chipset_notready(void); -void visorchipset_save_message(struct controlvm_message *msg, - enum crash_obj_type type); -void *visorchipset_cache_alloc(struct kmem_cache *pool, - bool ok_to_block, char *fn, int ln); -void visorchipset_cache_free(struct kmem_cache *pool, void *p, - char *fn, int ln); -int visorchipset_file_init(dev_t majorDev, - struct visorchannel **pControlVm_channel); -void visorchipset_file_cleanup(dev_t major_dev); -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c deleted file mode 100644 index dc9f1dc18306..000000000000 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ /dev/null @@ -1,2863 +0,0 @@ -/* visorchipset_main.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include "memregion.h" -#include "controlvmchannel.h" -#include "version.h" -#include "procobjecttree.h" -#include "visorbus.h" -#include "periodic_work.h" -#include "uisutils.h" -#include "controlvmcompletionstatus.h" -#include "guestlinuxdebug.h" -#include "visorchipset.h" - - -#include -#include -#include -#include -#include -#include -#include -#include - -#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c -#define TEST_VNIC_PHYSITF "eth0" /* physical network itf for - * vnic loopback test */ -#define TEST_VNIC_SWITCHNO 1 -#define TEST_VNIC_BUSNO 9 - -#define MAX_NAME_SIZE 128 -#define MAX_IP_SIZE 50 -#define MAXOUTSTANDINGCHANNELCOMMAND 256 -#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 -#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 - -#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) -/* - * Module parameters - */ -static int visorchipset_testvnic; -static int visorchipset_testvnicclient; -static int visorchipset_testmsg; -static int visorchipset_major; -static int visorchipset_serverregwait; -static int visorchipset_clientregwait = 1; /* default is on */ -static int visorchipset_testteardown; -static int visorchipset_disable_controlvm; -static int visorchipset_holdchipsetready; -static unsigned long controlvm_payload_bytes_buffered; - -static int -visorchipset_open(struct inode *inode, struct file *file) -{ - unsigned minor_number = iminor(inode); - - if (minor_number) - return -ENODEV; - file->private_data = NULL; - return 0; -} - -static int -visorchipset_release(struct inode *inode, struct file *file) -{ - return 0; -} - -/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS, -* we switch to slow polling mode. As soon as we get a controlvm -* message, we switch back to fast polling mode. -*/ -#define MIN_IDLE_SECONDS 10 -static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -static unsigned long most_recent_message_jiffies; /* when we got our last - * controlvm message */ -static int serverregistered; -static int clientregistered; - -#define MAX_CHIPSET_EVENTS 2 -static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 }; - -struct parser_context { - unsigned long allocbytes; - unsigned long param_bytes; - u8 *curr; - unsigned long bytes_remaining; - bool byte_stream; - char data[0]; -}; - -static struct delayed_work periodic_controlvm_work; -static struct workqueue_struct *periodic_controlvm_workqueue; -static DEFINE_SEMAPHORE(notifier_lock); - -static struct cdev file_cdev; -static struct visorchannel **file_controlvm_channel; -static struct controlvm_message_header g_chipset_msg_hdr; -static const uuid_le spar_diag_pool_channel_protocol_uuid = - SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID; -/* 0xffffff is an invalid Bus/Device number */ -static u32 g_diagpool_bus_no = 0xffffff; -static u32 g_diagpool_dev_no = 0xffffff; -static struct controlvm_message_packet g_devicechangestate_packet; - -/* Only VNIC and VHBA channels are sent to visorclientbus (aka - * "visorhackbus") - */ -#define FOR_VISORHACKBUS(channel_type_guid) \ - (((uuid_le_cmp(channel_type_guid,\ - spar_vnic_channel_protocol_uuid) == 0) ||\ - (uuid_le_cmp(channel_type_guid,\ - spar_vhba_channel_protocol_uuid) == 0))) -#define FOR_VISORBUS(channel_type_guid) (!(FOR_VISORHACKBUS(channel_type_guid))) - -#define is_diagpool_channel(channel_type_guid) \ - (uuid_le_cmp(channel_type_guid,\ - spar_diag_pool_channel_protocol_uuid) == 0) - -static LIST_HEAD(bus_info_list); -static LIST_HEAD(dev_info_list); - -static struct visorchannel *controlvm_channel; - -/* Manages the request payload in the controlvm channel */ -struct visor_controlvm_payload_info { - u8 __iomem *ptr; /* pointer to base address of payload pool */ - u64 offset; /* offset from beginning of controlvm - * channel to beginning of payload * pool */ - u32 bytes; /* number of bytes in payload pool */ -}; - -static struct visor_controlvm_payload_info controlvm_payload_info; - -/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / - * CONTROLVM_DUMP_GETTEXTDUMP / CONTROLVM_DUMP_COMPLETE conversation. - */ -struct visor_livedump_info { - struct controlvm_message_header dumpcapture_header; - struct controlvm_message_header gettextdump_header; - struct controlvm_message_header dumpcomplete_header; - bool gettextdump_outstanding; - u32 crc32; - unsigned long length; - atomic_t buffers_in_use; - unsigned long destination; -}; - -static struct visor_livedump_info livedump_info; - -/* The following globals are used to handle the scenario where we are unable to - * offload the payload from a controlvm message due to memory requirements. In - * this scenario, we simply stash the controlvm message, then attempt to - * process it again the next time controlvm_periodic_work() runs. - */ -static struct controlvm_message controlvm_pending_msg; -static bool controlvm_pending_msg_valid = false; - -/* This identifies a data buffer that has been received via a controlvm messages - * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation. - */ -struct putfile_buffer_entry { - struct list_head next; /* putfile_buffer_entry list */ - struct parser_context *parser_ctx; /* points to input data buffer */ -}; - -/* List of struct putfile_request *, via next_putfile_request member. - * Each entry in this list identifies an outstanding TRANSMIT_FILE - * conversation. - */ -static LIST_HEAD(putfile_request_list); - -/* This describes a buffer and its current state of transfer (e.g., how many - * bytes have already been supplied as putfile data, and how many bytes are - * remaining) for a putfile_request. - */ -struct putfile_active_buffer { - /* a payload from a controlvm message, containing a file data buffer */ - struct parser_context *parser_ctx; - /* points within data area of parser_ctx to next byte of data */ - u8 *pnext; - /* # bytes left from to the end of this data buffer */ - size_t bytes_remaining; -}; - -#define PUTFILE_REQUEST_SIG 0x0906101302281211 -/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE - * conversation. Structs of this type are dynamically linked into - * . - */ -struct putfile_request { - u64 sig; /* PUTFILE_REQUEST_SIG */ - - /* header from original TransmitFile request */ - struct controlvm_message_header controlvm_header; - u64 file_request_number; /* from original TransmitFile request */ - - /* link to next struct putfile_request */ - struct list_head next_putfile_request; - - /* most-recent sequence number supplied via a controlvm message */ - u64 data_sequence_number; - - /* head of putfile_buffer_entry list, which describes the data to be - * supplied as putfile data; - * - this list is added to when controlvm messages come in that supply - * file data - * - this list is removed from via the hotplug program that is actually - * consuming these buffers to write as file data */ - struct list_head input_buffer_list; - spinlock_t req_list_lock; /* lock for input_buffer_list */ - - /* waiters for input_buffer_list to go non-empty */ - wait_queue_head_t input_buffer_wq; - - /* data not yet read within current putfile_buffer_entry */ - struct putfile_active_buffer active_buf; - - /* <0 = failed, 0 = in-progress, >0 = successful; */ - /* note that this must be set with req_list_lock, and if you set <0, */ - /* it is your responsibility to also free up all of the other objects */ - /* in this struct (like input_buffer_list, active_buf.parser_ctx) */ - /* before releasing the lock */ - int completion_status; -}; - -struct parahotplug_request { - struct list_head list; - int id; - unsigned long expiration; - struct controlvm_message msg; -}; - -static LIST_HEAD(parahotplug_request_list); -static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ -static void parahotplug_process_list(void); - -/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE / - * CONTROLVM_REPORTEVENT. - */ -static struct visorchipset_busdev_notifiers busdev_server_notifiers; -static struct visorchipset_busdev_notifiers busdev_client_notifiers; - -static void bus_create_response(u32 bus_no, int response); -static void bus_destroy_response(u32 bus_no, int response); -static void device_create_response(u32 bus_no, u32 dev_no, int response); -static void device_destroy_response(u32 bus_no, u32 dev_no, int response); -static void device_resume_response(u32 bus_no, u32 dev_no, int response); - -static struct visorchipset_busdev_responders busdev_responders = { - .bus_create = bus_create_response, - .bus_destroy = bus_destroy_response, - .device_create = device_create_response, - .device_destroy = device_destroy_response, - .device_pause = visorchipset_device_pause_response, - .device_resume = device_resume_response, -}; - -/* info for /dev/visorchipset */ -static dev_t major_dev = -1; /**< indicates major num for device */ - -/* prototypes for attributes */ -static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, char *buf); -static ssize_t toolaction_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_RW(toolaction); - -static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, char *buf); -static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count); -static DEVICE_ATTR_RW(boottotool); - -static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf); -static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_RW(error); - -static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf); -static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_RW(textid); - -static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf); -static ssize_t remaining_steps_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_RW(remaining_steps); - -static ssize_t chipsetready_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(chipsetready); - -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(devicedisabled); - -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(deviceenabled); - -static struct attribute *visorchipset_install_attrs[] = { - &dev_attr_toolaction.attr, - &dev_attr_boottotool.attr, - &dev_attr_error.attr, - &dev_attr_textid.attr, - &dev_attr_remaining_steps.attr, - NULL -}; - -static struct attribute_group visorchipset_install_group = { - .name = "install", - .attrs = visorchipset_install_attrs -}; - -static struct attribute *visorchipset_guest_attrs[] = { - &dev_attr_chipsetready.attr, - NULL -}; - -static struct attribute_group visorchipset_guest_group = { - .name = "guest", - .attrs = visorchipset_guest_attrs -}; - -static struct attribute *visorchipset_parahotplug_attrs[] = { - &dev_attr_devicedisabled.attr, - &dev_attr_deviceenabled.attr, - NULL -}; - -static struct attribute_group visorchipset_parahotplug_group = { - .name = "parahotplug", - .attrs = visorchipset_parahotplug_attrs -}; - -static const struct attribute_group *visorchipset_dev_groups[] = { - &visorchipset_install_group, - &visorchipset_guest_group, - &visorchipset_parahotplug_group, - NULL -}; - -/* /sys/devices/platform/visorchipset */ -static struct platform_device visorchipset_platform_device = { - .name = "visorchipset", - .id = -1, - .dev.groups = visorchipset_dev_groups, -}; - -/* Function prototypes */ -static void controlvm_respond(struct controlvm_message_header *msg_hdr, - int response); -static void controlvm_respond_chipset_init( - struct controlvm_message_header *msg_hdr, int response, - enum ultra_chipset_feature features); -static void controlvm_respond_physdev_changestate( - struct controlvm_message_header *msg_hdr, int response, - struct spar_segment_state state); - - -static struct parser_context * -parser_init_guts(u64 addr, u32 bytes, bool local, - bool standard_payload_header, bool *retry) -{ - int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *rc = NULL; - struct parser_context *ctx = NULL; - struct memregion *rgn = NULL; - struct spar_controlvm_parameters_header *phdr = NULL; - - if (retry) - *retry = false; - if (!standard_payload_header) - /* alloc and 0 extra byte to ensure payload is - * '\0'-terminated - */ - allocbytes++; - if ((controlvm_payload_bytes_buffered + bytes) - > MAX_CONTROLVM_PAYLOAD_BYTES) { - if (retry) - *retry = true; - rc = NULL; - goto cleanup; - } - ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); - if (!ctx) { - if (retry) - *retry = true; - rc = NULL; - goto cleanup; - } - - ctx->allocbytes = allocbytes; - ctx->param_bytes = bytes; - ctx->curr = NULL; - ctx->bytes_remaining = 0; - ctx->byte_stream = false; - if (local) { - void *p; - - if (addr > virt_to_phys(high_memory - 1)) { - rc = NULL; - goto cleanup; - } - p = __va((unsigned long) (addr)); - memcpy(ctx->data, p, bytes); - } else { - rgn = visor_memregion_create(addr, bytes); - if (!rgn) { - rc = NULL; - goto cleanup; - } - if (visor_memregion_read(rgn, 0, ctx->data, bytes) < 0) { - rc = NULL; - goto cleanup; - } - } - if (!standard_payload_header) { - ctx->byte_stream = true; - rc = ctx; - goto cleanup; - } - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - if (phdr->total_length != bytes) { - rc = NULL; - goto cleanup; - } - if (phdr->total_length < phdr->header_length) { - rc = NULL; - goto cleanup; - } - if (phdr->header_length < - sizeof(struct spar_controlvm_parameters_header)) { - rc = NULL; - goto cleanup; - } - - rc = ctx; -cleanup: - if (rgn) { - visor_memregion_destroy(rgn); - rgn = NULL; - } - if (rc) { - controlvm_payload_bytes_buffered += ctx->param_bytes; - } else { - if (ctx) { - parser_done(ctx); - ctx = NULL; - } - } - return rc; -} - -struct parser_context * -parser_init(u64 addr, u32 bytes, bool local, bool *retry) -{ - return parser_init_guts(addr, bytes, local, true, retry); -} - -/* Call this instead of parser_init() if the payload area consists of just - * a sequence of bytes, rather than a struct spar_controlvm_parameters_header - * structures. Afterwards, you can call parser_simpleString_get() or - * parser_byteStream_get() to obtain the data. - */ -struct parser_context * -parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) -{ - return parser_init_guts(addr, bytes, local, false, retry); -} - -/* Obtain '\0'-terminated copy of string in payload area. - */ -char * -parser_simpleString_get(struct parser_context *ctx) -{ - if (!ctx->byte_stream) - return NULL; - return ctx->data; /* note this IS '\0'-terminated, because of - * the num of bytes we alloc+clear in - * parser_init_byteStream() */ -} - -/* Obtain a copy of the buffer in the payload area. - */ -void *parser_byte_stream_get(struct parser_context *ctx, unsigned long *nbytes) -{ - if (!ctx->byte_stream) - return NULL; - if (nbytes) - *nbytes = ctx->param_bytes; - return (void *)ctx->data; -} - -uuid_le -parser_id_get(struct parser_context *ctx) -{ - struct spar_controlvm_parameters_header *phdr = NULL; - - if (ctx == NULL) - return NULL_UUID_LE; - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - return phdr->id; -} - -void -parser_param_start(struct parser_context *ctx, PARSER_WHICH_STRING which_string) -{ - struct spar_controlvm_parameters_header *phdr = NULL; - - if (ctx == NULL) - goto Away; - phdr = (struct spar_controlvm_parameters_header *)(ctx->data); - switch (which_string) { - case PARSERSTRING_INITIATOR: - ctx->curr = ctx->data + phdr->initiator_offset; - ctx->bytes_remaining = phdr->initiator_length; - break; - case PARSERSTRING_TARGET: - ctx->curr = ctx->data + phdr->target_offset; - ctx->bytes_remaining = phdr->target_length; - break; - case PARSERSTRING_CONNECTION: - ctx->curr = ctx->data + phdr->connection_offset; - ctx->bytes_remaining = phdr->connection_length; - break; - case PARSERSTRING_NAME: - ctx->curr = ctx->data + phdr->name_offset; - ctx->bytes_remaining = phdr->name_length; - break; - default: - break; - } - -Away: - return; -} - -void -parser_done(struct parser_context *ctx) -{ - if (!ctx) - return; - controlvm_payload_bytes_buffered -= ctx->param_bytes; - kfree(ctx); -} - -/** Return length of string not counting trailing spaces. */ -static int -string_length_no_trail(char *s, int len) -{ - int i = len - 1; - - while (i >= 0) { - if (!isspace(s[i])) - return i + 1; - i--; - } - return 0; -} - -/** Grab the next name and value out of the parameter buffer. - * The entire parameter buffer looks like this: - * =\0 - * =\0 - * ... - * \0 - * If successful, the next value is returned within the supplied - * buffer (the value is always upper-cased), and the corresponding - * is returned within a kmalloc()ed buffer, whose pointer is - * provided as the return value of this function. - * (The total number of bytes allocated is strlen()+1.) - * - * NULL is returned to indicate failure, which can occur for several reasons: - * - all = pairs have already been processed - * - bad parameter - * - parameter buffer ends prematurely (couldn't find an '=' or '\0' within - * the confines of the parameter buffer) - * - the buffer is not large enough to hold the of the next - * parameter - */ -void * -parser_param_get(struct parser_context *ctx, char *nam, int namesize) -{ - u8 *pscan, *pnam = nam; - unsigned long nscan; - int value_length = -1, orig_value_length = -1; - void *value = NULL; - int i; - int closing_quote = 0; - - if (!ctx) - return NULL; - pscan = ctx->curr; - nscan = ctx->bytes_remaining; - if (nscan == 0) - return NULL; - if (*pscan == '\0') - /* This is the normal return point after you have processed - * all of the = pairs in a syntactically-valid - * parameter buffer. - */ - return NULL; - - /* skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - - while (*pscan != ':') { - if (namesize <= 0) - return NULL; - *pnam = toupper(*pscan); - pnam++; - namesize--; - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - if (namesize <= 0) - return NULL; - *pnam = '\0'; - nam[string_length_no_trail(nam, strlen(nam))] = '\0'; - - /* point to char immediately after ":" in ":" */ - pscan++; - nscan--; - /* skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - if (nscan == 0) - return NULL; - if (*pscan == '\'' || *pscan == '"') { - closing_quote = *pscan; - pscan++; - nscan--; - if (nscan == 0) - return NULL; - } - - /* look for a separator character, terminator character, or - * end of data - */ - for (i = 0, value_length = -1; i < nscan; i++) { - if (closing_quote) { - if (pscan[i] == '\0') - return NULL; - if (pscan[i] == closing_quote) { - value_length = i; - break; - } - } else - if (pscan[i] == ',' || pscan[i] == ';' - || pscan[i] == '\0') { - value_length = i; - break; - } - } - if (value_length < 0) { - if (closing_quote) - return NULL; - value_length = nscan; - } - orig_value_length = value_length; - if (closing_quote == 0) - value_length = string_length_no_trail(pscan, orig_value_length); - value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); - if (value == NULL) - return NULL; - memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; - - pscan += orig_value_length; - nscan -= orig_value_length; - - /* skip past separator or closing quote */ - if (nscan > 0) { - if (*pscan != '\0') { - pscan++; - nscan--; - } - } - - if (closing_quote && (nscan > 0)) { - /* we still need to skip around the real separator if present */ - /* first, skip whitespace */ - while (isspace(*pscan)) { - pscan++; - nscan--; - if (nscan == 0) - break; - } - if (nscan > 0) { - if (*pscan == ',' || *pscan == ';') { - pscan++; - nscan--; - } else if (*pscan != '\0') { - kfree(value); - value = NULL; - return NULL; - } - } - } - ctx->curr = pscan; - ctx->bytes_remaining = nscan; - return value; -} - -void * -parser_string_get(struct parser_context *ctx) -{ - u8 *pscan; - unsigned long nscan; - int value_length = -1; - void *value = NULL; - int i; - - if (!ctx) - return NULL; - pscan = ctx->curr; - nscan = ctx->bytes_remaining; - if (nscan == 0) - return NULL; - if (!pscan) - return NULL; - for (i = 0, value_length = -1; i < nscan; i++) - if (pscan[i] == '\0') { - value_length = i; - break; - } - if (value_length < 0) /* '\0' was not included in the length */ - value_length = nscan; - value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); - if (value == NULL) - return NULL; - if (value_length > 0) - memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; - return value; -} - - -static ssize_t toolaction_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - u8 tool_action; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); - return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); -} - -static ssize_t toolaction_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u8 tool_action; - int ret; - - if (kstrtou8(buf, 10, &tool_action)) - return -EINVAL; - - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), - &tool_action, sizeof(u8)); - - if (ret) - return ret; - return count; -} - -static ssize_t boottotool_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct efi_spar_indication efi_spar_indication; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &efi_spar_indication, - sizeof(struct efi_spar_indication)); - return scnprintf(buf, PAGE_SIZE, "%u\n", - efi_spar_indication.boot_to_tool); -} - -static ssize_t boottotool_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int val, ret; - struct efi_spar_indication efi_spar_indication; - - if (kstrtoint(buf, 10, &val)) - return -EINVAL; - - efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &(efi_spar_indication), - sizeof(struct efi_spar_indication)); - - if (ret) - return ret; - return count; -} - -static ssize_t error_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 error; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", error); -} - -static ssize_t error_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 error; - int ret; - - if (kstrtou32(buf, 10, &error)) - return -EINVAL; - - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); - if (ret) - return ret; - return count; -} - -static ssize_t textid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - u32 text_id; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); -} - -static ssize_t textid_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 text_id; - int ret; - - if (kstrtou32(buf, 10, &text_id)) - return -EINVAL; - - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); - if (ret) - return ret; - return count; -} - -static ssize_t remaining_steps_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u16 remaining_steps; - - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps); -} - -static ssize_t remaining_steps_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u16 remaining_steps; - int ret; - - if (kstrtou16(buf, 10, &remaining_steps)) - return -EINVAL; - - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); - if (ret) - return ret; - return count; -} - -static void -bus_info_clear(void *v) -{ - struct visorchipset_bus_info *p = (struct visorchipset_bus_info *) v; - - kfree(p->name); - kfree(p->description); - memset(p, 0, sizeof(struct visorchipset_bus_info)); -} - -static void -dev_info_clear(void *v) -{ - struct visorchipset_device_info *p = - (struct visorchipset_device_info *) v; - - memset(p, 0, sizeof(struct visorchipset_device_info)); -} - -static struct visorchipset_bus_info * -bus_find(struct list_head *list, u32 bus_no) -{ - struct visorchipset_bus_info *p; - - list_for_each_entry(p, list, entry) { - if (p->bus_no == bus_no) - return p; - } - - return NULL; -} - -static struct visorchipset_device_info * -device_find(struct list_head *list, u32 bus_no, u32 dev_no) -{ - struct visorchipset_device_info *p; - - list_for_each_entry(p, list, entry) { - if (p->bus_no == bus_no && p->dev_no == dev_no) - return p; - } - - return NULL; -} - -static void busdevices_del(struct list_head *list, u32 bus_no) -{ - struct visorchipset_device_info *p, *tmp; - - list_for_each_entry_safe(p, tmp, list, entry) { - if (p->bus_no == bus_no) { - list_del(&p->entry); - kfree(p); - } - } -} - -static u8 -check_chipset_events(void) -{ - int i; - u8 send_msg = 1; - /* Check events to determine if response should be sent */ - for (i = 0; i < MAX_CHIPSET_EVENTS; i++) - send_msg &= chipset_events[i]; - return send_msg; -} - -static void -clear_chipset_events(void) -{ - int i; - /* Clear chipset_events */ - for (i = 0; i < MAX_CHIPSET_EVENTS; i++) - chipset_events[i] = 0; -} - -void -visorchipset_register_busdev_server( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info) -{ - down(¬ifier_lock); - if (!notifiers) { - memset(&busdev_server_notifiers, 0, - sizeof(busdev_server_notifiers)); - serverregistered = 0; /* clear flag */ - } else { - busdev_server_notifiers = *notifiers; - serverregistered = 1; /* set flag */ - } - if (responders) - *responders = busdev_responders; - if (driver_info) - bus_device_info_init(driver_info, "chipset", "visorchipset", - VERSION, NULL); - - up(¬ifier_lock); -} -EXPORT_SYMBOL_GPL(visorchipset_register_busdev_server); - -void -visorchipset_register_busdev_client( - struct visorchipset_busdev_notifiers *notifiers, - struct visorchipset_busdev_responders *responders, - struct ultra_vbus_deviceinfo *driver_info) -{ - down(¬ifier_lock); - if (!notifiers) { - memset(&busdev_client_notifiers, 0, - sizeof(busdev_client_notifiers)); - clientregistered = 0; /* clear flag */ - } else { - busdev_client_notifiers = *notifiers; - clientregistered = 1; /* set flag */ - } - if (responders) - *responders = busdev_responders; - if (driver_info) - bus_device_info_init(driver_info, "chipset(bolts)", - "visorchipset", VERSION, NULL); - up(¬ifier_lock); -} -EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client); - -static void -cleanup_controlvm_structures(void) -{ - struct visorchipset_bus_info *bi, *tmp_bi; - struct visorchipset_device_info *di, *tmp_di; - - list_for_each_entry_safe(bi, tmp_bi, &bus_info_list, entry) { - bus_info_clear(bi); - list_del(&bi->entry); - kfree(bi); - } - - list_for_each_entry_safe(di, tmp_di, &dev_info_list, entry) { - dev_info_clear(di); - list_del(&di->entry); - kfree(di); - } -} - -static void -chipset_init(struct controlvm_message *inmsg) -{ - static int chipset_inited; - enum ultra_chipset_feature features = 0; - int rc = CONTROLVM_RESP_SUCCESS; - - POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); - if (chipset_inited) { - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; - } - chipset_inited = 1; - POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); - - /* Set features to indicate we support parahotplug (if Command - * also supports it). */ - features = - inmsg->cmd.init_chipset. - features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; - - /* Set the "reply" bit so Command knows this is a - * features-aware driver. */ - features |= ULTRA_CHIPSET_FEATURE_REPLY; - -cleanup: - if (rc < 0) - cleanup_controlvm_structures(); - if (inmsg->hdr.flags.response_expected) - controlvm_respond_chipset_init(&inmsg->hdr, rc, features); -} - -static void -controlvm_init_response(struct controlvm_message *msg, - struct controlvm_message_header *msg_hdr, int response) -{ - memset(msg, 0, sizeof(struct controlvm_message)); - memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header)); - msg->hdr.payload_bytes = 0; - msg->hdr.payload_vm_offset = 0; - msg->hdr.payload_max_bytes = 0; - if (response < 0) { - msg->hdr.flags.failed = 1; - msg->hdr.completion_status = (u32) (-response); - } -} - -static void -controlvm_respond(struct controlvm_message_header *msg_hdr, int response) -{ - struct controlvm_message outmsg; - - controlvm_init_response(&outmsg, msg_hdr, response); - /* For DiagPool channel DEVICE_CHANGESTATE, we need to send - * back the deviceChangeState structure in the packet. */ - if (msg_hdr->id == CONTROLVM_DEVICE_CHANGESTATE && - g_devicechangestate_packet.device_change_state.bus_no == - g_diagpool_bus_no && - g_devicechangestate_packet.device_change_state.dev_no == - g_diagpool_dev_no) - outmsg.cmd = g_devicechangestate_packet; - if (outmsg.hdr.flags.test_message == 1) - return; - - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { - return; - } -} - -static void -controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, - int response, - enum ultra_chipset_feature features) -{ - struct controlvm_message outmsg; - - controlvm_init_response(&outmsg, msg_hdr, response); - outmsg.cmd.init_chipset.features = features; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { - return; - } -} - -static void controlvm_respond_physdev_changestate( - struct controlvm_message_header *msg_hdr, int response, - struct spar_segment_state state) -{ - struct controlvm_message outmsg; - - controlvm_init_response(&outmsg, msg_hdr, response); - outmsg.cmd.device_change_state.state = state; - outmsg.cmd.device_change_state.flags.phys_device = 1; - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) { - return; - } -} - -void -visorchipset_save_message(struct controlvm_message *msg, - enum crash_obj_type type) -{ - u32 crash_msg_offset; - u16 crash_msg_count; - - /* get saved message count */ - if (visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - saved_crash_message_count), - &crash_msg_count, sizeof(u16)) < 0) { - POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - - if (crash_msg_count != CONTROLVM_CRASHMSG_MAX) { - POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC, - crash_msg_count, - POSTCODE_SEVERITY_ERR); - return; - } - - /* get saved crash message offset */ - if (visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - saved_crash_message_offset), - &crash_msg_offset, sizeof(u32)) < 0) { - POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - - if (type == CRASH_BUS) { - if (visorchannel_write(controlvm_channel, - crash_msg_offset, - msg, - sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - } else { - if (visorchannel_write(controlvm_channel, - crash_msg_offset + - sizeof(struct controlvm_message), msg, - sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - } -} -EXPORT_SYMBOL_GPL(visorchipset_save_message); - -static void -bus_responder(enum controlvm_id cmd_id, u32 bus_no, int response) -{ - struct visorchipset_bus_info *p; - bool need_clear = false; - - p = bus_find(&bus_info_list, bus_no); - if (!p) - return; - - if (response < 0) { - if ((cmd_id == CONTROLVM_BUS_CREATE) && - (response != (-CONTROLVM_RESP_ERROR_ALREADY_DONE))) - /* undo the row we just created... */ - busdevices_del(&dev_info_list, bus_no); - } else { - if (cmd_id == CONTROLVM_BUS_CREATE) - p->state.created = 1; - if (cmd_id == CONTROLVM_BUS_DESTROY) - need_clear = true; - } - - if (p->pending_msg_hdr.id == CONTROLVM_INVALID) - return; /* no controlvm response needed */ - if (p->pending_msg_hdr.id != (u32)cmd_id) - return; - controlvm_respond(&p->pending_msg_hdr, response); - p->pending_msg_hdr.id = CONTROLVM_INVALID; - if (need_clear) { - bus_info_clear(p); - busdevices_del(&dev_info_list, bus_no); - } -} - -static void -device_changestate_responder(enum controlvm_id cmd_id, - u32 bus_no, u32 dev_no, int response, - struct spar_segment_state response_state) -{ - struct visorchipset_device_info *p; - struct controlvm_message outmsg; - - p = device_find(&dev_info_list, bus_no, dev_no); - if (!p) - return; - if (p->pending_msg_hdr.id == CONTROLVM_INVALID) - return; /* no controlvm response needed */ - if (p->pending_msg_hdr.id != cmd_id) - return; - - controlvm_init_response(&outmsg, &p->pending_msg_hdr, response); - - outmsg.cmd.device_change_state.bus_no = bus_no; - outmsg.cmd.device_change_state.dev_no = dev_no; - outmsg.cmd.device_change_state.state = response_state; - - if (!visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg)) - return; - - p->pending_msg_hdr.id = CONTROLVM_INVALID; -} - -static void -device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response) -{ - struct visorchipset_device_info *p; - bool need_clear = false; - - p = device_find(&dev_info_list, bus_no, dev_no); - if (!p) - return; - if (response >= 0) { - if (cmd_id == CONTROLVM_DEVICE_CREATE) - p->state.created = 1; - if (cmd_id == CONTROLVM_DEVICE_DESTROY) - need_clear = true; - } - - if (p->pending_msg_hdr.id == CONTROLVM_INVALID) - return; /* no controlvm response needed */ - - if (p->pending_msg_hdr.id != (u32)cmd_id) - return; - - controlvm_respond(&p->pending_msg_hdr, response); - p->pending_msg_hdr.id = CONTROLVM_INVALID; - if (need_clear) - dev_info_clear(p); -} - -static void -bus_epilog(u32 bus_no, - u32 cmd, struct controlvm_message_header *msg_hdr, - int response, bool need_response) -{ - struct visorchipset_bus_info *bus_info; - bool notified = false; - - bus_info = bus_find(&bus_info_list, bus_no); - - if (!bus_info) - return; - - if (need_response) { - memcpy(&bus_info->pending_msg_hdr, msg_hdr, - sizeof(struct controlvm_message_header)); - } else { - bus_info->pending_msg_hdr.id = CONTROLVM_INVALID; - } - - down(¬ifier_lock); - if (response == CONTROLVM_RESP_SUCCESS) { - switch (cmd) { - case CONTROLVM_BUS_CREATE: - /* We can't tell from the bus_create - * information which of our 2 bus flavors the - * devices on this bus will ultimately end up. - * FORTUNATELY, it turns out it is harmless to - * send the bus_create to both of them. We can - * narrow things down a little bit, though, - * because we know: - BusDev_Server can handle - * either server or client devices - * - BusDev_Client can handle ONLY client - * devices */ - if (busdev_server_notifiers.bus_create) { - (*busdev_server_notifiers.bus_create) (bus_no); - notified = true; - } - if ((!bus_info->flags.server) /*client */ && - busdev_client_notifiers.bus_create) { - (*busdev_client_notifiers.bus_create) (bus_no); - notified = true; - } - break; - case CONTROLVM_BUS_DESTROY: - if (busdev_server_notifiers.bus_destroy) { - (*busdev_server_notifiers.bus_destroy) (bus_no); - notified = true; - } - if ((!bus_info->flags.server) /*client */ && - busdev_client_notifiers.bus_destroy) { - (*busdev_client_notifiers.bus_destroy) (bus_no); - notified = true; - } - break; - } - } - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call bus_responder() - */ - ; - else - bus_responder(cmd, bus_no, response); - up(¬ifier_lock); -} - -static void -device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd, - struct controlvm_message_header *msg_hdr, int response, - bool need_response, bool for_visorbus) -{ - struct visorchipset_busdev_notifiers *notifiers; - bool notified = false; - - struct visorchipset_device_info *dev_info = - device_find(&dev_info_list, bus_no, dev_no); - char *envp[] = { - "SPARSP_DIAGPOOL_PAUSED_STATE = 1", - NULL - }; - - if (!dev_info) - return; - - if (for_visorbus) - notifiers = &busdev_server_notifiers; - else - notifiers = &busdev_client_notifiers; - if (need_response) { - memcpy(&dev_info->pending_msg_hdr, msg_hdr, - sizeof(struct controlvm_message_header)); - } else { - dev_info->pending_msg_hdr.id = CONTROLVM_INVALID; - } - - down(¬ifier_lock); - if (response >= 0) { - switch (cmd) { - case CONTROLVM_DEVICE_CREATE: - if (notifiers->device_create) { - (*notifiers->device_create) (bus_no, dev_no); - notified = true; - } - break; - case CONTROLVM_DEVICE_CHANGESTATE: - /* ServerReady / ServerRunning / SegmentStateRunning */ - if (state.alive == segment_state_running.alive && - state.operating == - segment_state_running.operating) { - if (notifiers->device_resume) { - (*notifiers->device_resume) (bus_no, - dev_no); - notified = true; - } - } - /* ServerNotReady / ServerLost / SegmentStateStandby */ - else if (state.alive == segment_state_standby.alive && - state.operating == - segment_state_standby.operating) { - /* technically this is standby case - * where server is lost - */ - if (notifiers->device_pause) { - (*notifiers->device_pause) (bus_no, - dev_no); - notified = true; - } - } else if (state.alive == segment_state_paused.alive && - state.operating == - segment_state_paused.operating) { - /* this is lite pause where channel is - * still valid just 'pause' of it - */ - if (bus_no == g_diagpool_bus_no && - dev_no == g_diagpool_dev_no) { - /* this will trigger the - * diag_shutdown.sh script in - * the visorchipset hotplug */ - kobject_uevent_env - (&visorchipset_platform_device.dev. - kobj, KOBJ_ONLINE, envp); - } - } - break; - case CONTROLVM_DEVICE_DESTROY: - if (notifiers->device_destroy) { - (*notifiers->device_destroy) (bus_no, dev_no); - notified = true; - } - break; - } - } - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call device_responder() - */ - ; - else - device_responder(cmd, bus_no, dev_no, response); - up(¬ifier_lock); -} - -static void -bus_create(struct controlvm_message *inmsg) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->create_bus.bus_no; - int rc = CONTROLVM_RESP_SUCCESS; - struct visorchipset_bus_info *bus_info; - - bus_info = bus_find(&bus_info_list, bus_no); - if (bus_info && (bus_info->state.created == 1)) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; - } - bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); - if (!bus_info) { - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; - } - - INIT_LIST_HEAD(&bus_info->entry); - bus_info->bus_no = bus_no; - - POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO); - - if (inmsg->hdr.flags.test_message == 1) - bus_info->chan_info.addr_type = ADDRTYPE_LOCALTEST; - else - bus_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL; - - bus_info->flags.server = inmsg->hdr.flags.server; - bus_info->chan_info.channel_addr = cmd->create_bus.channel_addr; - bus_info->chan_info.n_channel_bytes = cmd->create_bus.channel_bytes; - bus_info->chan_info.channel_type_uuid = - cmd->create_bus.bus_data_type_uuid; - bus_info->chan_info.channel_inst_uuid = cmd->create_bus.bus_inst_uuid; - - list_add(&bus_info->entry, &bus_info_list); - - POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); - -cleanup: - bus_epilog(bus_no, CONTROLVM_BUS_CREATE, &inmsg->hdr, - rc, inmsg->hdr.flags.response_expected == 1); -} - -static void -bus_destroy(struct controlvm_message *inmsg) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->destroy_bus.bus_no; - struct visorchipset_bus_info *bus_info; - int rc = CONTROLVM_RESP_SUCCESS; - - bus_info = bus_find(&bus_info_list, bus_no); - if (!bus_info) - rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - else if (bus_info->state.created == 0) - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - - bus_epilog(bus_no, CONTROLVM_BUS_DESTROY, &inmsg->hdr, - rc, inmsg->hdr.flags.response_expected == 1); -} - -static void -bus_configure(struct controlvm_message *inmsg, - struct parser_context *parser_ctx) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no; - struct visorchipset_bus_info *bus_info; - int rc = CONTROLVM_RESP_SUCCESS; - char s[99]; - - bus_no = cmd->configure_bus.bus_no; - POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no, - POSTCODE_SEVERITY_INFO); - - bus_info = bus_find(&bus_info_list, bus_no); - if (!bus_info) { - POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - } else if (bus_info->state.created == 0) { - POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - } else if (bus_info->pending_msg_hdr.id != CONTROLVM_INVALID) { - POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; - } else { - bus_info->partition_handle = cmd->configure_bus.guest_handle; - bus_info->partition_uuid = parser_id_get(parser_ctx); - parser_param_start(parser_ctx, PARSERSTRING_NAME); - bus_info->name = parser_string_get(parser_ctx); - - visorchannel_uuid_id(&bus_info->partition_uuid, s); - POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no, - POSTCODE_SEVERITY_INFO); - } - bus_epilog(bus_no, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr, - rc, inmsg->hdr.flags.response_expected == 1); -} - -static void -my_device_create(struct controlvm_message *inmsg) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->create_device.bus_no; - u32 dev_no = cmd->create_device.dev_no; - struct visorchipset_device_info *dev_info; - struct visorchipset_bus_info *bus_info; - int rc = CONTROLVM_RESP_SUCCESS; - - dev_info = device_find(&dev_info_list, bus_no, dev_no); - if (dev_info && (dev_info->state.created == 1)) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; - } - bus_info = bus_find(&bus_info_list, bus_no); - if (!bus_info) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; - } - if (bus_info->state.created == 0) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; - } - dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); - if (!dev_info) { - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; - } - - INIT_LIST_HEAD(&dev_info->entry); - dev_info->bus_no = bus_no; - dev_info->dev_no = dev_no; - dev_info->dev_inst_uuid = cmd->create_device.dev_inst_uuid; - POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); - - if (inmsg->hdr.flags.test_message == 1) - dev_info->chan_info.addr_type = ADDRTYPE_LOCALTEST; - else - dev_info->chan_info.addr_type = ADDRTYPE_LOCALPHYSICAL; - dev_info->chan_info.channel_addr = cmd->create_device.channel_addr; - dev_info->chan_info.n_channel_bytes = cmd->create_device.channel_bytes; - dev_info->chan_info.channel_type_uuid = - cmd->create_device.data_type_uuid; - dev_info->chan_info.intr = cmd->create_device.intr; - list_add(&dev_info->entry, &dev_info_list); - POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, - POSTCODE_SEVERITY_INFO); -cleanup: - /* get the bus and devNo for DiagPool channel */ - if (dev_info && - is_diagpool_channel(dev_info->chan_info.channel_type_uuid)) { - g_diagpool_bus_no = bus_no; - g_diagpool_dev_no = dev_no; - } - device_epilog(bus_no, dev_no, segment_state_running, - CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc, - inmsg->hdr.flags.response_expected == 1, - FOR_VISORBUS(dev_info->chan_info.channel_type_uuid)); -} - -static void -my_device_changestate(struct controlvm_message *inmsg) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->device_change_state.bus_no; - u32 dev_no = cmd->device_change_state.dev_no; - struct spar_segment_state state = cmd->device_change_state.state; - struct visorchipset_device_info *dev_info; - int rc = CONTROLVM_RESP_SUCCESS; - - dev_info = device_find(&dev_info_list, bus_no, dev_no); - if (!dev_info) { - POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; - } else if (dev_info->state.created == 0) { - POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, - POSTCODE_SEVERITY_ERR); - rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; - } - if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info) - device_epilog(bus_no, dev_no, state, - CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc, - inmsg->hdr.flags.response_expected == 1, - FOR_VISORBUS( - dev_info->chan_info.channel_type_uuid)); -} - -static void -my_device_destroy(struct controlvm_message *inmsg) -{ - struct controlvm_message_packet *cmd = &inmsg->cmd; - u32 bus_no = cmd->destroy_device.bus_no; - u32 dev_no = cmd->destroy_device.dev_no; - struct visorchipset_device_info *dev_info; - int rc = CONTROLVM_RESP_SUCCESS; - - dev_info = device_find(&dev_info_list, bus_no, dev_no); - if (!dev_info) - rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID; - else if (dev_info->state.created == 0) - rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - - if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info) - device_epilog(bus_no, dev_no, segment_state_running, - CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc, - inmsg->hdr.flags.response_expected == 1, - FOR_VISORBUS( - dev_info->chan_info.channel_type_uuid)); -} - -/* When provided with the physical address of the controlvm channel - * (phys_addr), the offset to the payload area we need to manage - * (offset), and the size of this payload area (bytes), fills in the - * controlvm_payload_info struct. Returns true for success or false - * for failure. - */ -static int -initialize_controlvm_payload_info(HOSTADDRESS phys_addr, u64 offset, u32 bytes, - struct visor_controlvm_payload_info *info) -{ - u8 __iomem *payload = NULL; - int rc = CONTROLVM_RESP_SUCCESS; - - if (!info) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } - memset(info, 0, sizeof(struct visor_controlvm_payload_info)); - if ((offset == 0) || (bytes == 0)) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } - payload = ioremap_cache(phys_addr + offset, bytes); - if (!payload) { - rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - goto cleanup; - } - - info->offset = offset; - info->bytes = bytes; - info->ptr = payload; - -cleanup: - if (rc < 0) { - if (payload) { - iounmap(payload); - payload = NULL; - } - } - return rc; -} - -static void -destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info) -{ - if (info->ptr) { - iounmap(info->ptr); - info->ptr = NULL; - } - memset(info, 0, sizeof(struct visor_controlvm_payload_info)); -} - -static void -initialize_controlvm_payload(void) -{ - HOSTADDRESS phys_addr = visorchannel_get_physaddr(controlvm_channel); - u64 payload_offset = 0; - u32 payload_bytes = 0; - - if (visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - request_payload_offset), - &payload_offset, sizeof(payload_offset)) < 0) { - POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - if (visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - request_payload_bytes), - &payload_bytes, sizeof(payload_bytes)) < 0) { - POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - initialize_controlvm_payload_info(phys_addr, - payload_offset, payload_bytes, - &controlvm_payload_info); -} - -/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. - */ -int -visorchipset_chipset_ready(void) -{ - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE); - return CONTROLVM_RESP_SUCCESS; -} -EXPORT_SYMBOL_GPL(visorchipset_chipset_ready); - -int -visorchipset_chipset_selftest(void) -{ - char env_selftest[20]; - char *envp[] = { env_selftest, NULL }; - - sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); - return CONTROLVM_RESP_SUCCESS; -} -EXPORT_SYMBOL_GPL(visorchipset_chipset_selftest); - -/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset. - * Returns CONTROLVM_RESP_xxx code. - */ -int -visorchipset_chipset_notready(void) -{ - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE); - return CONTROLVM_RESP_SUCCESS; -} -EXPORT_SYMBOL_GPL(visorchipset_chipset_notready); - -static void -chipset_ready(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_ready(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready) - controlvm_respond(msg_hdr, rc); - if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) { - /* Send CHIPSET_READY response when all modules have been loaded - * and disks mounted for the partition - */ - g_chipset_msg_hdr = *msg_hdr; - } -} - -static void -chipset_selftest(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_selftest(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected) - controlvm_respond(msg_hdr, rc); -} - -static void -chipset_notready(struct controlvm_message_header *msg_hdr) -{ - int rc = visorchipset_chipset_notready(); - - if (rc != CONTROLVM_RESP_SUCCESS) - rc = -rc; - if (msg_hdr->flags.response_expected) - controlvm_respond(msg_hdr, rc); -} - -/* This is your "one-stop" shop for grabbing the next message from the - * CONTROLVM_QUEUE_EVENT queue in the controlvm channel. - */ -static bool -read_controlvm_event(struct controlvm_message *msg) -{ - if (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg)) { - /* got a message */ - if (msg->hdr.flags.test_message == 1) - return false; - return true; - } - return false; -} - -/* - * The general parahotplug flow works as follows. The visorchipset - * driver receives a DEVICE_CHANGESTATE message from Command - * specifying a physical device to enable or disable. The CONTROLVM - * message handler calls parahotplug_process_message, which then adds - * the message to a global list and kicks off a udev event which - * causes a user level script to enable or disable the specified - * device. The udev script then writes to - * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write - * to get called, at which point the appropriate CONTROLVM message is - * retrieved from the list and responded to. - */ - -#define PARAHOTPLUG_TIMEOUT_MS 2000 - -/* - * Generate unique int to match an outstanding CONTROLVM message with a - * udev script /proc response - */ -static int -parahotplug_next_id(void) -{ - static atomic_t id = ATOMIC_INIT(0); - - return atomic_inc_return(&id); -} - -/* - * Returns the time (in jiffies) when a CONTROLVM message on the list - * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future - */ -static unsigned long -parahotplug_next_expiration(void) -{ - return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); -} - -/* - * Create a parahotplug_request, which is basically a wrapper for a - * CONTROLVM_MESSAGE that we can stick on a list - */ -static struct parahotplug_request * -parahotplug_request_create(struct controlvm_message *msg) -{ - struct parahotplug_request *req; - - req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY); - if (!req) - return NULL; - - req->id = parahotplug_next_id(); - req->expiration = parahotplug_next_expiration(); - req->msg = *msg; - - return req; -} - -/* - * Free a parahotplug_request. - */ -static void -parahotplug_request_destroy(struct parahotplug_request *req) -{ - kfree(req); -} - -/* - * Cause uevent to run the user level script to do the disable/enable - * specified in (the CONTROLVM message in) the specified - * parahotplug_request - */ -static void -parahotplug_request_kickoff(struct parahotplug_request *req) -{ - struct controlvm_message_packet *cmd = &req->msg.cmd; - char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], - env_func[40]; - char *envp[] = { - env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL - }; - - sprintf(env_cmd, "SPAR_PARAHOTPLUG=1"); - sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id); - sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d", - cmd->device_change_state.state.active); - sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d", - cmd->device_change_state.bus_no); - sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d", - cmd->device_change_state.dev_no >> 3); - sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", - cmd->device_change_state.dev_no & 0x7); - - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); -} - -/* - * Remove any request from the list that's been on there too long and - * respond with an error. - */ -static void -parahotplug_process_list(void) -{ - struct list_head *pos; - struct list_head *tmp; - - spin_lock(¶hotplug_request_list_lock); - - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); - - if (!time_after_eq(jiffies, req->expiration)) - continue; - - list_del(pos); - if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, - CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT, - req->msg.cmd.device_change_state.state); - parahotplug_request_destroy(req); - } - - spin_unlock(¶hotplug_request_list_lock); -} - -/* - * Called from the /proc handler, which means the user script has - * finished the enable/disable. Find the matching identifier, and - * respond to the CONTROLVM message with success. - */ -static int -parahotplug_request_complete(int id, u16 active) -{ - struct list_head *pos; - struct list_head *tmp; - - spin_lock(¶hotplug_request_list_lock); - - /* Look for a request matching "id". */ - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); - if (req->id == id) { - /* Found a match. Remove it from the list and - * respond. - */ - list_del(pos); - spin_unlock(¶hotplug_request_list_lock); - req->msg.cmd.device_change_state.state.active = active; - if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, CONTROLVM_RESP_SUCCESS, - req->msg.cmd.device_change_state.state); - parahotplug_request_destroy(req); - return 0; - } - } - - spin_unlock(¶hotplug_request_list_lock); - return -1; -} - -/* - * Enables or disables a PCI device by kicking off a udev script - */ -static void -parahotplug_process_message(struct controlvm_message *inmsg) -{ - struct parahotplug_request *req; - - req = parahotplug_request_create(inmsg); - - if (!req) - return; - - if (inmsg->cmd.device_change_state.state.active) { - /* For enable messages, just respond with success - * right away. This is a bit of a hack, but there are - * issues with the early enable messages we get (with - * either the udev script not detecting that the device - * is up, or not getting called at all). Fortunately - * the messages that get lost don't matter anyway, as - * devices are automatically enabled at - * initialization. - */ - parahotplug_request_kickoff(req); - controlvm_respond_physdev_changestate(&inmsg->hdr, - CONTROLVM_RESP_SUCCESS, - inmsg->cmd.device_change_state.state); - parahotplug_request_destroy(req); - } else { - /* For disable messages, add the request to the - * request list before kicking off the udev script. It - * won't get responded to until the script has - * indicated it's done. - */ - spin_lock(¶hotplug_request_list_lock); - list_add_tail(&req->list, ¶hotplug_request_list); - spin_unlock(¶hotplug_request_list_lock); - - parahotplug_request_kickoff(req); - } -} - -/* Process a controlvm message. - * Return result: - * false - this function will return FALSE only in the case where the - * controlvm message was NOT processed, but processing must be - * retried before reading the next controlvm message; a - * scenario where this can occur is when we need to throttle - * the allocation of memory in which to copy out controlvm - * payload data - * true - processing of the controlvm message completed, - * either successfully or with an error. - */ -static bool -handle_command(struct controlvm_message inmsg, HOSTADDRESS channel_addr) -{ - struct controlvm_message_packet *cmd = &inmsg.cmd; - u64 parm_addr; - u32 parm_bytes; - struct parser_context *parser_ctx = NULL; - bool local_addr; - struct controlvm_message ackmsg; - - /* create parsing context if necessary */ - local_addr = (inmsg.hdr.flags.test_message == 1); - if (channel_addr == 0) - return true; - parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; - parm_bytes = inmsg.hdr.payload_bytes; - - /* Parameter and channel addresses within test messages actually lie - * within our OS-controlled memory. We need to know that, because it - * makes a difference in how we compute the virtual address. - */ - if (parm_addr && parm_bytes) { - bool retry = false; - - parser_ctx = - parser_init_byte_stream(parm_addr, parm_bytes, - local_addr, &retry); - if (!parser_ctx && retry) - return false; - } - - if (!local_addr) { - controlvm_init_response(&ackmsg, &inmsg.hdr, - CONTROLVM_RESP_SUCCESS); - if (controlvm_channel) - visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_ACK, - &ackmsg); - } - switch (inmsg.hdr.id) { - case CONTROLVM_CHIPSET_INIT: - chipset_init(&inmsg); - break; - case CONTROLVM_BUS_CREATE: - bus_create(&inmsg); - break; - case CONTROLVM_BUS_DESTROY: - bus_destroy(&inmsg); - break; - case CONTROLVM_BUS_CONFIGURE: - bus_configure(&inmsg, parser_ctx); - break; - case CONTROLVM_DEVICE_CREATE: - my_device_create(&inmsg); - break; - case CONTROLVM_DEVICE_CHANGESTATE: - if (cmd->device_change_state.flags.phys_device) { - parahotplug_process_message(&inmsg); - } else { - /* save the hdr and cmd structures for later use */ - /* when sending back the response to Command */ - my_device_changestate(&inmsg); - g_devicechangestate_packet = inmsg.cmd; - break; - } - break; - case CONTROLVM_DEVICE_DESTROY: - my_device_destroy(&inmsg); - break; - case CONTROLVM_DEVICE_CONFIGURE: - /* no op for now, just send a respond that we passed */ - if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); - break; - case CONTROLVM_CHIPSET_READY: - chipset_ready(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_SELFTEST: - chipset_selftest(&inmsg.hdr); - break; - case CONTROLVM_CHIPSET_STOP: - chipset_notready(&inmsg.hdr); - break; - default: - if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, - -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); - break; - } - - if (parser_ctx) { - parser_done(parser_ctx); - parser_ctx = NULL; - } - return true; -} - -static HOSTADDRESS controlvm_get_channel_address(void) -{ - u64 addr = 0; - u32 size = 0; - - if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size))) - return 0; - - return addr; -} - -static void -controlvm_periodic_work(struct work_struct *work) -{ - struct controlvm_message inmsg; - bool got_command = false; - bool handle_command_failed = false; - static u64 poll_count; - - /* make sure visorbus server is registered for controlvm callbacks */ - if (visorchipset_serverregwait && !serverregistered) - goto cleanup; - /* make sure visorclientbus server is regsitered for controlvm - * callbacks - */ - if (visorchipset_clientregwait && !clientregistered) - goto cleanup; - - poll_count++; - if (poll_count >= 250) - ; /* keep going */ - else - goto cleanup; - - /* Check events to determine if response to CHIPSET_READY - * should be sent - */ - if (visorchipset_holdchipsetready && - (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) { - if (check_chipset_events() == 1) { - controlvm_respond(&g_chipset_msg_hdr, 0); - clear_chipset_events(); - memset(&g_chipset_msg_hdr, 0, - sizeof(struct controlvm_message_header)); - } - } - - while (visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_RESPONSE, - &inmsg)) - ; - if (!got_command) { - if (controlvm_pending_msg_valid) { - /* we throttled processing of a prior - * msg, so try to process it again - * rather than reading a new one - */ - inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = false; - got_command = true; - } else { - got_command = read_controlvm_event(&inmsg); - } - } - - handle_command_failed = false; - while (got_command && (!handle_command_failed)) { - most_recent_message_jiffies = jiffies; - if (handle_command(inmsg, - visorchannel_get_physaddr - (controlvm_channel))) - got_command = read_controlvm_event(&inmsg); - else { - /* this is a scenario where throttling - * is required, but probably NOT an - * error...; we stash the current - * controlvm msg so we will attempt to - * reprocess it on our next loop - */ - handle_command_failed = true; - controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = true; - } - } - - /* parahotplug_worker */ - parahotplug_process_list(); - -cleanup: - - if (time_after(jiffies, - most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { - /* it's been longer than MIN_IDLE_SECONDS since we - * processed our last controlvm message; slow down the - * polling - */ - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - } else { - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - } - - queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); -} - -static void -setup_crash_devices_work_queue(struct work_struct *work) -{ - struct controlvm_message local_crash_bus_msg; - struct controlvm_message local_crash_dev_msg; - struct controlvm_message msg; - u32 local_crash_msg_offset; - u16 local_crash_msg_count; - - /* make sure visorbus server is registered for controlvm callbacks */ - if (visorchipset_serverregwait && !serverregistered) - goto cleanup; - - /* make sure visorclientbus server is regsitered for controlvm - * callbacks - */ - if (visorchipset_clientregwait && !clientregistered) - goto cleanup; - - POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); - - /* send init chipset msg */ - msg.hdr.id = CONTROLVM_CHIPSET_INIT; - msg.cmd.init_chipset.bus_count = 23; - msg.cmd.init_chipset.switch_count = 0; - - chipset_init(&msg); - - /* get saved message 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; - } - - /* get saved crash message offset */ - 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; - } - - /* read create device message for storage bus offset */ - if (visorchannel_read(controlvm_channel, - local_crash_msg_offset, - &local_crash_bus_msg, - sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - - /* read create device message for storage device */ - if (visorchannel_read(controlvm_channel, - local_crash_msg_offset + - sizeof(struct controlvm_message), - &local_crash_dev_msg, - sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - - /* reuse IOVM create bus message */ - if (local_crash_bus_msg.cmd.create_bus.channel_addr) { - bus_create(&local_crash_bus_msg); - } else { - POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - - /* reuse create device message for storage device */ - if (local_crash_dev_msg.cmd.create_device.channel_addr) { - my_device_create(&local_crash_dev_msg); - } else { - POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC, - POSTCODE_SEVERITY_ERR); - return; - } - POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); - return; - -cleanup: - - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - - queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); -} - -static void -bus_create_response(u32 bus_no, int response) -{ - bus_responder(CONTROLVM_BUS_CREATE, bus_no, response); -} - -static void -bus_destroy_response(u32 bus_no, int response) -{ - bus_responder(CONTROLVM_BUS_DESTROY, bus_no, response); -} - -static void -device_create_response(u32 bus_no, u32 dev_no, int response) -{ - device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response); -} - -static void -device_destroy_response(u32 bus_no, u32 dev_no, int response) -{ - device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response); -} - -void -visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response) -{ - device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, - bus_no, dev_no, response, - segment_state_standby); -} -EXPORT_SYMBOL_GPL(visorchipset_device_pause_response); - -static void -device_resume_response(u32 bus_no, u32 dev_no, int response) -{ - device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, - bus_no, dev_no, response, - segment_state_running); -} - -bool -visorchipset_get_bus_info(u32 bus_no, struct visorchipset_bus_info *bus_info) -{ - void *p = bus_find(&bus_info_list, bus_no); - - if (!p) - return false; - memcpy(bus_info, p, sizeof(struct visorchipset_bus_info)); - return true; -} -EXPORT_SYMBOL_GPL(visorchipset_get_bus_info); - -bool -visorchipset_set_bus_context(u32 bus_no, void *context) -{ - struct visorchipset_bus_info *p = bus_find(&bus_info_list, bus_no); - - if (!p) - return false; - p->bus_driver_context = context; - return true; -} -EXPORT_SYMBOL_GPL(visorchipset_set_bus_context); - -bool -visorchipset_get_device_info(u32 bus_no, u32 dev_no, - struct visorchipset_device_info *dev_info) -{ - void *p = device_find(&dev_info_list, bus_no, dev_no); - - if (!p) - return false; - memcpy(dev_info, p, sizeof(struct visorchipset_device_info)); - return true; -} -EXPORT_SYMBOL_GPL(visorchipset_get_device_info); - -bool -visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context) -{ - struct visorchipset_device_info *p; - - p = device_find(&dev_info_list, bus_no, dev_no); - - if (!p) - return false; - p->bus_driver_context = context; - return true; -} -EXPORT_SYMBOL_GPL(visorchipset_set_device_context); - -/* Generic wrapper function for allocating memory from a kmem_cache pool. - */ -void * -visorchipset_cache_alloc(struct kmem_cache *pool, bool ok_to_block, - char *fn, int ln) -{ - gfp_t gfp; - void *p; - - if (ok_to_block) - gfp = GFP_KERNEL; - else - gfp = GFP_ATOMIC; - /* __GFP_NORETRY means "ok to fail", meaning - * kmem_cache_alloc() can return NULL, implying the caller CAN - * cope with failure. If you do NOT specify __GFP_NORETRY, - * Linux will go to extreme measures to get memory for you - * (like, invoke oom killer), which will probably cripple the - * system. - */ - gfp |= __GFP_NORETRY; - p = kmem_cache_alloc(pool, gfp); - if (!p) - return NULL; - - return p; -} - -/* Generic wrapper function for freeing memory from a kmem_cache pool. - */ -void -visorchipset_cache_free(struct kmem_cache *pool, void *p, char *fn, int ln) -{ - if (!p) - return; - - kmem_cache_free(pool, p); -} - -static ssize_t chipsetready_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - char msgtype[64]; - - if (sscanf(buf, "%63s", msgtype) != 1) - return -EINVAL; - - if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) { - chipset_events[0] = 1; - return count; - } else if (!strcmp(msgtype, "MODULES_LOADED")) { - chipset_events[1] = 1; - return count; - } - return -EINVAL; -} - -/* The parahotplug/devicedisabled interface gets called by our support script - * when an SR-IOV device has been shut down. The ID is passed to the script - * and then passed back when the device has been removed. - */ -static ssize_t devicedisabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - parahotplug_request_complete(id, 0); - return count; -} - -/* The parahotplug/deviceenabled interface gets called by our support script - * when an SR-IOV device has been recovered. The ID is passed to the script - * and then passed back when the device has been brought back up. - */ -static ssize_t deviceenabled_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int id; - - if (kstrtouint(buf, 10, &id)) - return -EINVAL; - - parahotplug_request_complete(id, 1); - return count; -} - -static int -visorchipset_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned long physaddr = 0; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - GUEST_PHYSICAL_ADDRESS addr = 0; - - /* sv_enable_dfp(); */ - if (offset & (PAGE_SIZE - 1)) - return -ENXIO; /* need aligned offsets */ - - switch (offset) { - case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: - vma->vm_flags |= VM_IO; - if (!*file_controlvm_channel) - return -ENXIO; - - visorchannel_read(*file_controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - gp_control_channel), - &addr, sizeof(addr)); - if (!addr) - return -ENXIO; - - physaddr = (unsigned long)addr; - if (remap_pfn_range(vma, vma->vm_start, - physaddr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - /*pgprot_noncached */ - (vma->vm_page_prot))) { - return -EAGAIN; - } - break; - default: - return -ENXIO; - } - return 0; -} - -static long visorchipset_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - s64 adjustment; - s64 vrtc_offset; - - switch (cmd) { - case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: - /* get the physical rtc offset */ - vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); - if (copy_to_user((void __user *)arg, &vrtc_offset, - sizeof(vrtc_offset))) { - return -EFAULT; - } - return SUCCESS; - case VMCALL_UPDATE_PHYSICAL_TIME: - if (copy_from_user(&adjustment, (void __user *)arg, - sizeof(adjustment))) { - return -EFAULT; - } - return issue_vmcall_update_physical_time(adjustment); - default: - return -EFAULT; - } -} - -static const struct file_operations visorchipset_fops = { - .owner = THIS_MODULE, - .open = visorchipset_open, - .read = NULL, - .write = NULL, - .unlocked_ioctl = visorchipset_ioctl, - .release = visorchipset_release, - .mmap = visorchipset_mmap, -}; - -int -visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) -{ - int rc = 0; - - file_controlvm_channel = controlvm_channel; - cdev_init(&file_cdev, &visorchipset_fops); - file_cdev.owner = THIS_MODULE; - if (MAJOR(major_dev) == 0) { - rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset"); - /* dynamic major device number registration required */ - if (rc < 0) - return rc; - } else { - /* static major device number registration required */ - rc = register_chrdev_region(major_dev, 1, "visorchipset"); - if (rc < 0) - return rc; - } - rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1); - if (rc < 0) { - unregister_chrdev_region(major_dev, 1); - return rc; - } - return 0; -} - - - -static int __init -visorchipset_init(void) -{ - int rc = 0, x = 0; - HOSTADDRESS addr; - - if (!unisys_spar_platform) - return -ENODEV; - - memset(&busdev_server_notifiers, 0, sizeof(busdev_server_notifiers)); - memset(&busdev_client_notifiers, 0, sizeof(busdev_client_notifiers)); - memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); - memset(&livedump_info, 0, sizeof(livedump_info)); - atomic_set(&livedump_info.buffers_in_use, 0); - - if (visorchipset_testvnic) { - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, x, DIAG_SEVERITY_ERR); - rc = x; - goto cleanup; - } - - addr = controlvm_get_channel_address(); - if (addr) { - controlvm_channel = - visorchannel_create_with_lock - (addr, - sizeof(struct spar_controlvm_channel_protocol), - spar_controlvm_channel_protocol_uuid); - if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT( - visorchannel_get_header(controlvm_channel))) { - initialize_controlvm_payload(); - } else { - visorchannel_destroy(controlvm_channel); - controlvm_channel = NULL; - return -ENODEV; - } - } else { - return -ENODEV; - } - - major_dev = MKDEV(visorchipset_major, 0); - rc = visorchipset_file_init(major_dev, &controlvm_channel); - if (rc < 0) { - POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR); - goto cleanup; - } - - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); - - if (!visorchipset_disable_controlvm) { - /* if booting in a crash kernel */ - if (is_kdump_kernel()) - INIT_DELAYED_WORK(&periodic_controlvm_work, - setup_crash_devices_work_queue); - else - INIT_DELAYED_WORK(&periodic_controlvm_work, - controlvm_periodic_work); - periodic_controlvm_workqueue = - create_singlethread_workqueue("visorchipset_controlvm"); - - if (!periodic_controlvm_workqueue) { - POSTCODE_LINUX_2(CREATE_WORKQUEUE_FAILED_PC, - DIAG_SEVERITY_ERR); - rc = -ENOMEM; - goto cleanup; - } - most_recent_message_jiffies = jiffies; - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - rc = queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); - if (rc < 0) { - POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, - DIAG_SEVERITY_ERR); - goto cleanup; - } - } - - visorchipset_platform_device.dev.devt = major_dev; - if (platform_device_register(&visorchipset_platform_device) < 0) { - POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR); - rc = -1; - goto cleanup; - } - POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO); - rc = 0; -cleanup: - if (rc) { - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, - POSTCODE_SEVERITY_ERR); - } - return rc; -} - -void -visorchipset_file_cleanup(dev_t major_dev) -{ - if (file_cdev.ops) - cdev_del(&file_cdev); - file_cdev.ops = NULL; - unregister_chrdev_region(major_dev, 1); -} - -static void -visorchipset_exit(void) -{ - POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO); - - if (visorchipset_disable_controlvm) { - ; - } else { - cancel_delayed_work(&periodic_controlvm_work); - flush_workqueue(periodic_controlvm_workqueue); - destroy_workqueue(periodic_controlvm_workqueue); - periodic_controlvm_workqueue = NULL; - destroy_controlvm_payload_info(&controlvm_payload_info); - } - - cleanup_controlvm_structures(); - - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); - - visorchannel_destroy(controlvm_channel); - - visorchipset_file_cleanup(visorchipset_platform_device.dev.devt); - POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO); -} - -module_param_named(testvnic, visorchipset_testvnic, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_testvnic, "1 to test vnic, using dummy VNIC connected via a loopback to a physical ethernet"); -module_param_named(testvnicclient, visorchipset_testvnicclient, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_testvnicclient, "1 to test vnic, using real VNIC channel attached to a separate IOVM guest"); -module_param_named(testmsg, visorchipset_testmsg, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_testmsg, - "1 to manufacture the chipset, bus, and switch messages"); -module_param_named(major, visorchipset_major, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_major, - "major device number to use for the device node"); -module_param_named(serverregwait, visorchipset_serverregwait, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_serverreqwait, - "1 to have the module wait for the visor bus to register"); -module_param_named(clientregwait, visorchipset_clientregwait, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_clientregwait, "1 to have the module wait for the visorclientbus to register"); -module_param_named(testteardown, visorchipset_testteardown, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_testteardown, - "1 to test teardown of the chipset, bus, and switch"); -module_param_named(disable_controlvm, visorchipset_disable_controlvm, int, - S_IRUGO); -MODULE_PARM_DESC(visorchipset_disable_controlvm, - "1 to disable polling of controlVm channel"); -module_param_named(holdchipsetready, visorchipset_holdchipsetready, - int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_holdchipsetready, - "1 to hold response to CHIPSET_READY"); - -module_init(visorchipset_init); -module_exit(visorchipset_exit); - -MODULE_AUTHOR("Unisys"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver " - VERSION); -MODULE_VERSION(VERSION); -- cgit v1.2.3-55-g7522