00001
00005 #include "qres_config.h"
00006 #define QOS_DEBUG_LEVEL QRES_MOD_DEBUG_LEVEL
00007 #include <linux/aquosa/qos_debug.h>
00008 #include "qsup_gw_ks.h"
00009 #include "qres_proc_fs.h"
00010
00011 #ifdef PROF_QRES_MOD_DEV
00012 # define QOS_PROFILE
00013 #endif
00014 #include <linux/aquosa/qos_prof.h>
00015
00016 #include <linux/init.h>
00017 #include <linux/fs.h>
00018 #include <asm/uaccess.h>
00019 #include <asm/processor.h>
00020
00021 #include "qres_gw_ks.h"
00022 #include "qsup_mod.h"
00023
00024 #include <linux/aquosa/qos_kernel_dep.h>
00025
00026 #define SUCCESS 0
00027 #define BUF_LEN 80
00028 #define DEBUG
00029
00034 static int Device_Open = 0;
00035
00036
00037
00038
00039 static char Message[BUF_LEN];
00040
00041
00042
00043
00044
00045
00046 static char *Message_Ptr;
00047
00048
00049
00050
00051 static int device_open(struct inode *inode, struct file *file) {
00052 qos_log_debug("device_open(%p)", file);
00053
00054 Device_Open++;
00055
00056
00057
00058 Message_Ptr = Message;
00059
00060 KERN_INCREMENT;
00061
00062 return SUCCESS;
00063 }
00064
00070 static int device_release(struct inode *inode, struct file *file)
00071 {
00072 qos_log_debug("device_release(%p,%p)", inode, file);
00073
00074
00075
00076 Device_Open--;
00077
00078 KERN_DECREMENT;
00079
00080 return SUCCESS;
00081 }
00082
00083
00084
00085
00086
00087 static ssize_t device_read(struct file *file,
00088 char __user * buffer,
00089
00090 size_t length,
00091 loff_t * offset)
00092 {
00093
00094
00095
00096 int bytes_read = 0;
00097
00098 qos_log_debug("device_read(%p,%p,%zu)", file, buffer, length);
00099
00100
00101
00102
00103
00104 if (*Message_Ptr == 0)
00105 return 0;
00106
00107
00108
00109
00110 while (length && *Message_Ptr) {
00111
00112
00113
00114
00115
00116
00117
00118
00119 put_user(*(Message_Ptr++), buffer++);
00120 length--;
00121 bytes_read++;
00122 }
00123
00124 qos_log_debug("Read %d bytes, %zu left", bytes_read, length);
00125
00126
00127
00128
00129
00130 return bytes_read;
00131 }
00132
00133
00134
00135
00136
00137 static ssize_t
00138 device_write(struct file *file,
00139 const char __user * buffer, size_t length, loff_t * offset)
00140 {
00141 int i;
00142 qos_log_debug("device_write(%p,%s,%zu)", file, buffer, length);
00143
00144 for (i = 0; i < length && i < BUF_LEN; i++)
00145 get_user(Message[i], buffer + i);
00146
00147 Message_Ptr = Message;
00148
00149
00150
00151
00152 return i;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 int device_ioctl(struct inode *inode,
00166 struct file *file,
00167 unsigned int ioctl_num,
00168 unsigned long ioctl_param)
00169 {
00170 qos_rv err;
00171
00172 err = qres_gw_ks(_IOC_NR(ioctl_num), (void *) ioctl_param,
00173 _IOC_SIZE(ioctl_num));
00174 qos_log_debug("Returning %d (%s)", qos_rv_int(err), qos_strerror(err));
00175 return qos_rv_int(err);
00176 }
00177
00178
00179
00188 struct file_operations Fops = {
00189 .read = device_read,
00190 .write = device_write,
00191 .ioctl = device_ioctl,
00192 .open = device_open,
00193 .release = device_release,
00194 };
00195
00196 static qos_dev_info_t qres_dev_info;
00197
00198 #ifdef QSUP_DYNAMIC_RECLAIM
00199 static void (*old_block_hook)(struct task_struct *t) = 0;
00200 static void (*old_unblock_hook)(struct task_struct *t, long old_state) = 0;
00201 static void (*old_stop_hook)(struct task_struct *t) = 0;
00202 static void (*old_continue_hook)(struct task_struct *t, long old_state) = 0;
00203
00204 void qres_block_hook(struct task_struct *t) {
00205 kal_irq_state flags;
00206 server_t *rres;
00207
00208 old_block_hook(t);
00209 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00210 rres = rres_find_by_task(t);
00211 if (rres && ! rres_has_ready_tasks(rres)) {
00212 qres_server_t *qres = qres_find_by_rres(rres);
00213
00214 if (qres->params.Q > qres->params.Q_min)
00215 qsup_set_required_bw(&qres->qsup, qres->params.Q_min);
00216
00217 }
00218 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00219 }
00220
00221 void qres_unblock_hook(struct task_struct *t, long old_state) {
00222 kal_irq_state flags;
00223 server_t *rres;
00224
00225 old_unblock_hook(t, old_state);
00226 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00227 rres = rres_find_by_task(t);
00228 if (rres && rres_has_ready_tasks(rres)) {
00229 qres_server_t *qres = qres_find_by_rres(rres);
00230 qsup_set_required_bw(&qres->qsup, r2bw(qres->params.Q, qres->params.P));
00231 }
00232 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00233 }
00234
00235 void qres_stop_hook(struct task_struct *t) {
00236 kal_irq_state flags;
00237 server_t *rres;
00238
00239 old_stop_hook(t);
00240 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00241 rres = rres_find_by_task(t);
00242 if (rres && ! rres_has_ready_tasks(rres)) {
00243 qres_server_t *qres = qres_find_by_rres(rres);
00244 qsup_set_required_bw(&qres->qsup, 0);
00245 }
00246 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00247 }
00248
00249 void qres_continue_hook(struct task_struct *t, long old_state) {
00250 kal_irq_state flags;
00251 server_t *rres;
00252
00253 old_continue_hook(t, old_state);
00254 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00255 rres = rres_find_by_task(t);
00256 if (rres && rres_has_ready_tasks(rres)) {
00257 qres_server_t *qres = qres_find_by_rres(rres);
00258 qsup_set_required_bw(&qres->qsup, r2bw(qres->params.Q, qres->params.P));
00259 }
00260 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00261 }
00262 #endif
00263
00265 static int qres_init_module(void) {
00266 qos_rv rv;
00267 kal_irq_state flags;
00268
00269 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00270
00271 qres_init();
00272 qos_log_debug("Initing QSUP");
00273 if ((rv = qsup_init_ks()) != QOS_OK) {
00274 qos_log_crit("qsup_init_ks() failed: %s", qos_strerror(rv));
00275 qres_cleanup();
00276 goto err;
00277 }
00278
00279
00280
00281 #ifdef QSUP_DYNAMIC_RECLAIM
00282 write_lock(&hook_lock);
00283 old_block_hook = block_hook;
00284 old_unblock_hook = unblock_hook;
00285 old_stop_hook = stop_hook;
00286 old_continue_hook = continue_hook;
00287 block_hook = qres_block_hook;
00288 unblock_hook = qres_unblock_hook;
00289 stop_hook = qres_stop_hook;
00290 continue_hook = qres_continue_hook;
00291 write_unlock(&hook_lock);
00292 #endif
00293
00294 qos_log_debug("qres module initialization finished");
00295
00296 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00297
00298
00299
00300
00301
00302 if (qos_dev_register(&qres_dev_info, QRES_DEV_NAME, QRES_MAJOR_NUM, &Fops) != QOS_OK) {
00303 qos_log_crit("Registration of device %s failed", QRES_DEV_NAME);
00304 } else {
00305 qos_log_info("Registered QRES device with major device number %d.", MAJOR(qres_dev_info.dev_num));
00306 qos_log_info("If you want to talk to the device driver,");
00307 qos_log_info("you'll have to create a device file. ");
00308 qos_log_info("We suggest you use:");
00309 qos_log_info("mknod %s c %d 0", QRES_DEV_NAME, MAJOR(qres_dev_info.dev_num));
00310 }
00311
00312 qsup_dev_register();
00313
00315 if (qres_proc_register())
00316 qos_log_err("Failed to register qres module in /proc filesystem");
00317
00318 return 0;
00319
00320 err:
00321
00322 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00323 return -1;
00324 }
00325
00327 static void qres_cleanup_module(void) {
00328 kal_irq_state flags;
00329 qos_rv ret;
00330
00331 qres_proc_unregister();
00332
00333
00334
00335
00336 qos_dev_unregister(&qres_dev_info);
00337 qsup_dev_unregister();
00338
00339 kal_spin_lock_irqsave(rres_get_spinlock(), &flags);
00340
00341 #ifdef QSUP_DYNAMIC_RECLAIM
00342 write_lock(&hook_lock);
00343 block_hook = old_block_hook;
00344 unblock_hook = old_unblock_hook;
00345 stop_hook = old_stop_hook;
00346 continue_hook = old_continue_hook;
00347 write_unlock(&hook_lock);
00348 #endif
00349
00350 ret = qres_cleanup();
00351 if (ret != QOS_OK) {
00352 qos_log_crit("Error in qres_cleanup_ks(): %s", qos_strerror(ret));
00353 goto err;
00354 }
00355
00356 qsup_cleanup();
00357
00358
00359
00360 err:
00361
00362 kal_spin_unlock_irqrestore(rres_get_spinlock(), &flags);
00363 }
00364
00365 module_init(qres_init_module);
00366 module_exit(qres_cleanup_module);
00367
00368 MODULE_LICENSE("GPL");
00369 MODULE_AUTHOR("ReTiS Lab");
00370 MODULE_DESCRIPTION("AQuoSA Resource Reservation - Support for user-space library and supervisor");
00371 MODULE_SUPPORTED_DEVICE("qosres");