linux/arch/frv/kernel/sysctl.c
<<
>>
Prefs
   1/* sysctl.c: implementation of /proc/sys files relating to FRV specifically
   2 *
   3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/slab.h>
  13#include <linux/sysctl.h>
  14#include <linux/proc_fs.h>
  15#include <linux/init.h>
  16#include <asm/uaccess.h>
  17
  18static const char frv_cache_wback[] = "wback";
  19static const char frv_cache_wthru[] = "wthru";
  20
  21static void frv_change_dcache_mode(unsigned long newmode)
  22{
  23        unsigned long flags, hsr0;
  24
  25        local_irq_save(flags);
  26
  27        hsr0 = __get_HSR(0);
  28        hsr0 &= ~HSR0_DCE;
  29        __set_HSR(0, hsr0);
  30
  31        asm volatile("  dcef    @(gr0,gr0),#1   \n"
  32                     "  membar                  \n"
  33                     : : : "memory"
  34                     );
  35
  36        hsr0 = (hsr0 & ~HSR0_CBM) | newmode;
  37        __set_HSR(0, hsr0);
  38        hsr0 |= HSR0_DCE;
  39        __set_HSR(0, hsr0);
  40
  41        local_irq_restore(flags);
  42
  43        //printk("HSR0 now %08lx\n", hsr0);
  44}
  45
  46/*****************************************************************************/
  47/*
  48 * handle requests to dynamically switch the write caching mode delivered by /proc
  49 */
  50static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
  51                                 void __user *buffer, size_t *lenp, loff_t *ppos)
  52{
  53        unsigned long hsr0;
  54        char buff[8];
  55        int len;
  56
  57        len = *lenp;
  58
  59        if (write) {
  60                /* potential state change */
  61                if (len <= 1 || len > sizeof(buff) - 1)
  62                        return -EINVAL;
  63
  64                if (copy_from_user(buff, buffer, len) != 0)
  65                        return -EFAULT;
  66
  67                if (buff[len - 1] == '\n')
  68                        buff[len - 1] = '\0';
  69                else
  70                        buff[len] = '\0';
  71
  72                if (strcmp(buff, frv_cache_wback) == 0) {
  73                        /* switch dcache into write-back mode */
  74                        frv_change_dcache_mode(HSR0_CBM_COPY_BACK);
  75                        return 0;
  76                }
  77
  78                if (strcmp(buff, frv_cache_wthru) == 0) {
  79                        /* switch dcache into write-through mode */
  80                        frv_change_dcache_mode(HSR0_CBM_WRITE_THRU);
  81                        return 0;
  82                }
  83
  84                return -EINVAL;
  85        }
  86
  87        /* read the state */
  88        if (filp->f_pos > 0) {
  89                *lenp = 0;
  90                return 0;
  91        }
  92
  93        hsr0 = __get_HSR(0);
  94        switch (hsr0 & HSR0_CBM) {
  95        case HSR0_CBM_WRITE_THRU:
  96                memcpy(buff, frv_cache_wthru, sizeof(frv_cache_wthru) - 1);
  97                buff[sizeof(frv_cache_wthru) - 1] = '\n';
  98                len = sizeof(frv_cache_wthru);
  99                break;
 100        default:
 101                memcpy(buff, frv_cache_wback, sizeof(frv_cache_wback) - 1);
 102                buff[sizeof(frv_cache_wback) - 1] = '\n';
 103                len = sizeof(frv_cache_wback);
 104                break;
 105        }
 106
 107        if (len > *lenp)
 108                len = *lenp;
 109
 110        if (copy_to_user(buffer, buff, len) != 0)
 111                return -EFAULT;
 112
 113        *lenp = len;
 114        filp->f_pos = len;
 115        return 0;
 116
 117} /* end procctl_frv_cachemode() */
 118
 119/*****************************************************************************/
 120/*
 121 * permit the mm_struct the nominated process is using have its MMU context ID pinned
 122 */
 123#ifdef CONFIG_MMU
 124static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
 125                                void __user *buffer, size_t *lenp, loff_t *ppos)
 126{
 127        pid_t pid;
 128        char buff[16], *p;
 129        int len;
 130
 131        len = *lenp;
 132
 133        if (write) {
 134                /* potential state change */
 135                if (len <= 1 || len > sizeof(buff) - 1)
 136                        return -EINVAL;
 137
 138                if (copy_from_user(buff, buffer, len) != 0)
 139                        return -EFAULT;
 140
 141                if (buff[len - 1] == '\n')
 142                        buff[len - 1] = '\0';
 143                else
 144                        buff[len] = '\0';
 145
 146                pid = simple_strtoul(buff, &p, 10);
 147                if (*p)
 148                        return -EINVAL;
 149
 150                return cxn_pin_by_pid(pid);
 151        }
 152
 153        /* read the currently pinned CXN */
 154        if (filp->f_pos > 0) {
 155                *lenp = 0;
 156                return 0;
 157        }
 158
 159        len = snprintf(buff, sizeof(buff), "%d\n", cxn_pinned);
 160        if (len > *lenp)
 161                len = *lenp;
 162
 163        if (copy_to_user(buffer, buff, len) != 0)
 164                return -EFAULT;
 165
 166        *lenp = len;
 167        filp->f_pos = len;
 168        return 0;
 169
 170} /* end procctl_frv_pin_cxnr() */
 171#endif
 172
 173/*
 174 * FR-V specific sysctls
 175 */
 176static struct ctl_table frv_table[] =
 177{
 178        {
 179                .ctl_name       = 1,
 180                .procname       = "cache-mode",
 181                .data           = NULL,
 182                .maxlen         = 0,
 183                .mode           = 0644,
 184                .proc_handler   = &procctl_frv_cachemode,
 185        },
 186#ifdef CONFIG_MMU
 187        {
 188                .ctl_name       = 2,
 189                .procname       = "pin-cxnr",
 190                .data           = NULL,
 191                .maxlen         = 0,
 192                .mode           = 0644,
 193                .proc_handler   = &procctl_frv_pin_cxnr
 194        },
 195#endif
 196        {}
 197};
 198
 199/*
 200 * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
 201 * when all the PM interfaces exist nicely.
 202 */
 203static struct ctl_table frv_dir_table[] =
 204{
 205        {
 206                .ctl_name       = CTL_FRV,
 207                .procname       = "frv",
 208                .mode           = 0555,
 209                .child          = frv_table
 210        },
 211        {}
 212};
 213
 214/*
 215 * Initialize power interface
 216 */
 217static int __init frv_sysctl_init(void)
 218{
 219        register_sysctl_table(frv_dir_table);
 220        return 0;
 221}
 222
 223__initcall(frv_sysctl_init);
 224