aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-proc.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
commit8185d5aa93e0a5c111adc4952a5b87193a68ae5b (patch)
tree431aeb09a448b7b07a353e12f4fe931ebb8555cd /drivers/ide/ide-proc.c
parent263138a0ad6e38de7f6526b7de037ed4511308ef (diff)
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros. * Add 'const struct ide_devset **settings' to ide_driver_t. * Use 'const struct ide_devset **settings' in ide_drive_t instead of 'struct ide_settings_s *settings'. Then convert core code and device drivers to use struct ide_devset and co.: - device settings are no longer allocated dynamically for each device but instead there is an unique struct ide_devset instance per setting - device driver keeps the pointer to the table of pointers to its settings in ide_driver_t.settings - generic settings are kept in ide_generic_setting[] - ide_proc_[un]register_driver(), ide_find_setting_by_name(), ide_{read,write}_setting() and proc_ide_{read,write}_settings() are updated accordingly - ide*_add_settings() are removed * Remove no longer used __ide_add_setting(), ide_add_setting(), __ide_remove_setting() and auto_remove_settings(). * Remove no longer used TYPE_*, SETTING_*, ide_procset_t and ide_settings_t. * ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap, ->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields can now be bitfield flags. While at it: * Rename ide_find_setting_by_name() to ide_find_setting(). * Rename write_wcache() to set_wcache(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-proc.c')
-rw-r--r--drivers/ide/ide-proc.c279
1 files changed, 87 insertions, 192 deletions
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 7a64aedfa648..5634b3971d21 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -114,140 +114,24 @@ static int proc_ide_read_identify
114} 114}
115 115
116/** 116/**
117 * __ide_add_setting - add an ide setting option 117 * ide_find_setting - find a specific setting
118 * @drive: drive to use 118 * @st: setting table pointer
119 * @name: setting name 119 * @name: setting name
120 * @rw: true if the function is read write
121 * @data_type: type of data
122 * @min: range minimum
123 * @max: range maximum
124 * @mul_factor: multiplication scale
125 * @div_factor: divison scale
126 * @data: private data field
127 * @set: setting
128 * @auto_remove: setting auto removal flag
129 * 120 *
130 * Removes the setting named from the device if it is present. 121 * Scan's the setting table for a matching entry and returns
131 * The function takes the settings_lock to protect against
132 * parallel changes. This function must not be called from IRQ
133 * context. Returns 0 on success or -1 on failure.
134 *
135 * BUGS: This code is seriously over-engineered. There is also
136 * magic about how the driver specific features are setup. If
137 * a driver is attached we assume the driver settings are auto
138 * remove.
139 */
140
141static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
142{
143 ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
144
145 mutex_lock(&ide_setting_mtx);
146 while ((*p) && strcmp((*p)->name, name) < 0)
147 p = &((*p)->next);
148 if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
149 goto abort;
150 if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
151 goto abort;
152 strcpy(setting->name, name);
153 setting->rw = rw;
154 setting->data_type = data_type;
155 setting->min = min;
156 setting->max = max;
157 setting->mul_factor = mul_factor;
158 setting->div_factor = div_factor;
159 setting->data = data;
160 setting->set = set;
161
162 setting->next = *p;
163 if (auto_remove)
164 setting->auto_remove = 1;
165 *p = setting;
166 mutex_unlock(&ide_setting_mtx);
167 return 0;
168abort:
169 mutex_unlock(&ide_setting_mtx);
170 kfree(setting);
171 return -1;
172}
173
174int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
175{
176 return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
177}
178
179EXPORT_SYMBOL(ide_add_setting);
180
181/**
182 * __ide_remove_setting - remove an ide setting option
183 * @drive: drive to use
184 * @name: setting name
185 *
186 * Removes the setting named from the device if it is present.
187 * The caller must hold the setting semaphore.
188 */
189
190static void __ide_remove_setting(ide_drive_t *drive, char *name)
191{
192 ide_settings_t **p, *setting;
193
194 p = (ide_settings_t **) &drive->settings;
195
196 while ((*p) && strcmp((*p)->name, name))
197 p = &((*p)->next);
198 setting = (*p);
199 if (setting == NULL)
200 return;
201
202 (*p) = setting->next;
203
204 kfree(setting->name);
205 kfree(setting);
206}
207
208/**
209 * auto_remove_settings - remove driver specific settings
210 * @drive: drive
211 *
212 * Automatically remove all the driver specific settings for this
213 * drive. This function may not be called from IRQ context. The
214 * caller must hold ide_setting_mtx.
215 */
216
217static void auto_remove_settings(ide_drive_t *drive)
218{
219 ide_settings_t *setting;
220repeat:
221 setting = drive->settings;
222 while (setting) {
223 if (setting->auto_remove) {
224 __ide_remove_setting(drive, setting->name);
225 goto repeat;
226 }
227 setting = setting->next;
228 }
229}
230
231/**
232 * ide_find_setting_by_name - find a drive specific setting
233 * @drive: drive to scan
234 * @name: setting name
235 *
236 * Scan's the device setting table for a matching entry and returns
237 * this or NULL if no entry is found. The caller must hold the 122 * this or NULL if no entry is found. The caller must hold the
238 * setting semaphore 123 * setting semaphore
239 */ 124 */
240 125
241static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) 126static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
127 char *name)
242{ 128{
243 ide_settings_t *setting = drive->settings; 129 while (*st) {
244 130 if (strcmp((*st)->name, name) == 0)
245 while (setting) {
246 if (strcmp(setting->name, name) == 0)
247 break; 131 break;
248 setting = setting->next; 132 st++;
249 } 133 }
250 return setting; 134 return *st;
251} 135}
252 136
253/** 137/**
@@ -263,26 +147,19 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
263 * be told apart 147 * be told apart
264 */ 148 */
265 149
266static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) 150static int ide_read_setting(ide_drive_t *drive,
151 const struct ide_devset *setting)
267{ 152{
268 int val = -EINVAL; 153 int val = -EINVAL;
269 unsigned long flags; 154
155 if ((setting->flags & S_READ)) {
156 unsigned long flags;
270 157
271 if ((setting->rw & SETTING_READ)) {
272 spin_lock_irqsave(&ide_lock, flags); 158 spin_lock_irqsave(&ide_lock, flags);
273 switch (setting->data_type) { 159 val = setting->get(drive);
274 case TYPE_BYTE:
275 val = *((u8 *) setting->data);
276 break;
277 case TYPE_SHORT:
278 val = *((u16 *) setting->data);
279 break;
280 case TYPE_INT:
281 val = *((u32 *) setting->data);
282 break;
283 }
284 spin_unlock_irqrestore(&ide_lock, flags); 160 spin_unlock_irqrestore(&ide_lock, flags);
285 } 161 }
162
286 return val; 163 return val;
287} 164}
288 165
@@ -304,33 +181,26 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
304 * The current scheme of polling is kludgy, though safe enough. 181 * The current scheme of polling is kludgy, though safe enough.
305 */ 182 */
306 183
307static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) 184static int ide_write_setting(ide_drive_t *drive,
185 const struct ide_devset *setting, int val)
308{ 186{
309 if (!capable(CAP_SYS_ADMIN)) 187 if (!capable(CAP_SYS_ADMIN))
310 return -EACCES; 188 return -EACCES;
311 if (setting->set) 189 if (setting->set && (setting->flags & S_NOLOCK))
312 return setting->set(drive, val); 190 return setting->set(drive, val);
313 if (!(setting->rw & SETTING_WRITE)) 191 if (!(setting->flags & S_WRITE))
314 return -EPERM; 192 return -EPERM;
315 if (val < setting->min || val > setting->max) 193 if (val < setting->min || val > setting->max)
316 return -EINVAL; 194 return -EINVAL;
317 if (ide_spin_wait_hwgroup(drive)) 195 if (ide_spin_wait_hwgroup(drive))
318 return -EBUSY; 196 return -EBUSY;
319 switch (setting->data_type) { 197 setting->set(drive, val);
320 case TYPE_BYTE:
321 *((u8 *) setting->data) = val;
322 break;
323 case TYPE_SHORT:
324 *((u16 *) setting->data) = val;
325 break;
326 case TYPE_INT:
327 *((u32 *) setting->data) = val;
328 break;
329 }
330 spin_unlock_irq(&ide_lock); 198 spin_unlock_irq(&ide_lock);
331 return 0; 199 return 0;
332} 200}
333 201
202static ide_devset_get(xfer_rate, current_speed);
203
334static int set_xfer_rate (ide_drive_t *drive, int arg) 204static int set_xfer_rate (ide_drive_t *drive, int arg)
335{ 205{
336 ide_task_t task; 206 ide_task_t task;
@@ -355,29 +225,30 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
355 return err; 225 return err;
356} 226}
357 227
358/** 228ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate);
359 * ide_add_generic_settings - generic ide settings 229ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit);
360 * @drive: drive being configured 230ide_devset_rw_nolock(keepsettings, 0, 1, ksettings);
361 * 231ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq);
362 * Add the generic parts of the system settings to the /proc files. 232ide_devset_rw_nolock(using_dma, 0, 1, using_dma);
363 * The caller must not be holding the ide_setting_mtx. 233
364 */ 234ide_devset_w_nolock(pio_mode, 0, 255, pio_mode);
365 235
366void ide_add_generic_settings (ide_drive_t *drive) 236ide_devset_rw(init_speed, 0, 70, init_speed);
367{ 237ide_devset_rw(nice1, 0, 1, nice1);
368/* 238ide_devset_rw(number, 0, 3, dn);
369 * drive setting name read/write access data type min max mul_factor div_factor data pointer set function 239
370 */ 240static const struct ide_devset *ide_generic_settings[] = {
371 __ide_add_setting(drive, "io_32bit", SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); 241 &ide_devset_current_speed,
372 __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, set_ksettings, 0); 242 &ide_devset_init_speed,
373 __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); 243 &ide_devset_io_32bit,
374 __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); 244 &ide_devset_keepsettings,
375 __ide_add_setting(drive, "unmaskirq", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, set_unmaskirq, 0); 245 &ide_devset_nice1,
376 __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); 246 &ide_devset_number,
377 __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); 247 &ide_devset_pio_mode,
378 __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); 248 &ide_devset_unmaskirq,
379 __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); 249 &ide_devset_using_dma,
380} 250 NULL
251};
381 252
382static void proc_ide_settings_warn(void) 253static void proc_ide_settings_warn(void)
383{ 254{
@@ -394,19 +265,31 @@ static void proc_ide_settings_warn(void)
394static int proc_ide_read_settings 265static int proc_ide_read_settings
395 (char *page, char **start, off_t off, int count, int *eof, void *data) 266 (char *page, char **start, off_t off, int count, int *eof, void *data)
396{ 267{
268 const struct ide_devset *setting, **g, **d;
397 ide_drive_t *drive = (ide_drive_t *) data; 269 ide_drive_t *drive = (ide_drive_t *) data;
398 ide_settings_t *setting = (ide_settings_t *) drive->settings;
399 char *out = page; 270 char *out = page;
400 int len, rc, mul_factor, div_factor; 271 int len, rc, mul_factor, div_factor;
401 272
402 proc_ide_settings_warn(); 273 proc_ide_settings_warn();
403 274
404 mutex_lock(&ide_setting_mtx); 275 mutex_lock(&ide_setting_mtx);
276 g = ide_generic_settings;
277 d = drive->settings;
405 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); 278 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
406 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); 279 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
407 while (setting) { 280 while (*g || (d && *d)) {
408 mul_factor = setting->mul_factor; 281 /* read settings in the alphabetical order */
409 div_factor = setting->div_factor; 282 if (*g && d && *d) {
283 if (strcmp((*d)->name, (*g)->name) < 0)
284 setting = *d++;
285 else
286 setting = *g++;
287 } else if (d && *d) {
288 setting = *d++;
289 } else
290 setting = *g++;
291 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
292 div_factor = setting->divf ? setting->divf(drive) : 1;
410 out += sprintf(out, "%-24s", setting->name); 293 out += sprintf(out, "%-24s", setting->name);
411 rc = ide_read_setting(drive, setting); 294 rc = ide_read_setting(drive, setting);
412 if (rc >= 0) 295 if (rc >= 0)
@@ -414,12 +297,11 @@ static int proc_ide_read_settings
414 else 297 else
415 out += sprintf(out, "%-16s", "write-only"); 298 out += sprintf(out, "%-16s", "write-only");
416 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); 299 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
417 if (setting->rw & SETTING_READ) 300 if (setting->flags & S_READ)
418 out += sprintf(out, "r"); 301 out += sprintf(out, "r");
419 if (setting->rw & SETTING_WRITE) 302 if (setting->flags & S_WRITE)
420 out += sprintf(out, "w"); 303 out += sprintf(out, "w");
421 out += sprintf(out, "\n"); 304 out += sprintf(out, "\n");
422 setting = setting->next;
423 } 305 }
424 len = out - page; 306 len = out - page;
425 mutex_unlock(&ide_setting_mtx); 307 mutex_unlock(&ide_setting_mtx);
@@ -433,9 +315,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
433{ 315{
434 ide_drive_t *drive = (ide_drive_t *) data; 316 ide_drive_t *drive = (ide_drive_t *) data;
435 char name[MAX_LEN + 1]; 317 char name[MAX_LEN + 1];
436 int for_real = 0; 318 int for_real = 0, mul_factor, div_factor;
437 unsigned long n; 319 unsigned long n;
438 ide_settings_t *setting; 320
321 const struct ide_devset *setting;
439 char *buf, *s; 322 char *buf, *s;
440 323
441 if (!capable(CAP_SYS_ADMIN)) 324 if (!capable(CAP_SYS_ADMIN))
@@ -503,13 +386,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
503 } 386 }
504 387
505 mutex_lock(&ide_setting_mtx); 388 mutex_lock(&ide_setting_mtx);
506 setting = ide_find_setting_by_name(drive, name); 389 /* generic settings first, then driver specific ones */
390 setting = ide_find_setting(ide_generic_settings, name);
507 if (!setting) { 391 if (!setting) {
508 mutex_unlock(&ide_setting_mtx); 392 if (drive->settings)
509 goto parse_error; 393 setting = ide_find_setting(drive->settings, name);
394 if (!setting) {
395 mutex_unlock(&ide_setting_mtx);
396 goto parse_error;
397 }
398 }
399 if (for_real) {
400 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
401 div_factor = setting->divf ? setting->divf(drive) : 1;
402 ide_write_setting(drive, setting, val * div_factor / mul_factor);
510 } 403 }
511 if (for_real)
512 ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
513 mutex_unlock(&ide_setting_mtx); 404 mutex_unlock(&ide_setting_mtx);
514 } 405 }
515 } while (!for_real++); 406 } while (!for_real++);
@@ -680,6 +571,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
680 571
681void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) 572void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
682{ 573{
574 mutex_lock(&ide_setting_mtx);
575 drive->settings = driver->settings;
576 mutex_unlock(&ide_setting_mtx);
577
683 ide_add_proc_entries(drive->proc, driver->proc, drive); 578 ide_add_proc_entries(drive->proc, driver->proc, drive);
684} 579}
685 580
@@ -716,7 +611,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
716 * OTOH both ide_{read,write}_setting are only ever used under 611 * OTOH both ide_{read,write}_setting are only ever used under
717 * ide_setting_mtx. 612 * ide_setting_mtx.
718 */ 613 */
719 auto_remove_settings(drive); 614 drive->settings = NULL;
720 spin_unlock_irqrestore(&ide_lock, flags); 615 spin_unlock_irqrestore(&ide_lock, flags);
721 mutex_unlock(&ide_setting_mtx); 616 mutex_unlock(&ide_setting_mtx);
722} 617}