]>
Commit | Line | Data |
---|---|---|
e28d2af4 IT |
1 | /* |
2 | * Copyright IBM Corp. 2016 | |
3 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | |
4 | * | |
5 | * Adjunct processor bus, card related code. | |
6 | */ | |
7 | ||
8 | #define KMSG_COMPONENT "ap" | |
9 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
10 | ||
11 | #include <linux/init.h> | |
12 | #include <linux/slab.h> | |
13 | #include <asm/facility.h> | |
14 | ||
15 | #include "ap_bus.h" | |
16 | #include "ap_asm.h" | |
17 | ||
18 | /* | |
19 | * AP card related attributes. | |
20 | */ | |
21 | static ssize_t ap_hwtype_show(struct device *dev, | |
22 | struct device_attribute *attr, char *buf) | |
23 | { | |
24 | struct ap_card *ac = to_ap_card(dev); | |
25 | ||
26 | return snprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type); | |
27 | } | |
28 | ||
29 | static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL); | |
30 | ||
31 | static ssize_t ap_raw_hwtype_show(struct device *dev, | |
32 | struct device_attribute *attr, char *buf) | |
33 | { | |
34 | struct ap_card *ac = to_ap_card(dev); | |
35 | ||
36 | return snprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype); | |
37 | } | |
38 | ||
39 | static DEVICE_ATTR(raw_hwtype, 0444, ap_raw_hwtype_show, NULL); | |
40 | ||
41 | static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr, | |
42 | char *buf) | |
43 | { | |
44 | struct ap_card *ac = to_ap_card(dev); | |
45 | ||
46 | return snprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth); | |
47 | } | |
48 | ||
49 | static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL); | |
50 | ||
51 | static ssize_t ap_functions_show(struct device *dev, | |
52 | struct device_attribute *attr, char *buf) | |
53 | { | |
54 | struct ap_card *ac = to_ap_card(dev); | |
55 | ||
56 | return snprintf(buf, PAGE_SIZE, "0x%08X\n", ac->functions); | |
57 | } | |
58 | ||
59 | static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL); | |
60 | ||
d0360d7b HF |
61 | static ssize_t ap_req_count_show(struct device *dev, |
62 | struct device_attribute *attr, | |
63 | char *buf) | |
e28d2af4 IT |
64 | { |
65 | struct ap_card *ac = to_ap_card(dev); | |
e28d2af4 IT |
66 | unsigned int req_cnt; |
67 | ||
68 | req_cnt = 0; | |
69 | spin_lock_bh(&ap_list_lock); | |
e47de21d | 70 | req_cnt = atomic_read(&ac->total_request_count); |
e28d2af4 IT |
71 | spin_unlock_bh(&ap_list_lock); |
72 | return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); | |
73 | } | |
74 | ||
d0360d7b HF |
75 | static ssize_t ap_req_count_store(struct device *dev, |
76 | struct device_attribute *attr, | |
77 | const char *buf, size_t count) | |
78 | { | |
79 | struct ap_card *ac = to_ap_card(dev); | |
80 | struct ap_queue *aq; | |
81 | ||
82 | spin_lock_bh(&ap_list_lock); | |
83 | for_each_ap_queue(aq, ac) | |
84 | aq->total_request_count = 0; | |
85 | spin_unlock_bh(&ap_list_lock); | |
86 | atomic_set(&ac->total_request_count, 0); | |
87 | ||
88 | return count; | |
89 | } | |
90 | ||
91 | static DEVICE_ATTR(request_count, 0644, ap_req_count_show, ap_req_count_store); | |
e28d2af4 IT |
92 | |
93 | static ssize_t ap_requestq_count_show(struct device *dev, | |
94 | struct device_attribute *attr, char *buf) | |
95 | { | |
96 | struct ap_card *ac = to_ap_card(dev); | |
97 | struct ap_queue *aq; | |
98 | unsigned int reqq_cnt; | |
99 | ||
100 | reqq_cnt = 0; | |
101 | spin_lock_bh(&ap_list_lock); | |
102 | for_each_ap_queue(aq, ac) | |
103 | reqq_cnt += aq->requestq_count; | |
104 | spin_unlock_bh(&ap_list_lock); | |
105 | return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt); | |
106 | } | |
107 | ||
108 | static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL); | |
109 | ||
110 | static ssize_t ap_pendingq_count_show(struct device *dev, | |
111 | struct device_attribute *attr, char *buf) | |
112 | { | |
113 | struct ap_card *ac = to_ap_card(dev); | |
114 | struct ap_queue *aq; | |
115 | unsigned int penq_cnt; | |
116 | ||
117 | penq_cnt = 0; | |
118 | spin_lock_bh(&ap_list_lock); | |
119 | for_each_ap_queue(aq, ac) | |
120 | penq_cnt += aq->pendingq_count; | |
121 | spin_unlock_bh(&ap_list_lock); | |
122 | return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt); | |
123 | } | |
124 | ||
125 | static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL); | |
126 | ||
127 | static ssize_t ap_modalias_show(struct device *dev, | |
128 | struct device_attribute *attr, char *buf) | |
129 | { | |
130 | return sprintf(buf, "ap:t%02X\n", to_ap_dev(dev)->device_type); | |
131 | } | |
132 | ||
133 | static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL); | |
134 | ||
135 | static struct attribute *ap_card_dev_attrs[] = { | |
136 | &dev_attr_hwtype.attr, | |
137 | &dev_attr_raw_hwtype.attr, | |
138 | &dev_attr_depth.attr, | |
139 | &dev_attr_ap_functions.attr, | |
140 | &dev_attr_request_count.attr, | |
141 | &dev_attr_requestq_count.attr, | |
142 | &dev_attr_pendingq_count.attr, | |
143 | &dev_attr_modalias.attr, | |
144 | NULL | |
145 | }; | |
146 | ||
147 | static struct attribute_group ap_card_dev_attr_group = { | |
148 | .attrs = ap_card_dev_attrs | |
149 | }; | |
150 | ||
151 | static const struct attribute_group *ap_card_dev_attr_groups[] = { | |
152 | &ap_card_dev_attr_group, | |
153 | NULL | |
154 | }; | |
155 | ||
227374b1 | 156 | static struct device_type ap_card_type = { |
e28d2af4 IT |
157 | .name = "ap_card", |
158 | .groups = ap_card_dev_attr_groups, | |
159 | }; | |
160 | ||
161 | static void ap_card_device_release(struct device *dev) | |
162 | { | |
e3850508 HF |
163 | struct ap_card *ac = to_ap_card(dev); |
164 | ||
165 | if (!list_empty(&ac->list)) { | |
166 | spin_lock_bh(&ap_list_lock); | |
167 | list_del_init(&ac->list); | |
168 | spin_unlock_bh(&ap_list_lock); | |
169 | } | |
170 | kfree(ac); | |
e28d2af4 IT |
171 | } |
172 | ||
173 | struct ap_card *ap_card_create(int id, int queue_depth, int device_type, | |
174 | unsigned int functions) | |
175 | { | |
176 | struct ap_card *ac; | |
177 | ||
178 | ac = kzalloc(sizeof(*ac), GFP_KERNEL); | |
179 | if (!ac) | |
180 | return NULL; | |
181 | INIT_LIST_HEAD(&ac->queues); | |
182 | ac->ap_dev.device.release = ap_card_device_release; | |
183 | ac->ap_dev.device.type = &ap_card_type; | |
184 | ac->ap_dev.device_type = device_type; | |
185 | /* CEX6 toleration: map to CEX5 */ | |
186 | if (device_type == AP_DEVICE_TYPE_CEX6) | |
187 | ac->ap_dev.device_type = AP_DEVICE_TYPE_CEX5; | |
188 | ac->raw_hwtype = device_type; | |
189 | ac->queue_depth = queue_depth; | |
190 | ac->functions = functions; | |
191 | ac->id = id; | |
192 | return ac; | |
193 | } |