aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2013-06-05 12:58:35 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-06-26 15:10:14 -0400
commitda5b6cb162b6bef39d76446a5e015d6a111459b1 (patch)
treedae7bc447358be3c4f2a25e27c9a2d2bf1e1034b /drivers/s390
parentd475f942b1dd6a897dac3ad4ed98d6994b275378 (diff)
s390/qdio: cleanup chsc SSQD usage
Cleanup the function qdio_setup_get_ssqd. Fix some possible memleaks and an unchecked allocation and create a wrapper for SSQD in chsc.c . Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/chsc.c23
-rw-r--r--drivers/s390/cio/chsc.h17
-rw-r--r--drivers/s390/cio/qdio.h14
-rw-r--r--drivers/s390/cio/qdio_setup.c47
4 files changed, 58 insertions, 43 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 8ea7d9b2c671..d119d0d87e9b 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -144,6 +144,29 @@ out:
144 return ret; 144 return ret;
145} 145}
146 146
147/**
148 * chsc_ssqd() - store subchannel QDIO data (SSQD)
149 * @schid: id of the subchannel on which SSQD is performed
150 * @ssqd: request and response block for SSQD
151 *
152 * Returns 0 on success.
153 */
154int chsc_ssqd(struct subchannel_id schid, struct chsc_ssqd_area *ssqd)
155{
156 memset(ssqd, 0, sizeof(*ssqd));
157 ssqd->request.length = 0x0010;
158 ssqd->request.code = 0x0024;
159 ssqd->first_sch = schid.sch_no;
160 ssqd->last_sch = schid.sch_no;
161 ssqd->ssid = schid.ssid;
162
163 if (chsc(ssqd))
164 return -EIO;
165
166 return chsc_error_from_response(ssqd->response.code);
167}
168EXPORT_SYMBOL_GPL(chsc_ssqd);
169
147static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data) 170static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
148{ 171{
149 spin_lock_irq(sch->lock); 172 spin_lock_irq(sch->lock);
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 62d096f11e65..2b88e74e6b65 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -7,6 +7,7 @@
7#include <asm/chpid.h> 7#include <asm/chpid.h>
8#include <asm/chsc.h> 8#include <asm/chsc.h>
9#include <asm/schid.h> 9#include <asm/schid.h>
10#include <asm/qdio.h>
10 11
11#define CHSC_SDA_OC_MSS 0x2 12#define CHSC_SDA_OC_MSS 0x2
12 13
@@ -72,6 +73,20 @@ struct chsc_ssd_info {
72 u16 fla[8]; 73 u16 fla[8];
73}; 74};
74 75
76struct chsc_ssqd_area {
77 struct chsc_header request;
78 u16:10;
79 u8 ssid:2;
80 u8 fmt:4;
81 u16 first_sch;
82 u16:16;
83 u16 last_sch;
84 u32:32;
85 struct chsc_header response;
86 u32:32;
87 struct qdio_ssqd_desc qdio_ssqd;
88} __packed;
89
75struct chsc_scpd { 90struct chsc_scpd {
76 struct chsc_header request; 91 struct chsc_header request;
77 u32:2; 92 u32:2;
@@ -111,7 +126,7 @@ int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
111void chsc_chp_online(struct chp_id chpid); 126void chsc_chp_online(struct chp_id chpid);
112void chsc_chp_offline(struct chp_id chpid); 127void chsc_chp_offline(struct chp_id chpid);
113int chsc_get_channel_measurement_chars(struct channel_path *chp); 128int chsc_get_channel_measurement_chars(struct channel_path *chp);
114 129int chsc_ssqd(struct subchannel_id schid, struct chsc_ssqd_area *ssqd);
115int chsc_error_from_response(int response); 130int chsc_error_from_response(int response);
116 131
117int chsc_siosl(struct subchannel_id schid); 132int chsc_siosl(struct subchannel_id schid);
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 5132554d7917..b8bda2175b6c 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -140,20 +140,6 @@ struct siga_flag {
140 u8:3; 140 u8:3;
141} __attribute__ ((packed)); 141} __attribute__ ((packed));
142 142
143struct chsc_ssqd_area {
144 struct chsc_header request;
145 u16:10;
146 u8 ssid:2;
147 u8 fmt:4;
148 u16 first_sch;
149 u16:16;
150 u16 last_sch;
151 u32:32;
152 struct chsc_header response;
153 u32:32;
154 struct qdio_ssqd_desc qdio_ssqd;
155} __attribute__ ((packed));
156
157struct scssc_area { 143struct scssc_area {
158 struct chsc_header request; 144 struct chsc_header request;
159 u16 operation_code; 145 u16 operation_code;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 16ecd35b8e51..f5f4a91fab44 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -254,40 +254,31 @@ int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
254 int rc; 254 int rc;
255 255
256 DBF_EVENT("getssqd:%4x", schid->sch_no); 256 DBF_EVENT("getssqd:%4x", schid->sch_no);
257 if (irq_ptr != NULL) 257 if (!irq_ptr) {
258 ssqd = (struct chsc_ssqd_area *)irq_ptr->chsc_page;
259 else
260 ssqd = (struct chsc_ssqd_area *)__get_free_page(GFP_KERNEL); 258 ssqd = (struct chsc_ssqd_area *)__get_free_page(GFP_KERNEL);
261 memset(ssqd, 0, PAGE_SIZE); 259 if (!ssqd)
262 260 return -ENOMEM;
263 ssqd->request = (struct chsc_header) { 261 } else {
264 .length = 0x0010, 262 ssqd = (struct chsc_ssqd_area *)irq_ptr->chsc_page;
265 .code = 0x0024, 263 }
266 }; 264
267 ssqd->first_sch = schid->sch_no; 265 rc = chsc_ssqd(*schid, ssqd);
268 ssqd->last_sch = schid->sch_no;
269 ssqd->ssid = schid->ssid;
270
271 if (chsc(ssqd))
272 return -EIO;
273 rc = chsc_error_from_response(ssqd->response.code);
274 if (rc) 266 if (rc)
275 return rc; 267 goto out;
276 268
277 if (!(ssqd->qdio_ssqd.flags & CHSC_FLAG_QDIO_CAPABILITY) || 269 if (!(ssqd->qdio_ssqd.flags & CHSC_FLAG_QDIO_CAPABILITY) ||
278 !(ssqd->qdio_ssqd.flags & CHSC_FLAG_VALIDITY) || 270 !(ssqd->qdio_ssqd.flags & CHSC_FLAG_VALIDITY) ||
279 (ssqd->qdio_ssqd.sch != schid->sch_no)) 271 (ssqd->qdio_ssqd.sch != schid->sch_no))
280 return -EINVAL; 272 rc = -EINVAL;
281 273
282 if (irq_ptr != NULL) 274 if (!rc)
283 memcpy(&irq_ptr->ssqd_desc, &ssqd->qdio_ssqd, 275 memcpy(data, &ssqd->qdio_ssqd, sizeof(*data));
284 sizeof(struct qdio_ssqd_desc)); 276
285 else { 277out:
286 memcpy(data, &ssqd->qdio_ssqd, 278 if (!irq_ptr)
287 sizeof(struct qdio_ssqd_desc));
288 free_page((unsigned long)ssqd); 279 free_page((unsigned long)ssqd);
289 } 280
290 return 0; 281 return rc;
291} 282}
292 283
293void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr) 284void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr)
@@ -295,7 +286,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr)
295 unsigned char qdioac; 286 unsigned char qdioac;
296 int rc; 287 int rc;
297 288
298 rc = qdio_setup_get_ssqd(irq_ptr, &irq_ptr->schid, NULL); 289 rc = qdio_setup_get_ssqd(irq_ptr, &irq_ptr->schid, &irq_ptr->ssqd_desc);
299 if (rc) { 290 if (rc) {
300 DBF_ERROR("%4x ssqd ERR", irq_ptr->schid.sch_no); 291 DBF_ERROR("%4x ssqd ERR", irq_ptr->schid.sch_no);
301 DBF_ERROR("rc:%x", rc); 292 DBF_ERROR("rc:%x", rc);