Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  drivers/s390/char/sclp_cmd.c
  3  *
  4  *    Copyright IBM Corp. 2007
  5  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  6  *               Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  7  */
  8 
  9 #include <linux/completion.h>
 10 #include <linux/init.h>
 11 #include <linux/errno.h>
 12 #include <linux/slab.h>
 13 #include <linux/string.h>
 14 #include <asm/chpid.h>
 15 #include <asm/sclp.h>
 16 #include "sclp.h"
 17 
 18 #define TAG     "sclp_cmd: "
 19 
 20 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 21 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 22 
 23 struct read_info_sccb {
 24         struct  sccb_header header;     /* 0-7 */
 25         u16     rnmax;                  /* 8-9 */
 26         u8      rnsize;                 /* 10 */
 27         u8      _reserved0[24 - 11];    /* 11-15 */
 28         u8      loadparm[8];            /* 24-31 */
 29         u8      _reserved1[48 - 32];    /* 32-47 */
 30         u64     facilities;             /* 48-55 */
 31         u8      _reserved2[84 - 56];    /* 56-83 */
 32         u8      fac84;                  /* 84 */
 33         u8      _reserved3[91 - 85];    /* 85-90 */
 34         u8      flags;                  /* 91 */
 35         u8      _reserved4[100 - 92];   /* 92-99 */
 36         u32     rnsize2;                /* 100-103 */
 37         u64     rnmax2;                 /* 104-111 */
 38         u8      _reserved5[4096 - 112]; /* 112-4095 */
 39 } __attribute__((packed, aligned(PAGE_SIZE)));
 40 
 41 static struct read_info_sccb __initdata early_read_info_sccb;
 42 static int __initdata early_read_info_sccb_valid;
 43 
 44 u64 sclp_facilities;
 45 static u8 sclp_fac84;
 46 
 47 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
 48 {
 49         int rc;
 50 
 51         __ctl_set_bit(0, 9);
 52         rc = sclp_service_call(cmd, sccb);
 53         if (rc)
 54                 goto out;
 55         __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
 56                         PSW_MASK_WAIT | PSW_DEFAULT_KEY);
 57         local_irq_disable();
 58 out:
 59         /* Contents of the sccb might have changed. */
 60         barrier();
 61         __ctl_clear_bit(0, 9);
 62         return rc;
 63 }
 64 
 65 void __init sclp_read_info_early(void)
 66 {
 67         int rc;
 68         int i;
 69         struct read_info_sccb *sccb;
 70         sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
 71                                   SCLP_CMDW_READ_SCP_INFO};
 72 
 73         sccb = &early_read_info_sccb;
 74         for (i = 0; i < ARRAY_SIZE(commands); i++) {
 75                 do {
 76                         memset(sccb, 0, sizeof(*sccb));
 77                         sccb->header.length = sizeof(*sccb);
 78                         sccb->header.control_mask[2] = 0x80;
 79                         rc = sclp_cmd_sync_early(commands[i], sccb);
 80                 } while (rc == -EBUSY);
 81 
 82                 if (rc)
 83                         break;
 84                 if (sccb->header.response_code == 0x10) {
 85                         early_read_info_sccb_valid = 1;
 86                         break;
 87                 }
 88                 if (sccb->header.response_code != 0x1f0)
 89                         break;
 90         }
 91 }
 92 
 93 void __init sclp_facilities_detect(void)
 94 {
 95         if (!early_read_info_sccb_valid)
 96                 return;
 97         sclp_facilities = early_read_info_sccb.facilities;
 98         sclp_fac84 = early_read_info_sccb.fac84;
 99 }
