^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* ds.c: Domain Services driver for Logical Domains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched/clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/hypervisor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/ldc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/vio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/mdesc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DRV_MODULE_NAME "ds"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PFX DRV_MODULE_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRV_MODULE_VERSION "1.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DRV_MODULE_RELDATE "Jul 11, 2007"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static char version[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_DESCRIPTION("Sun LDOM domain services driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MODULE_VERSION(DRV_MODULE_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct ds_msg_tag {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) __u32 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DS_INIT_REQ 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DS_INIT_ACK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DS_INIT_NACK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DS_REG_REQ 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DS_REG_ACK 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DS_REG_NACK 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DS_UNREG_REQ 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DS_UNREG_ACK 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DS_UNREG_NACK 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define DS_DATA 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define DS_NACK 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) __u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Result codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define DS_OK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define DS_REG_VER_NACK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DS_REG_DUP 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define DS_INV_HDL 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define DS_TYPE_UNKNOWN 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct ds_version {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) __u16 major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) __u16 minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct ds_ver_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct ds_version ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct ds_ver_ack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) __u16 minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct ds_ver_nack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) __u16 major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct ds_reg_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) __u16 major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) __u16 minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) char svc_id[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct ds_reg_ack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __u16 minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct ds_reg_nack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) __u16 major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct ds_unreg_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct ds_unreg_ack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct ds_unreg_nack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct ds_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) __u64 handle;
^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) struct ds_data_nack {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct ds_msg_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) __u64 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct ds_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct ds_cap_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) __u64 handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) void (*data)(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) const char *service_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u8 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define CAP_STATE_UNKNOWN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define CAP_STATE_REG_SENT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define CAP_STATE_REGISTERED 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void md_update_data(struct ds_info *dp, struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void domain_shutdown_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void domain_panic_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void dr_cpu_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void ds_pri_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void ds_var_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) void *buf, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct ds_cap_state ds_states_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .service_id = "md-update",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .data = md_update_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .service_id = "domain-shutdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .data = domain_shutdown_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .service_id = "domain-panic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .data = domain_panic_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .service_id = "dr-cpu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .data = dr_cpu_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .service_id = "pri",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .data = ds_pri_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .service_id = "var-config",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .data = ds_var_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .service_id = "var-config-backup",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .data = ds_var_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static DEFINE_SPINLOCK(ds_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct ds_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct ldc_channel *lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u8 hs_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define DS_HS_START 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define DS_HS_DONE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u64 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) void *rcv_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int rcv_buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct ds_cap_state *ds_states;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int num_ds_states;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct ds_info *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static struct ds_info *ds_info_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static struct ds_cap_state *find_cap(struct ds_info *dp, u64 handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) unsigned int index = handle >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (index >= dp->num_ds_states)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return &dp->ds_states[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static struct ds_cap_state *find_cap_by_string(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) for (i = 0; i < dp->num_ds_states; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (strcmp(dp->ds_states[i].service_id, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return &dp->ds_states[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int __ds_send(struct ldc_channel *lp, void *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int err, limit = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) while (limit-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) err = ldc_write(lp, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!err || (err != -EAGAIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int ds_send(struct ldc_channel *lp, void *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) err = __ds_send(lp, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct ds_md_update_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct ds_md_update_res {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) __u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static void md_update_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct ds_data *dpkt = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct ds_md_update_req *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct ds_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct ds_md_update_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) } pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) rp = (struct ds_md_update_req *) (dpkt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) printk(KERN_INFO "ds-%llu: Machine description update.\n", dp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) mdesc_update();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) memset(&pkt, 0, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pkt.data.tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pkt.data.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pkt.res.req_num = rp->req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pkt.res.result = DS_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ds_send(lp, &pkt, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct ds_shutdown_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) __u32 ms_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct ds_shutdown_res {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) __u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) char reason[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static void domain_shutdown_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct ds_data *dpkt = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct ds_shutdown_req *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct ds_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct ds_shutdown_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) rp = (struct ds_shutdown_req *) (dpkt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) printk(KERN_ALERT "ds-%llu: Shutdown request from "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "LDOM manager received.\n", dp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) memset(&pkt, 0, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) pkt.data.tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pkt.data.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pkt.res.req_num = rp->req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) pkt.res.result = DS_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pkt.res.reason[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ds_send(lp, &pkt, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) orderly_poweroff(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct ds_panic_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct ds_panic_res {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) __u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) char reason[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static void domain_panic_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct ds_data *dpkt = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct ds_panic_req *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct ds_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct ds_panic_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) } pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rp = (struct ds_panic_req *) (dpkt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) printk(KERN_ALERT "ds-%llu: Panic request from "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) "LDOM manager received.\n", dp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) memset(&pkt, 0, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pkt.data.tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) pkt.data.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) pkt.res.req_num = rp->req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pkt.res.result = DS_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pkt.res.reason[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ds_send(lp, &pkt, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) panic("PANIC requested by LDOM manager.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct dr_cpu_tag {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) __u32 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) #define DR_CPU_CONFIGURE 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) #define DR_CPU_UNCONFIGURE 0x55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) #define DR_CPU_FORCE_UNCONFIGURE 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) #define DR_CPU_STATUS 0x53
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* Responses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #define DR_CPU_OK 0x6f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) #define DR_CPU_ERROR 0x65
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) __u32 num_records;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct dr_cpu_resp_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) __u32 cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) __u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #define DR_CPU_RES_OK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #define DR_CPU_RES_FAILURE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) #define DR_CPU_RES_BLOCKED 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) #define DR_CPU_RES_CPU_NOT_RESPONDING 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #define DR_CPU_RES_NOT_IN_MD 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) __u32 stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #define DR_CPU_STAT_NOT_PRESENT 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #define DR_CPU_STAT_UNCONFIGURED 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) #define DR_CPU_STAT_CONFIGURED 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) __u32 str_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static void __dr_cpu_send_error(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct ds_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct ds_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct dr_cpu_tag tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) } pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) memset(&pkt, 0, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) pkt.data.tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) pkt.data.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) pkt.tag.req_num = tag->req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) pkt.tag.type = DR_CPU_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pkt.tag.num_records = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) msg_len = (sizeof(struct ds_data) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) sizeof(struct dr_cpu_tag));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) __ds_send(dp->lp, &pkt, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void dr_cpu_send_error(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct ds_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) __dr_cpu_send_error(dp, cp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) #define CPU_SENTINEL 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static void purge_dups(u32 *list, u32 num_ents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) for (i = 0; i < num_ents; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) u32 cpu = list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) unsigned int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (cpu == CPU_SENTINEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) for (j = i + 1; j < num_ents; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (list[j] == cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) list[j] = CPU_SENTINEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static int dr_cpu_size_response(int ncpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return (sizeof(struct ds_data) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) sizeof(struct dr_cpu_tag) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) (sizeof(struct dr_cpu_resp_entry) * ncpus));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static void dr_cpu_init_response(struct ds_data *resp, u64 req_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) u64 handle, int resp_len, int ncpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) cpumask_t *mask, u32 default_stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct dr_cpu_resp_entry *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct dr_cpu_tag *tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int i, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) tag = (struct dr_cpu_tag *) (resp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ent = (struct dr_cpu_resp_entry *) (tag + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) resp->tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) resp->tag.len = resp_len - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) resp->handle = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) tag->req_num = req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) tag->type = DR_CPU_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) tag->num_records = ncpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) for_each_cpu(cpu, mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ent[i].cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ent[i].result = DR_CPU_RES_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ent[i].stat = default_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) BUG_ON(i != ncpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) u32 res, u32 stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct dr_cpu_resp_entry *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct dr_cpu_tag *tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) tag = (struct dr_cpu_tag *) (resp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ent = (struct dr_cpu_resp_entry *) (tag + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) for (i = 0; i < ncpus; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (ent[i].cpu != cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ent[i].result = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ent[i].stat = stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int dr_cpu_configure(struct ds_info *dp, struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) u64 req_num, cpumask_t *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct ds_data *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int resp_len, ncpus, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ncpus = cpumask_weight(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) resp_len = dr_cpu_size_response(ncpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) resp = kzalloc(resp_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dr_cpu_init_response(resp, req_num, cp->handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) resp_len, ncpus, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) DR_CPU_STAT_CONFIGURED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mdesc_populate_present_mask(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mdesc_fill_in_cpu_data(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) for_each_cpu(cpu, mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) printk(KERN_INFO "ds-%llu: Starting cpu %d...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) dp->id, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) err = add_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) __u32 res = DR_CPU_RES_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) __u32 stat = DR_CPU_STAT_UNCONFIGURED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!cpu_present(cpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* CPU not present in MD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) res = DR_CPU_RES_NOT_IN_MD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) stat = DR_CPU_STAT_NOT_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else if (err == -ENODEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* CPU did not call in successfully */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) res = DR_CPU_RES_CPU_NOT_RESPONDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) printk(KERN_INFO "ds-%llu: CPU startup failed err=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) dp->id, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dr_cpu_mark(resp, cpu, ncpus, res, stat);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) __ds_send(dp->lp, resp, resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) kfree(resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* Redistribute IRQs, taking into account the new cpus. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) fixup_irqs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int dr_cpu_unconfigure(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) u64 req_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) cpumask_t *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct ds_data *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int resp_len, ncpus, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) ncpus = cpumask_weight(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) resp_len = dr_cpu_size_response(ncpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) resp = kzalloc(resp_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (!resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dr_cpu_init_response(resp, req_num, cp->handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) resp_len, ncpus, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) DR_CPU_STAT_UNCONFIGURED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) for_each_cpu(cpu, mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dp->id, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) err = remove_cpu(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) dr_cpu_mark(resp, cpu, ncpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) DR_CPU_RES_FAILURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) DR_CPU_STAT_CONFIGURED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) __ds_send(dp->lp, resp, resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) kfree(resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct ds_data *data = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) u32 *cpu_list = (u32 *) (tag + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) u64 req_num = tag->req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) cpumask_t mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) switch (tag->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case DR_CPU_CONFIGURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case DR_CPU_UNCONFIGURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case DR_CPU_FORCE_UNCONFIGURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dr_cpu_send_error(dp, cp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) purge_dups(cpu_list, tag->num_records);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) cpumask_clear(&mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) for (i = 0; i < tag->num_records; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (cpu_list[i] == CPU_SENTINEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (cpu_list[i] < nr_cpu_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) cpumask_set_cpu(cpu_list[i], &mask);
^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) if (tag->type == DR_CPU_CONFIGURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) err = dr_cpu_configure(dp, cp, req_num, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) err = dr_cpu_unconfigure(dp, cp, req_num, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dr_cpu_send_error(dp, cp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) #endif /* CONFIG_HOTPLUG_CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct ds_pri_msg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) __u64 req_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) __u64 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) #define DS_PRI_REQUEST 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) #define DS_PRI_DATA 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) #define DS_PRI_UPDATE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static void ds_pri_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct ds_data *dpkt = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) struct ds_pri_msg *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) rp = (struct ds_pri_msg *) (dpkt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) printk(KERN_INFO "ds-%llu: PRI REQ [%llx:%llx], len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dp->id, rp->req_num, rp->type, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct ds_var_hdr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) __u32 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) #define DS_VAR_SET_REQ 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) #define DS_VAR_DELETE_REQ 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) #define DS_VAR_SET_RESP 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) #define DS_VAR_DELETE_RESP 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct ds_var_set_msg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct ds_var_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) char name_and_value[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct ds_var_delete_msg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) struct ds_var_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) char name[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct ds_var_resp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct ds_var_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) __u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) #define DS_VAR_SUCCESS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) #define DS_VAR_NO_SPACE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) #define DS_VAR_INVALID_VAR 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) #define DS_VAR_INVALID_VAL 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) #define DS_VAR_NOT_PRESENT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static DEFINE_MUTEX(ds_var_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static int ds_var_doorbell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static int ds_var_response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static void ds_var_data(struct ds_info *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct ds_cap_state *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct ds_data *dpkt = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct ds_var_resp *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) rp = (struct ds_var_resp *) (dpkt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (rp->hdr.type != DS_VAR_SET_RESP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) rp->hdr.type != DS_VAR_DELETE_RESP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ds_var_response = rp->result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) ds_var_doorbell = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) void ldom_set_var(const char *var, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct ds_cap_state *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct ds_info *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) cp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) for (dp = ds_info_list; dp; dp = dp->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct ds_cap_state *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) tmp = find_cap_by_string(dp, "var-config");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (tmp && tmp->state == CAP_STATE_REGISTERED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) cp = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) for (dp = ds_info_list; dp; dp = dp->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct ds_cap_state *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) tmp = find_cap_by_string(dp, "var-config-backup");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (tmp && tmp->state == CAP_STATE_REGISTERED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) cp = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct ds_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct ds_var_set_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) } header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) char all[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) } pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) char *base, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) int msg_len, loops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (strlen(var) + strlen(value) + 2 >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) sizeof(pkt) - sizeof(pkt.header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) printk(KERN_ERR PFX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) "contents length: %zu, which more than max: %lu,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) "so could not set (%s) variable to (%s).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) strlen(var) + strlen(value) + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) sizeof(pkt) - sizeof(pkt.header), var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) memset(&pkt, 0, sizeof(pkt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) pkt.header.data.tag.type = DS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) pkt.header.data.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) pkt.header.msg.hdr.type = DS_VAR_SET_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) base = p = &pkt.header.msg.name_and_value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) strcpy(p, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) p += strlen(var) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) strcpy(p, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) p += strlen(value) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) msg_len = (sizeof(struct ds_data) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) sizeof(struct ds_var_set_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) (p - base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) msg_len = (msg_len + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) pkt.header.data.tag.len = msg_len - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) mutex_lock(&ds_var_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) ds_var_doorbell = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) ds_var_response = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) __ds_send(dp->lp, &pkt, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) loops = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) while (ds_var_doorbell == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (loops-- < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mutex_unlock(&ds_var_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ds_var_doorbell == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ds_var_response != DS_VAR_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) printk(KERN_ERR "ds-%llu: var-config [%s:%s] "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) "failed, response(%d).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) dp->id, var, value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ds_var_response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) printk(KERN_ERR PFX "var-config not registered so "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) "could not set (%s) variable to (%s).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static char full_boot_str[256] __attribute__((aligned(32)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int reboot_data_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) void ldom_reboot(const char *boot_command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* Don't bother with any of this if the boot_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * is empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (boot_command && strlen(boot_command)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) unsigned long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) snprintf(full_boot_str, sizeof(full_boot_str), "boot %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) boot_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) len = strlen(full_boot_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (reboot_data_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) unsigned long ra = kimage_addr_to_ra(full_boot_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) unsigned long hv_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) hv_ret = sun4v_reboot_data_set(ra, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (hv_ret != HV_EOK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) pr_err("SUN4V: Unable to set reboot data "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) "hv_ret=%lu\n", hv_ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ldom_set_var("reboot-command", full_boot_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) sun4v_mach_sir();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) void ldom_power_off(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) sun4v_mach_exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static void ds_conn_reset(struct ds_info *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) printk(KERN_ERR "ds-%llu: ds_conn_reset() from %ps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dp->id, __builtin_return_address(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static int register_services(struct ds_info *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) for (i = 0; i < dp->num_ds_states; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct ds_reg_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) u8 id_buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) } pbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct ds_cap_state *cp = &dp->ds_states[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) int err, msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) u64 new_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (cp->state == CAP_STATE_REGISTERED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) new_count = sched_clock() & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) cp->handle = ((u64) i << 32) | new_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) msg_len = (sizeof(struct ds_reg_req) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) strlen(cp->service_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) memset(&pbuf, 0, sizeof(pbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) pbuf.req.tag.type = DS_REG_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) pbuf.req.tag.len = (msg_len - sizeof(struct ds_msg_tag));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) pbuf.req.handle = cp->handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) pbuf.req.major = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) pbuf.req.minor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) strcpy(pbuf.id_buf, cp->service_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) err = __ds_send(lp, &pbuf, msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) cp->state = CAP_STATE_REG_SENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (dp->hs_state == DS_HS_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (pkt->type != DS_INIT_ACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) goto conn_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) dp->hs_state = DS_HS_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return register_services(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (dp->hs_state != DS_HS_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) goto conn_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (pkt->type == DS_REG_ACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct ds_reg_ack *ap = (struct ds_reg_ack *) pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct ds_cap_state *cp = find_cap(dp, ap->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) printk(KERN_ERR "ds-%llu: REG ACK for unknown "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) "handle %llx\n", dp->id, ap->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) printk(KERN_INFO "ds-%llu: Registered %s service.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) dp->id, cp->service_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) cp->state = CAP_STATE_REGISTERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) } else if (pkt->type == DS_REG_NACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct ds_reg_nack *np = (struct ds_reg_nack *) pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) struct ds_cap_state *cp = find_cap(dp, np->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) printk(KERN_ERR "ds-%llu: REG NACK for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) "unknown handle %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) dp->id, np->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) cp->state = CAP_STATE_UNKNOWN;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) conn_reset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) ds_conn_reset(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return -ECONNRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static void __send_ds_nack(struct ds_info *dp, u64 handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct ds_data_nack nack = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .tag = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .type = DS_NACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .len = (sizeof(struct ds_data_nack) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) sizeof(struct ds_msg_tag)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .handle = handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .result = DS_INV_HDL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) __ds_send(dp->lp, &nack, sizeof(nack));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static LIST_HEAD(ds_work_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static DECLARE_WAIT_QUEUE_HEAD(ds_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct ds_queue_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct ds_info *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) int req_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) int __pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) u64 req[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static void process_ds_work(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct ds_queue_entry *qp, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) LIST_HEAD(todo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) list_splice_init(&ds_work_list, &todo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) list_for_each_entry_safe(qp, tmp, &todo, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct ds_data *dpkt = (struct ds_data *) qp->req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct ds_info *dp = qp->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct ds_cap_state *cp = find_cap(dp, dpkt->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) int req_len = qp->req_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (!cp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) printk(KERN_ERR "ds-%llu: Data for unknown "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) "handle %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) dp->id, dpkt->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) __send_ds_nack(dp, dpkt->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) cp->data(dp, cp, dpkt, req_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) list_del(&qp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) kfree(qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static int ds_thread(void *__unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (list_empty(&ds_work_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) finish_wait(&ds_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (kthread_should_stop())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) process_ds_work();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct ds_data *dpkt = (struct ds_data *) pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct ds_queue_entry *qp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (!qp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) __send_ds_nack(dp, dpkt->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) qp->dp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) memcpy(&qp->req, pkt, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) list_add_tail(&qp->list, &ds_work_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) wake_up(&ds_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static void ds_up(struct ds_info *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct ds_ver_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) req.tag.type = DS_INIT_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) req.tag.len = sizeof(req) - sizeof(struct ds_msg_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) req.ver.major = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) req.ver.minor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) err = __ds_send(lp, &req, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (err > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) dp->hs_state = DS_HS_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static void ds_reset(struct ds_info *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) dp->hs_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) for (i = 0; i < dp->num_ds_states; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct ds_cap_state *cp = &dp->ds_states[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) cp->state = CAP_STATE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static void ds_event(void *arg, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct ds_info *dp = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct ldc_channel *lp = dp->lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) spin_lock_irqsave(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (event == LDC_EVENT_UP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) ds_up(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (event == LDC_EVENT_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) ds_reset(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (event != LDC_EVENT_DATA_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) printk(KERN_WARNING "ds-%llu: Unexpected LDC event %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) dp->id, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) struct ds_msg_tag *tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) err = ldc_read(lp, dp->rcv_buf, sizeof(*tag));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (unlikely(err < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if (err == -ECONNRESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) ds_conn_reset(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) tag = dp->rcv_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) err = ldc_read(lp, tag + 1, tag->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (unlikely(err < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (err == -ECONNRESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ds_conn_reset(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (err < tag->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (tag->type < DS_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) err = ds_handshake(dp, dp->rcv_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) err = ds_data(dp, dp->rcv_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) sizeof(*tag) + err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (err == -ECONNRESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) spin_unlock_irqrestore(&ds_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int ds_version_printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) struct ldc_channel_config ds_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .event = ds_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .mtu = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .mode = LDC_MODE_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct mdesc_handle *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) struct ldc_channel *lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) struct ds_info *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) const u64 *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (ds_version_printed++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) printk(KERN_INFO "%s", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) dp = kzalloc(sizeof(*dp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (!dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) hp = mdesc_grab();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) val = mdesc_get_property(hp, vdev->mp, "id", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) dp->id = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) mdesc_release(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dp->rcv_buf = kzalloc(4096, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (!dp->rcv_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) goto out_free_dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) dp->rcv_buf_len = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) dp->ds_states = kmemdup(ds_states_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) sizeof(ds_states_template), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!dp->ds_states)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) goto out_free_rcv_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) dp->num_ds_states = ARRAY_SIZE(ds_states_template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) for (i = 0; i < dp->num_ds_states; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dp->ds_states[i].handle = ((u64)i << 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) ds_cfg.tx_irq = vdev->tx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ds_cfg.rx_irq = vdev->rx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp, "DS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (IS_ERR(lp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) err = PTR_ERR(lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) goto out_free_ds_states;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dp->lp = lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) err = ldc_bind(lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) goto out_free_ldc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) spin_lock_irq(&ds_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) dp->next = ds_info_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ds_info_list = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) spin_unlock_irq(&ds_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) out_free_ldc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ldc_free(dp->lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) out_free_ds_states:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) kfree(dp->ds_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) out_free_rcv_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) kfree(dp->rcv_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) out_free_dp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) kfree(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static int ds_remove(struct vio_dev *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) static const struct vio_device_id ds_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .type = "domain-services-port",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static struct vio_driver ds_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) .id_table = ds_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .probe = ds_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .remove = ds_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .name = "ds",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static int __init ds_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) unsigned long hv_ret, major, minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (tlb_type == hypervisor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (hv_ret == HV_EOK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) major, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) reboot_data_supported = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) kthread_run(ds_thread, NULL, "kldomd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return vio_register_driver(&ds_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) fs_initcall(ds_init);