1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright IBM Corp. 2016
4*4882a593Smuzhiyun * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Adjunct processor bus, card related code.
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #define KMSG_COMPONENT "ap"
10*4882a593Smuzhiyun #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <asm/facility.h>
15*4882a593Smuzhiyun #include <asm/sclp.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "ap_bus.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * AP card related attributes.
21*4882a593Smuzhiyun */
hwtype_show(struct device * dev,struct device_attribute * attr,char * buf)22*4882a593Smuzhiyun static ssize_t hwtype_show(struct device *dev,
23*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type);
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static DEVICE_ATTR_RO(hwtype);
31*4882a593Smuzhiyun
raw_hwtype_show(struct device * dev,struct device_attribute * attr,char * buf)32*4882a593Smuzhiyun static ssize_t raw_hwtype_show(struct device *dev,
33*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static DEVICE_ATTR_RO(raw_hwtype);
41*4882a593Smuzhiyun
depth_show(struct device * dev,struct device_attribute * attr,char * buf)42*4882a593Smuzhiyun static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
43*4882a593Smuzhiyun char *buf)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth);
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun static DEVICE_ATTR_RO(depth);
51*4882a593Smuzhiyun
ap_functions_show(struct device * dev,struct device_attribute * attr,char * buf)52*4882a593Smuzhiyun static ssize_t ap_functions_show(struct device *dev,
53*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "0x%08X\n", ac->functions);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static DEVICE_ATTR_RO(ap_functions);
61*4882a593Smuzhiyun
request_count_show(struct device * dev,struct device_attribute * attr,char * buf)62*4882a593Smuzhiyun static ssize_t request_count_show(struct device *dev,
63*4882a593Smuzhiyun struct device_attribute *attr,
64*4882a593Smuzhiyun char *buf)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
67*4882a593Smuzhiyun u64 req_cnt;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun req_cnt = 0;
70*4882a593Smuzhiyun spin_lock_bh(&ap_queues_lock);
71*4882a593Smuzhiyun req_cnt = atomic64_read(&ac->total_request_count);
72*4882a593Smuzhiyun spin_unlock_bh(&ap_queues_lock);
73*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
request_count_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)76*4882a593Smuzhiyun static ssize_t request_count_store(struct device *dev,
77*4882a593Smuzhiyun struct device_attribute *attr,
78*4882a593Smuzhiyun const char *buf, size_t count)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun int bkt;
81*4882a593Smuzhiyun struct ap_queue *aq;
82*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun spin_lock_bh(&ap_queues_lock);
85*4882a593Smuzhiyun hash_for_each(ap_queues, bkt, aq, hnode)
86*4882a593Smuzhiyun if (ac == aq->card)
87*4882a593Smuzhiyun aq->total_request_count = 0;
88*4882a593Smuzhiyun spin_unlock_bh(&ap_queues_lock);
89*4882a593Smuzhiyun atomic64_set(&ac->total_request_count, 0);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun return count;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun static DEVICE_ATTR_RW(request_count);
95*4882a593Smuzhiyun
requestq_count_show(struct device * dev,struct device_attribute * attr,char * buf)96*4882a593Smuzhiyun static ssize_t requestq_count_show(struct device *dev,
97*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun int bkt;
100*4882a593Smuzhiyun struct ap_queue *aq;
101*4882a593Smuzhiyun unsigned int reqq_cnt;
102*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun reqq_cnt = 0;
105*4882a593Smuzhiyun spin_lock_bh(&ap_queues_lock);
106*4882a593Smuzhiyun hash_for_each(ap_queues, bkt, aq, hnode)
107*4882a593Smuzhiyun if (ac == aq->card)
108*4882a593Smuzhiyun reqq_cnt += aq->requestq_count;
109*4882a593Smuzhiyun spin_unlock_bh(&ap_queues_lock);
110*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun static DEVICE_ATTR_RO(requestq_count);
114*4882a593Smuzhiyun
pendingq_count_show(struct device * dev,struct device_attribute * attr,char * buf)115*4882a593Smuzhiyun static ssize_t pendingq_count_show(struct device *dev,
116*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun int bkt;
119*4882a593Smuzhiyun struct ap_queue *aq;
120*4882a593Smuzhiyun unsigned int penq_cnt;
121*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun penq_cnt = 0;
124*4882a593Smuzhiyun spin_lock_bh(&ap_queues_lock);
125*4882a593Smuzhiyun hash_for_each(ap_queues, bkt, aq, hnode)
126*4882a593Smuzhiyun if (ac == aq->card)
127*4882a593Smuzhiyun penq_cnt += aq->pendingq_count;
128*4882a593Smuzhiyun spin_unlock_bh(&ap_queues_lock);
129*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static DEVICE_ATTR_RO(pendingq_count);
133*4882a593Smuzhiyun
modalias_show(struct device * dev,struct device_attribute * attr,char * buf)134*4882a593Smuzhiyun static ssize_t modalias_show(struct device *dev,
135*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "ap:t%02X\n",
138*4882a593Smuzhiyun to_ap_dev(dev)->device_type);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun static DEVICE_ATTR_RO(modalias);
142*4882a593Smuzhiyun
config_show(struct device * dev,struct device_attribute * attr,char * buf)143*4882a593Smuzhiyun static ssize_t config_show(struct device *dev,
144*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%d\n", ac->config ? 1 : 0);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
config_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)151*4882a593Smuzhiyun static ssize_t config_store(struct device *dev,
152*4882a593Smuzhiyun struct device_attribute *attr,
153*4882a593Smuzhiyun const char *buf, size_t count)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun int rc = 0, cfg;
156*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun if (sscanf(buf, "%d\n", &cfg) != 1 || cfg < 0 || cfg > 1)
159*4882a593Smuzhiyun return -EINVAL;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (cfg && !ac->config)
162*4882a593Smuzhiyun rc = sclp_ap_configure(ac->id);
163*4882a593Smuzhiyun else if (!cfg && ac->config)
164*4882a593Smuzhiyun rc = sclp_ap_deconfigure(ac->id);
165*4882a593Smuzhiyun if (rc)
166*4882a593Smuzhiyun return rc;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun ac->config = cfg ? true : false;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun return count;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun static DEVICE_ATTR_RW(config);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun static struct attribute *ap_card_dev_attrs[] = {
176*4882a593Smuzhiyun &dev_attr_hwtype.attr,
177*4882a593Smuzhiyun &dev_attr_raw_hwtype.attr,
178*4882a593Smuzhiyun &dev_attr_depth.attr,
179*4882a593Smuzhiyun &dev_attr_ap_functions.attr,
180*4882a593Smuzhiyun &dev_attr_request_count.attr,
181*4882a593Smuzhiyun &dev_attr_requestq_count.attr,
182*4882a593Smuzhiyun &dev_attr_pendingq_count.attr,
183*4882a593Smuzhiyun &dev_attr_modalias.attr,
184*4882a593Smuzhiyun &dev_attr_config.attr,
185*4882a593Smuzhiyun NULL
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun static struct attribute_group ap_card_dev_attr_group = {
189*4882a593Smuzhiyun .attrs = ap_card_dev_attrs
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun static const struct attribute_group *ap_card_dev_attr_groups[] = {
193*4882a593Smuzhiyun &ap_card_dev_attr_group,
194*4882a593Smuzhiyun NULL
195*4882a593Smuzhiyun };
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun static struct device_type ap_card_type = {
198*4882a593Smuzhiyun .name = "ap_card",
199*4882a593Smuzhiyun .groups = ap_card_dev_attr_groups,
200*4882a593Smuzhiyun };
201*4882a593Smuzhiyun
ap_card_device_release(struct device * dev)202*4882a593Smuzhiyun static void ap_card_device_release(struct device *dev)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun struct ap_card *ac = to_ap_card(dev);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun kfree(ac);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
ap_card_create(int id,int queue_depth,int raw_type,int comp_type,unsigned int functions)209*4882a593Smuzhiyun struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
210*4882a593Smuzhiyun int comp_type, unsigned int functions)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun struct ap_card *ac;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun ac = kzalloc(sizeof(*ac), GFP_KERNEL);
215*4882a593Smuzhiyun if (!ac)
216*4882a593Smuzhiyun return NULL;
217*4882a593Smuzhiyun ac->ap_dev.device.release = ap_card_device_release;
218*4882a593Smuzhiyun ac->ap_dev.device.type = &ap_card_type;
219*4882a593Smuzhiyun ac->ap_dev.device_type = comp_type;
220*4882a593Smuzhiyun ac->raw_hwtype = raw_type;
221*4882a593Smuzhiyun ac->queue_depth = queue_depth;
222*4882a593Smuzhiyun ac->functions = functions;
223*4882a593Smuzhiyun ac->id = id;
224*4882a593Smuzhiyun return ac;
225*4882a593Smuzhiyun }
226