100 
101 unsigned long long __init sclp_memory_detect(void)
102 {
103         unsigned long long memsize;
104         struct read_info_sccb *sccb;
105 
106         if (!early_read_info_sccb_valid)
107                 return 0;
108         sccb = &early_read_info_sccb;
109         if (sccb->rnsize)
110                 memsize = sccb->rnsize << 20;
111         else
112                 memsize = sccb->rnsize2 << 20;
113         if (sccb->rnmax)
114                 memsize *= sccb->rnmax;
115         else
116                 memsize *= sccb->rnmax2;
117         return memsize;
118 }
119 
120 /*
121  * This function will be called after sclp_memory_detect(), which gets called
122  * early from early.c code. Therefore the sccb should have valid contents.
123  */
124 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
125 {
126         struct read_info_sccb *sccb;
127 
128         if (!early_read_info_sccb_valid)
129                 return;
130         sccb = &early_read_info_sccb;
131         info->is_valid = 1;
132         if (sccb->flags & 0x2)
133                 info->has_dump = 1;
134         memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
135 }
136 
137 static void sclp_sync_callback(struct sclp_req *req, void *data)
138 {
139         struct completion *completion = data;
140 
141         complete(completion);
142 }
143 
144 static int do_sync_request(sclp_cmdw_t cmd, void *sccb)
145 {
146         struct completion completion;
147         struct sclp_req *request;
148         int rc;
149 
150         request = kzalloc(sizeof(*request), GFP_KERNEL);
151         if (!request)
152                 return -ENOMEM;
153         request->command = cmd;
154         request->sccb = sccb;
155         request->status = SCLP_REQ_FILLED;
156         request->callback = sclp_sync_callback;
157         request->callback_data = &completion;
158         init_completion(&completion);
159 
160         /* Perform sclp request. */
161         rc = sclp_add_request(request);
162         if (rc)
163                 goto out;
164         wait_for_completion(&completion);
165 
166         /* Check response. */
167         if (request->status != SCLP_REQ_DONE) {
168                 printk(KERN_WARNING TAG "sync request failed "
169                        "(cmd=0x%08x, status=0x%02x)\n", cmd, request->status);
170                 rc = -EIO;
171         }
172 out:
173         kfree(request);
174         return rc;
175 }
176 
177 /*
178  * CPU configuration related functions.
179  */
180 
181 #define SCLP_CMDW_READ_CPU_INFO         0x00010001
182 #define SCLP_CMDW_CONFIGURE_CPU         0x00110001
183 #define SCLP_CMDW_DECONFIGURE_CPU       0x00100001
184 
185 struct read_cpu_info_sccb {
186         struct  sccb_header header;
187         u16     nr_configured;
188         u16     offset_configured;
189         u16     nr_standby;
190         u16     offset_standby;
191         u8      reserved[4096 - 16];
192 } __attribute__((packed, aligned(PAGE_SIZE)));
193 
194 static void sclp_fill_cpu_info(struct sclp_cpu_info *info,
195                                struct read_cpu_info_sccb *sccb)
196 {
197         char *page = (char *) sccb;
198 
199         memset(info, 0, sizeof(*info));
200         info->configured = sccb->nr_configured;
201         info->standby = sccb->nr_standby;
202         info->combined = sccb->nr_configured + sccb->nr_standby;
203         info->has_cpu_type = sclp_fac84 & 0x1;
204         memcpy(&info->cpu, page + sccb->offset_configured,
205                info->combined * sizeof(struct sclp_cpu_entry));
206 }
207 
208 int sclp_get_cpu_info(struct sclp_cpu_info *info)
209 {
210         int rc;
211         struct read_cpu_info_sccb *sccb;
212 
213         if (!SCLP_HAS_CPU_INFO)
214                 return -EOPNOTSUPP;
215         sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
216         if (!sccb)
217                 return -ENOMEM;
218         sccb->header.length = sizeof(*sccb);
219         rc = do_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb);
220         if (rc)
221                 goto out;
222         if (sccb->header.response_code != 0x0010) {
223                 printk(KERN_WARNING TAG "readcpuinfo failed "
224                        "(response=0x%04x)\n", sccb->header.response_code);
225                 rc = -EIO;
226                 goto out;
227         }
228         sclp_fill_cpu_info(info, sccb);
229 out:
230         free_page((unsigned long) sccb);
231         return rc;
232 }
233 
234 struct cpu_configure_sccb {
235         struct sccb_header header;
236 } __attribute__((packed, aligned(8)));
237 
238 static int do_cpu_configure(sclp_cmdw_t cmd)
239 {
240         struct cpu_configure_sccb *sccb;
241         int rc;
242 
243         if (!SCLP_HAS_CPU_RECONFIG)
244                 return -EOPNOTSUPP;
245         /*
246          * This is not going to cross a page boundary since we force
247          * kmalloc to have a minimum alignment of 8 bytes on s390.
248          */
249         sccb = kzalloc(sizeof(*sccb), GFP_KERNEL | GFP_DMA);
250         if (!sccb)
251                 return -ENOMEM;
252         sccb->header.length = sizeof(*sccb);
253         rc = do_sync_request(cmd, sccb);
254         if (rc)
255                 goto out;
256         switch (sccb->header.response_code) {
257         case 0x0020:
258         case 0x0120:
259                 break;
260         default:
261                 printk(KERN_WARNING TAG "configure cpu failed (cmd=0x%08x, "
262                        "response=0x%04x)\n", cmd, sccb->header.response_code);
263                 rc = -EIO;
264                 break;
265         }
266 out:
267         kfree(sccb);
268         return rc;
269 }
270 
271 int sclp_cpu_configure(u8 cpu)
272 {
273         return do_cpu_configure(SCLP_CMDW_CONFIGURE_CPU | cpu << 8);
274 }
275 
276 int sclp_cpu_deconfigure(u8 cpu)
277 {
278         return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
279 }
280 
281 /*
282  * Channel path configuration related functions.
283  */
284 
285 #define SCLP_CMDW_CONFIGURE_CHPATH              0x000f0001
286 #define SCLP_CMDW_DECONFIGURE_CHPATH            0x000e0001
287 #define SCLP_CMDW_READ_CHPATH_INFORMATION       0x00030001
288 
289 struct chp_cfg_sccb {
290         struct sccb_header header;
291         u8 ccm;
292         u8 reserved[6];
293         u8 cssid;
294 } __attribute__((packed));
295 
296 static int do_chp_configure(sclp_cmdw_t cmd)
297 {
298         struct chp_cfg_sccb *sccb;
299         int rc;
300 
301         if (!SCLP_HAS_CHP_RECONFIG)
302                 return -EOPNOTSUPP;
303         /* Prepare sccb. */
304         sccb = (struct chp_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
305         if (!sccb)
306                 return -ENOMEM;
307         sccb->header.length = sizeof(*sccb);
308         rc = do_sync_request(cmd, sccb);
309         if (rc)
310                 goto out;
311         switch (sccb->header.response_code) {
312         case 0x0020:
313         case 0x0120:
314         case 0x0440:
315         case 0x0450:
316                 break;
317         default:
318                 printk(KERN_WARNING TAG "configure channel-path failed "
319                        "(cmd=0x%08x, response=0x%04x)\n", cmd,
320                        sccb->header.response_code);
321                 rc = -EIO;
322                 break;
323         }
324 out:
325         free_page((unsigned long) sccb);
326         return rc;
327 }
328 
329 /**
330  * sclp_chp_configure - perform configure channel-path sclp command
331  * @chpid: channel-path ID
332  *
333  * Perform configure channel-path command sclp command for specified chpid.
334  * Return 0 after command successfully finished, non-zero otherwise.
335  */
336 int sclp_chp_configure(struct chp_id chpid)
337 {
338         return do_chp_configure(SCLP_CMDW_CONFIGURE_CHPATH | chpid.id << 8);
339 }
340 
341 /**
342  * sclp_chp_deconfigure - perform deconfigure channel-path sclp command
343  * @chpid: channel-path ID
344  *
345  * Perform deconfigure channel-path command sclp command for specified chpid
346  * and wait for completion. On success return 0. Return non-zero otherwise.
347  */
348 int sclp_chp_deconfigure(struct chp_id chpid)
349 {
350         return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
351 }
352 
353 struct chp_info_sccb {
354         struct sccb_header header;
355         u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
356         u8 standby[SCLP_CHP_INFO_MASK_SIZE];
357         u8 configured[SCLP_CHP_INFO_MASK_SIZE];
358         u8 ccm;
359         u8 reserved[6];
360         u8 cssid;
361 } __attribute__((packed));
362 
363 /**
364  * sclp_chp_read_info - perform read channel-path information sclp command
365  * @info: resulting channel-path information data
366  *
367  * Perform read channel-path information sclp command and wait for completion.
368  * On success, store channel-path information in @info and return 0. Return
369  * non-zero otherwise.
370  */
371 int sclp_chp_read_info(struct sclp_chp_info *info)
372 {
373         struct chp_info_sccb *sccb;
374         int rc;
375 
376         if (!SCLP_HAS_CHP_INFO)
377                 return -EOPNOTSUPP;
378         /* Prepare sccb. */
379         sccb = (struct chp_info_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
380         if (!sccb)
381                 return -ENOMEM;
382         sccb->header.length = sizeof(*sccb);
383         rc = do_sync_request(SCLP_CMDW_READ_CHPATH_INFORMATION, sccb);
384         if (rc)
385                 goto out;
386         if (sccb->header.response_code != 0x0010) {
387                 printk(KERN_WARNING TAG "read channel-path info failed "
388                        "(response=0x%04x)\n", sccb->header.response_code);
389                 rc = -EIO;
390                 goto out;
391         }
392         memcpy(info->recognized, sccb->recognized, SCLP_CHP_INFO_MASK_SIZE);
393         memcpy(info->standby, sccb->standby, SCLP_CHP_INFO_MASK_SIZE);
394         memcpy(info->configured, sccb->configured, SCLP_CHP_INFO_MASK_SIZE);
395 out:
396         free_page((unsigned long) sccb);
397         return rc;
398 }
399 
  This page was automatically generated by the LXR engine.