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/sysctl.h>
  13#include <linux/proc_fs.h>
  14#include <linux/init.h>
  15#include <asm/uaccess.h>
  16
  17static const char frv_cache_wback[] = "wback";
  18static const char frv_cache_wthru[] = "wthru";
  19
  20static void frv_change_dcache_mode(unsigned long newmode)
  21{
  22        unsigned long flags, hsr0;
  23
  24        local_irq_save(flags);
  25
  26        hsr0 = __get_HSR(0);
  27        hsr0 &= ~HSR0_DCE;
  28        __set_HSR(0, hsr0);
  29
  30        asm volatile("  dcef    @(gr0,gr0),#1   \n"
  31                     "  membar                  \n"
  32                     : : : "memory"
  33                     );
  34
  35        hsr0 = (hsr0 & ~HSR0_CBM) | newmode;
  36        __set_HSR(0, hsr0);
  37        hsr0 |= HSR0_DCE;
  38        __set_HSR(0, hsr0);
  39
  40        local_irq_restore(flags);
  41
  42        //printk("HSR0 now %08lx\n", hsr0);
  43}
  44
  45/*****************************************************************************/
  46/*
  47 * handle requests to dynamically switch the write caching mode delivered by /proc
  48 */
  49static int procctl_frv_cachemode(struct ctl_table *table, int write,
  50                                 void __user *buffer, size_t *lenp,
  51                                 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 (*ppos > 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        *ppos = 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(struct ctl_table *table, int write,
 125                                void __user *buffer, size_t *lenp,
 126                                loff_t *ppos)
 127{
 128        pid_t pid;
 129        char buff[16], *p;
 130        int len;
 131
 132        len = *lenp;
 133
 134        if (write) {
 135                /* potential state change */
 136                if (len <= 1 || len > sizeof(buff) - 1)
 137                        return -EINVAL;
 138
 139                if (copy_from_user(buff, buffer, len) != 0)
 140                        return -EFAULT;
 141
 142                if (buff[len - 1] == '\n')
 143                        buff[len - 1] = '\0';
 144                else
 145                        buff[len] = '\0';
 146
 147                pid = simple_strtoul(buff, &p, 10);
 148                if (*p)
 149                        return -EINVAL;
 150
 151                return cxn_pin_by_pid(pid);
 152        }
 153
 154        /* read the currently pinned CXN */
 155        if (*ppos > 0) {
 156                *lenp = 0;
 157                return 0;
 158        }
 159
 160        len = snprintf(buff, sizeof(buff), "%d\n", cxn_pinned);
 161        if (len > *lenp)
 162                len = *lenp;
 163
 164        if (copy_to_user(buffer, buff, len) != 0)
 165                return -EFAULT;
 166
 167        *lenp = len;
 168        *ppos = len;
 169        return 0;
 170
 171} /* end procctl_frv_pin_cxnr() */
 172#endif
 173
 174/*
 175 * FR-V specific sysctls
 176 */
 177static struct ctl_table frv_table[] =
 178{
 179        {
 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                .procname       = "pin-cxnr",
 189                .data           = NULL,
 190                .maxlen         = 0,
 191                .mode           = 0644,
 192                .proc_handler   = procctl_frv_pin_cxnr
 193        },
 194#endif
 195        {}
 196};
 197
 198/*
 199 * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
 200 * when all the PM interfaces exist nicely.
 201 */
 202static struct ctl_table frv_dir_table[] =
 203{
 204        {
 205                .procname       = "frv",
 206                .mode           = 0555,
 207                .child          = frv_table
 208        },
 209        {}
 210};
 211
 212/*
 213 * Initialize power interface
 214 */
 215static int __init frv_sysctl_init(void)
 216{
 217        register_sysctl_table(frv_dir_table);
 218        return 0;
 219}
 220
 221__initcall(frv_sysctl_init);
 222