^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * IBM ASM Service Processor Device Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) IBM Corporation, 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Max Asböck <amax@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "ibmasm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "lowlevel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static void exec_next_command(struct service_processor *sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static atomic_t command_count = ATOMIC_INIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct command *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) cmd = kzalloc(sizeof(struct command), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) cmd->buffer = kzalloc(buffer_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (cmd->buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) cmd->buffer_size = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) kref_init(&cmd->kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) cmd->lock = &sp->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) cmd->status = IBMASM_CMD_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) init_waitqueue_head(&cmd->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) INIT_LIST_HEAD(&cmd->queue_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) atomic_inc(&command_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) dbg("command count: %d\n", atomic_read(&command_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void ibmasm_free_command(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct command *cmd = to_command(kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) list_del(&cmd->queue_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) atomic_dec(&command_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) dbg("command count: %d\n", atomic_read(&command_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) kfree(cmd->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void enqueue_command(struct service_processor *sp, struct command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) list_add_tail(&cmd->queue_node, &sp->command_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static struct command *dequeue_command(struct service_processor *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct command *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct list_head *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (list_empty(&sp->command_queue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) next = sp->command_queue.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) list_del_init(next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) cmd = list_entry(next, struct command, queue_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline void do_exec_command(struct service_processor *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) char tsbuf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ibmasm_send_i2o_message(sp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sp->current_command->status = IBMASM_CMD_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) wake_up(&sp->current_command->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) command_put(sp->current_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) exec_next_command(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * exec_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * send a command to a service processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Commands are executed sequentially. One command (sp->current_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * is sent to the service processor. Once the interrupt handler gets a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * message of type command_response, the message is copied into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * the current commands buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) char tsbuf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) spin_lock_irqsave(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!sp->current_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) sp->current_command = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) command_get(sp->current_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) spin_unlock_irqrestore(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) do_exec_command(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) enqueue_command(sp, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) spin_unlock_irqrestore(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void exec_next_command(struct service_processor *sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) char tsbuf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) spin_lock_irqsave(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) sp->current_command = dequeue_command(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (sp->current_command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) command_get(sp->current_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) spin_unlock_irqrestore(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) do_exec_command(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) spin_unlock_irqrestore(&sp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Sleep until a command has failed or a response has been received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * and the command status been updated by the interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * (see receive_response).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) void ibmasm_wait_for_response(struct command *cmd, int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) wait_event_interruptible_timeout(cmd->wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) cmd->status == IBMASM_CMD_COMPLETE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) cmd->status == IBMASM_CMD_FAILED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) timeout * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * receive_command_response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * called by the interrupt handler when a dot command of type command_response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * was received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct command *cmd = sp->current_command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!sp->current_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) cmd->status = IBMASM_CMD_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) wake_up(&sp->current_command->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) command_put(sp->current_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) exec_next_command(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }