^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2004 Hollis Blanchard <hollisb@us.ibm.com>, IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /* Host Virtual Serial Interface (HVSI) is a protocol between the hosted OS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * and the service processor on IBM pSeries servers. On these servers, there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * are no serial ports under the OS's control, and sometimes there is no other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * console available either. However, the service processor has two standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * serial ports, so this over-complicated protocol allows the OS to control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * those ports by proxy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Besides data, the procotol supports the reading/writing of the serial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * port's DTR line, and the reading of the CD line. This is to allow the OS to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * control a modem attached to the service processor's serial port. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * the OS cannot change the speed of the port through this protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/hvcall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/hvconsole.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/vio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/hvsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define HVSI_MAJOR 229
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define HVSI_MINOR 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MAX_NR_HVSI_CONSOLES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define HVSI_TIMEOUT (5*HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define HVSI_VERSION 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define HVSI_MAX_PACKET 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define HVSI_MAX_READ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define HVSI_MAX_OUTGOING_DATA 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define N_OUTBUF 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * we pass data via two 8-byte registers, so we would like our char arrays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * properly aligned for those loads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct hvsi_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct tty_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct delayed_work writer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct work_struct handshaker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) wait_queue_head_t emptyq; /* woken when outbuf is emptied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) wait_queue_head_t stateq; /* woken when HVSI state changes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) uint8_t throttle_buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* inbuf is for packet reassembly. leave a little room for leftovers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) uint8_t inbuf[HVSI_MAX_PACKET + HVSI_MAX_READ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) uint8_t *inbuf_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int n_throttle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int n_outbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) uint32_t vtermno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) uint32_t virq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) atomic_t seqno; /* HVSI packet sequence number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) uint16_t mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) uint8_t state; /* HVSI protocol state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) uint8_t flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #ifdef CONFIG_MAGIC_SYSRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) uint8_t sysrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #endif /* CONFIG_MAGIC_SYSRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static struct hvsi_struct hvsi_ports[MAX_NR_HVSI_CONSOLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static struct tty_driver *hvsi_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int hvsi_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int (*hvsi_wait)(struct hvsi_struct *hp, int state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) enum HVSI_PROTOCOL_STATE {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) HVSI_CLOSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) HVSI_WAIT_FOR_VER_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) HVSI_WAIT_FOR_VER_QUERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) HVSI_OPEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) HVSI_WAIT_FOR_MCTRL_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) HVSI_FSP_DIED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define HVSI_CONSOLE 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline int is_console(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return hp->flags & HVSI_CONSOLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static inline int is_open(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* if we're waiting for an mctrl then we're already open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return (hp->state == HVSI_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) || (hp->state == HVSI_WAIT_FOR_MCTRL_RESPONSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline void print_state(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const char *state_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "HVSI_CLOSED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "HVSI_WAIT_FOR_VER_RESPONSE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) "HVSI_WAIT_FOR_VER_QUERY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "HVSI_OPEN",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "HVSI_WAIT_FOR_MCTRL_RESPONSE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "HVSI_FSP_DIED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) const char *name = (hp->state < ARRAY_SIZE(state_names))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ? state_names[hp->state] : "UNKNOWN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pr_debug("hvsi%i: state = %s\n", hp->index, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #endif /* DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static inline void __set_state(struct hvsi_struct *hp, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) hp->state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) print_state(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) wake_up_all(&hp->stateq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static inline void set_state(struct hvsi_struct *hp, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) __set_state(hp, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static inline int len_packet(const uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return (int)((struct hvsi_header *)packet)->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static inline int is_header(const uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct hvsi_header *header = (struct hvsi_header *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return header->type >= VS_QUERY_RESPONSE_PACKET_HEADER;
^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) static inline int got_packet(const struct hvsi_struct *hp, uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (hp->inbuf_end < packet + sizeof(struct hvsi_header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 0; /* don't even have the packet header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (hp->inbuf_end < (packet + len_packet(packet)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0; /* don't have the rest of the packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* shift remaining bytes in packetbuf down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int remaining = (int)(hp->inbuf_end - read_to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) pr_debug("%s: %i chars remain\n", __func__, remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (read_to != hp->inbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) memmove(hp->inbuf, read_to, remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) hp->inbuf_end = hp->inbuf + remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define dbg_dump_packet(packet) dump_packet(packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define dbg_dump_hex(data, len) dump_hex(data, len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define dbg_dump_packet(packet) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define dbg_dump_hex(data, len) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void dump_hex(const uint8_t *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) printk(" ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) for (i=0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) printk("%.2x", data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printk("\n ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i=0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (isprint(data[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printk("%c", data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) printk(".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void dump_packet(uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct hvsi_header *header = (struct hvsi_header *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) printk("type 0x%x, len %i, seqno %i:\n", header->type, header->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) header->seqno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dump_hex(packet, header->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) unsigned long got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) got = hvc_get_chars(hp->vtermno, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct tty_struct *tty, struct hvsi_struct **to_handshake)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct hvsi_control *header = (struct hvsi_control *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) switch (be16_to_cpu(header->verb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case VSV_MODEM_CTL_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if ((be32_to_cpu(header->word) & HVSI_TSCD) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* CD went away; no more connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pr_debug("hvsi%i: CD dropped\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) hp->mctrl &= TIOCM_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (tty && !C_CLOCAL(tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) tty_hangup(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case VSV_CLOSE_PROTOCOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pr_debug("hvsi%i: service processor came back\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (hp->state != HVSI_CLOSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *to_handshake = hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) dump_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct hvsi_query_response *resp = (struct hvsi_query_response *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) uint32_t mctrl_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) switch (hp->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case HVSI_WAIT_FOR_VER_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) __set_state(hp, HVSI_WAIT_FOR_VER_QUERY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case HVSI_WAIT_FOR_MCTRL_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) hp->mctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) mctrl_word = be32_to_cpu(resp->u.mctrl_word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (mctrl_word & HVSI_TSDTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) hp->mctrl |= TIOCM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (mctrl_word & HVSI_TSCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) hp->mctrl |= TIOCM_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) __set_state(hp, HVSI_OPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) printk(KERN_ERR "hvsi%i: unexpected query response: ", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dump_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* respond to service processor's version query */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct hvsi_query_response packet __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int wrote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) packet.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) packet.hdr.len = sizeof(struct hvsi_query_response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) packet.hdr.seqno = cpu_to_be16(atomic_inc_return(&hp->seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) packet.verb = cpu_to_be16(VSV_SEND_VERSION_NUMBER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) packet.u.version = HVSI_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) packet.query_seqno = cpu_to_be16(query_seqno+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (wrote != packet.hdr.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct hvsi_query *query = (struct hvsi_query *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) switch (hp->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case HVSI_WAIT_FOR_VER_QUERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) hvsi_version_respond(hp, be16_to_cpu(query->hdr.seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) __set_state(hp, HVSI_OPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) dump_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) for (i=0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) char c = buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) #ifdef CONFIG_MAGIC_SYSRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (c == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) hp->sysrq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) } else if (hp->sysrq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) handle_sysrq(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) hp->sysrq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #endif /* CONFIG_MAGIC_SYSRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) tty_insert_flip_char(&hp->port, c, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * We could get 252 bytes of data at once here. But the tty layer only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * throttles us at TTY_THRESHOLD_THROTTLE (128) bytes, so we could overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * it. Accordingly we won't send more than 128 bytes at a time to the flip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * buffer, which will give the tty buffer a chance to throttle us. Should the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * value of TTY_THRESHOLD_THROTTLE change in n_tty.c, this code should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * revisited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) #define TTY_THRESHOLD_THROTTLE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static bool hvsi_recv_data(struct hvsi_struct *hp, const uint8_t *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) const struct hvsi_header *header = (const struct hvsi_header *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) const uint8_t *data = packet + sizeof(struct hvsi_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int datalen = header->len - sizeof(struct hvsi_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int overflow = datalen - TTY_THRESHOLD_THROTTLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (datalen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (overflow > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) datalen = TTY_THRESHOLD_THROTTLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) hvsi_insert_chars(hp, data, datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (overflow > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * we still have more data to deliver, so we need to save off the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * overflow and send it later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pr_debug("%s: deferring overflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) hp->n_throttle = overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * Returns true/false indicating data successfully read from hypervisor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Used both to get packets for tty connections and to advance the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * machine during console handshaking (in which case tty = NULL and we ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * incoming data).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct hvsi_struct **handshake)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) uint8_t *packet = hp->inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int chunklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) bool flip = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *handshake = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (chunklen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) pr_debug("%s: 0-length read\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) pr_debug("%s: got %i bytes\n", __func__, chunklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) dbg_dump_hex(hp->inbuf_end, chunklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) hp->inbuf_end += chunklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* handle all completed packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) while ((packet < hp->inbuf_end) && got_packet(hp, packet)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct hvsi_header *header = (struct hvsi_header *)packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!is_header(packet)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* skip bytes until we find a header or run out of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) while ((packet < hp->inbuf_end) && (!is_header(packet)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) packet++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pr_debug("%s: handling %i-byte packet\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) len_packet(packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) dbg_dump_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) switch (header->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case VS_DATA_PACKET_HEADER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!is_open(hp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) flip = hvsi_recv_data(hp, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) case VS_CONTROL_PACKET_HEADER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) hvsi_recv_control(hp, packet, tty, handshake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case VS_QUERY_RESPONSE_PACKET_HEADER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) hvsi_recv_response(hp, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case VS_QUERY_PACKET_HEADER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) hvsi_recv_query(hp, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) hp->index, header->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) dump_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) packet += len_packet(packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (*handshake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) pr_debug("%s: handshake\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) compact_inbuf(hp, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (flip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) tty_flip_buffer_push(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static void hvsi_send_overflow(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pr_debug("%s: delivering %i bytes overflow\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) hp->n_throttle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) hp->n_throttle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * must get all pending data because we only get an irq on empty->non-empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static irqreturn_t hvsi_interrupt(int irq, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct hvsi_struct *hp = (struct hvsi_struct *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct hvsi_struct *handshake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int again = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) tty = tty_port_tty_get(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) while (again) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) again = hvsi_load_chunk(hp, tty, &handshake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (handshake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) pr_debug("hvsi%i: attempting re-handshake\n", handshake->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) schedule_work(&handshake->handshaker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (tty && hp->n_throttle && !tty_throttled(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* we weren't hung up and we weren't throttled, so we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * deliver the rest now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) hvsi_send_overflow(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) tty_flip_buffer_push(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tty_kref_put(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* for boot console, before the irq handler is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static int __init poll_for_state(struct hvsi_struct *hp, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) hvsi_interrupt(hp->virq, (void *)hp); /* get pending data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (hp->state == state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (time_after(jiffies, end_jiffies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* wait for irq handler to change our state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int wait_for_state(struct hvsi_struct *hp, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!wait_event_timeout(hp->stateq, (hp->state == state), HVSI_TIMEOUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct hvsi_query packet __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int wrote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) packet.hdr.type = VS_QUERY_PACKET_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) packet.hdr.len = sizeof(struct hvsi_query);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) packet.hdr.seqno = cpu_to_be16(atomic_inc_return(&hp->seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) packet.verb = cpu_to_be16(verb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (wrote != packet.hdr.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) wrote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int hvsi_get_mctrl(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) set_state(hp, HVSI_WAIT_FOR_MCTRL_RESPONSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) hvsi_query(hp, VSV_SEND_MODEM_CTL_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ret = hvsi_wait(hp, HVSI_OPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) printk(KERN_ERR "hvsi%i: didn't get modem flags\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) set_state(hp, HVSI_OPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) pr_debug("%s: mctrl 0x%x\n", __func__, hp->mctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* note that we can only set DTR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct hvsi_control packet __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int wrote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) packet.hdr.type = VS_CONTROL_PACKET_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) packet.hdr.seqno = cpu_to_be16(atomic_inc_return(&hp->seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) packet.hdr.len = sizeof(struct hvsi_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) packet.verb = cpu_to_be16(VSV_SET_MODEM_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) packet.mask = cpu_to_be32(HVSI_TSDTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (mctrl & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) packet.word = cpu_to_be32(HVSI_TSDTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (wrote != packet.hdr.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static void hvsi_drain_input(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) while (time_before(end_jiffies, jiffies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int hvsi_handshake(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * We could have a CLOSE or other data waiting for us before we even try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * to open; try to throw it all away so we don't get confused. (CLOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * is the first message sent up the pipe when the FSP comes online. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * need to distinguish between "it came up a while ago and we're the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * user" and "it was just reset before it saw our handshake packet".)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) hvsi_drain_input(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) set_state(hp, HVSI_WAIT_FOR_VER_RESPONSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = hvsi_query(hp, VSV_SEND_VERSION_NUMBER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) printk(KERN_ERR "hvsi%i: couldn't send version query\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ret = hvsi_wait(hp, HVSI_OPEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static void hvsi_handshaker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct hvsi_struct *hp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) container_of(work, struct hvsi_struct, handshaker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (hvsi_handshake(hp) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) printk(KERN_ERR "hvsi%i: re-handshaking failed\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (is_console(hp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * ttys will re-attempt the handshake via hvsi_open, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * the console will not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) printk(KERN_ERR "hvsi%i: lost console!\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct hvsi_data packet __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) packet.hdr.type = VS_DATA_PACKET_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) packet.hdr.seqno = cpu_to_be16(atomic_inc_return(&hp->seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) packet.hdr.len = count + sizeof(struct hvsi_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) memcpy(&packet.data, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (ret == packet.hdr.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* return the number of chars written, not the packet length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return ret; /* return any errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static void hvsi_close_protocol(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) struct hvsi_control packet __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) packet.hdr.type = VS_CONTROL_PACKET_HEADER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) packet.hdr.seqno = cpu_to_be16(atomic_inc_return(&hp->seqno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) packet.hdr.len = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) packet.verb = cpu_to_be16(VSV_CLOSE_PROTOCOL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int hvsi_open(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct hvsi_struct *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) hp = &hvsi_ports[tty->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) tty->driver_data = hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (hp->state == HVSI_FSP_DIED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) tty_port_tty_set(&hp->port, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) hp->port.count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) atomic_set(&hp->seqno, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (is_console(hp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return 0; /* this has already been handshaked as the console */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ret = hvsi_handshake(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) printk(KERN_ERR "%s: HVSI handshaking failed\n", tty->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ret = hvsi_get_mctrl(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) printk(KERN_ERR "%s: couldn't get initial modem flags\n", tty->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) printk(KERN_ERR "%s: couldn't set DTR\n", tty->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* wait for hvsi_write_worker to empty hp->outbuf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static void hvsi_flush_output(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) wait_event_timeout(hp->emptyq, (hp->n_outbuf <= 0), HVSI_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) cancel_delayed_work_sync(&hp->writer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) flush_work(&hp->handshaker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * it's also possible that our timeout expired and hvsi_write_worker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * didn't manage to push outbuf. poof.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) hp->n_outbuf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static void hvsi_close(struct tty_struct *tty, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (tty_hung_up_p(filp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (--hp->port.count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) tty_port_tty_set(&hp->port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* only close down connection if it is not the console */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!is_console(hp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) __set_state(hp, HVSI_CLOSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * any data delivered to the tty layer after this will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * discarded (except for XON/XOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) tty->closing = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /* let any existing irq handlers finish. no more will start. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) synchronize_irq(hp->virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* hvsi_write_worker will re-schedule until outbuf is empty. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) hvsi_flush_output(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* tell FSP to stop sending data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) hvsi_close_protocol(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * drain anything FSP is still in the middle of sending, and let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * hvsi_handshake drain the rest on the next open.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) hvsi_drain_input(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) } else if (hp->port.count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) printk(KERN_ERR "hvsi_close %lu: oops, count is %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) hp - hvsi_ports, hp->port.count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static void hvsi_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) tty_port_tty_set(&hp->port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) hp->port.count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) hp->n_outbuf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* called with hp->lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static void hvsi_push(struct hvsi_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (hp->n_outbuf <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (n > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) pr_debug("%s: wrote %i chars\n", __func__, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) hp->n_outbuf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) } else if (n == -EIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) __set_state(hp, HVSI_FSP_DIED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) printk(KERN_ERR "hvsi%i: service processor died\n", hp->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static void hvsi_write_worker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct hvsi_struct *hp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) container_of(work, struct hvsi_struct, writer.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static long start_j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (start_j == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) start_j = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) #endif /* DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (!is_open(hp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * We could have a non-open connection if the service processor died
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * while we were busily scheduling ourselves. In that case, it could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * be minutes before the service processor comes back, so only try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * again once a second.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) schedule_delayed_work(&hp->writer, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) hvsi_push(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (hp->n_outbuf > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) schedule_delayed_work(&hp->writer, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pr_debug("%s: outbuf emptied after %li jiffies\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) jiffies - start_j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) start_j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) #endif /* DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) wake_up_all(&hp->emptyq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) tty_port_tty_wakeup(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static int hvsi_write_room(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return N_OUTBUF - hp->n_outbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static int hvsi_chars_in_buffer(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return hp->n_outbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static int hvsi_write(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) const char *source = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) int total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) int origcount = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (!is_open(hp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /* we're either closing or not yet open; don't accept data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) pr_debug("%s: not open\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * when the hypervisor buffer (16K) fills, data will stay in hp->outbuf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * will see there is no room in outbuf and return.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) while ((count > 0) && (hvsi_write_room(tty) > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) int chunksize = min(count, hvsi_write_room(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) BUG_ON(hp->n_outbuf < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) memcpy(hp->outbuf + hp->n_outbuf, source, chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) hp->n_outbuf += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) total += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) source += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) count -= chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) hvsi_push(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (hp->n_outbuf > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * we weren't able to write it all to the hypervisor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * schedule another push attempt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) schedule_delayed_work(&hp->writer, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (total != origcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pr_debug("%s: wanted %i, only wrote %i\n", __func__, origcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * I have never seen throttle or unthrottle called, so this little throttle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * buffering scheme may or may not work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static void hvsi_throttle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static void hvsi_unthrottle(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (hp->n_throttle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) hvsi_send_overflow(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) tty_flip_buffer_push(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static int hvsi_tiocmget(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) hvsi_get_mctrl(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return hp->mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static int hvsi_tiocmset(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) unsigned int set, unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct hvsi_struct *hp = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) uint16_t new_mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /* we can only alter DTR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) clear &= TIOCM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) set &= TIOCM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) spin_lock_irqsave(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) new_mctrl = (hp->mctrl & ~clear) | set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (hp->mctrl != new_mctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) hvsi_set_mctrl(hp, new_mctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) hp->mctrl = new_mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) spin_unlock_irqrestore(&hp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static const struct tty_operations hvsi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) .open = hvsi_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) .close = hvsi_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) .write = hvsi_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) .hangup = hvsi_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .write_room = hvsi_write_room,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .chars_in_buffer = hvsi_chars_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .throttle = hvsi_throttle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .unthrottle = hvsi_unthrottle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .tiocmget = hvsi_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) .tiocmset = hvsi_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int __init hvsi_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) hvsi_driver = alloc_tty_driver(hvsi_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (!hvsi_driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) hvsi_driver->driver_name = "hvsi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) hvsi_driver->name = "hvsi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) hvsi_driver->major = HVSI_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) hvsi_driver->minor_start = HVSI_MINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) hvsi_driver->init_termios = tty_std_termios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) hvsi_driver->init_termios.c_ispeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) hvsi_driver->init_termios.c_ospeed = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) tty_set_operations(hvsi_driver, &hvsi_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) for (i=0; i < hvsi_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct hvsi_struct *hp = &hvsi_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) int ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) tty_port_link_device(&hp->port, hvsi_driver, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) hp->virq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) hvsi_wait = wait_for_state; /* irqs active now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ret = tty_register_driver(hvsi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) pr_err("Couldn't register hvsi console driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) err_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) hvsi_wait = poll_for_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) for (i = 0; i < hvsi_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct hvsi_struct *hp = &hvsi_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) free_irq(hp->virq, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) tty_driver_kref_put(hvsi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) device_initcall(hvsi_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /***** console (not tty) code: *****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static void hvsi_console_print(struct console *console, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct hvsi_struct *hp = &hvsi_ports[console->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) char c[HVSI_MAX_OUTGOING_DATA] __ALIGNED__;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) unsigned int i = 0, n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) int ret, donecr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!is_open(hp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * ugh, we have to translate LF -> CRLF ourselves, in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * copied from hvc_console.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) while (count > 0 || i > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (count > 0 && i < sizeof(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (buf[n] == '\n' && !donecr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) c[i++] = '\r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) donecr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) c[i++] = buf[n++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) donecr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) --count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret = hvsi_put_chars(hp, c, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) i -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static struct tty_driver *hvsi_console_device(struct console *console,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) int *index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) *index = console->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return hvsi_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static int __init hvsi_console_setup(struct console *console, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct hvsi_struct *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (console->index < 0 || console->index >= hvsi_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) hp = &hvsi_ports[console->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) /* give the FSP a chance to change the baud rate when we re-open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) hvsi_close_protocol(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ret = hvsi_handshake(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ret = hvsi_get_mctrl(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) hp->flags |= HVSI_CONSOLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static struct console hvsi_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .name = "hvsi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) .write = hvsi_console_print,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .device = hvsi_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .setup = hvsi_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static int __init hvsi_console_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct device_node *vty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) hvsi_wait = poll_for_state; /* no irqs yet; must poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /* search device tree for vty nodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) for_each_compatible_node(vty, "serial", "hvterm-protocol") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct hvsi_struct *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) const __be32 *vtermno, *irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) vtermno = of_get_property(vty, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) irq = of_get_property(vty, "interrupts", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (!vtermno || !irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (hvsi_count >= MAX_NR_HVSI_CONSOLES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) of_node_put(vty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) hp = &hvsi_ports[hvsi_count];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) INIT_WORK(&hp->handshaker, hvsi_handshaker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) init_waitqueue_head(&hp->emptyq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) init_waitqueue_head(&hp->stateq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) spin_lock_init(&hp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) tty_port_init(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) hp->index = hvsi_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) hp->inbuf_end = hp->inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) hp->state = HVSI_CLOSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) hp->vtermno = be32_to_cpup(vtermno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) hp->virq = irq_create_mapping(NULL, be32_to_cpup(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (hp->virq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) __func__, be32_to_cpup(irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) tty_port_destroy(&hp->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) hvsi_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (hvsi_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) register_console(&hvsi_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) console_initcall(hvsi_console_init);