ide-proc.c revision 3ceca727fe3a38dd8d7a3adf938fefda83eee8af
1/* 2 * Copyright (C) 1997-1998 Mark Lord 3 * Copyright (C) 2003 Red Hat <alan@redhat.com> 4 * 5 * Some code was moved here from ide.c, see it for original copyrights. 6 */ 7 8/* 9 * This is the /proc/ide/ filesystem implementation. 10 * 11 * Drive/Driver settings can be retrieved by reading the drive's 12 * "settings" files. e.g. "cat /proc/ide0/hda/settings" 13 * To write a new value "val" into a specific setting "name", use: 14 * echo "name:val" >/proc/ide/ide0/hda/settings 15 */ 16 17#include <linux/module.h> 18 19#include <asm/uaccess.h> 20#include <linux/errno.h> 21#include <linux/proc_fs.h> 22#include <linux/stat.h> 23#include <linux/mm.h> 24#include <linux/pci.h> 25#include <linux/ctype.h> 26#include <linux/ide.h> 27#include <linux/seq_file.h> 28 29#include <asm/io.h> 30 31static struct proc_dir_entry *proc_ide_root; 32 33static int proc_ide_read_imodel 34 (char *page, char **start, off_t off, int count, int *eof, void *data) 35{ 36 ide_hwif_t *hwif = (ide_hwif_t *) data; 37 int len; 38 const char *name; 39 40 switch (hwif->chipset) { 41 case ide_generic: name = "generic"; break; 42 case ide_pci: name = "pci"; break; 43 case ide_cmd640: name = "cmd640"; break; 44 case ide_dtc2278: name = "dtc2278"; break; 45 case ide_ali14xx: name = "ali14xx"; break; 46 case ide_qd65xx: name = "qd65xx"; break; 47 case ide_umc8672: name = "umc8672"; break; 48 case ide_ht6560b: name = "ht6560b"; break; 49 case ide_rz1000: name = "rz1000"; break; 50 case ide_trm290: name = "trm290"; break; 51 case ide_cmd646: name = "cmd646"; break; 52 case ide_cy82c693: name = "cy82c693"; break; 53 case ide_4drives: name = "4drives"; break; 54 case ide_pmac: name = "mac-io"; break; 55 case ide_au1xxx: name = "au1xxx"; break; 56 case ide_palm3710: name = "palm3710"; break; 57 case ide_acorn: name = "acorn"; break; 58 default: name = "(unknown)"; break; 59 } 60 len = sprintf(page, "%s\n", name); 61 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 62} 63 64static int proc_ide_read_mate 65 (char *page, char **start, off_t off, int count, int *eof, void *data) 66{ 67 ide_hwif_t *hwif = (ide_hwif_t *) data; 68 int len; 69 70 if (hwif && hwif->mate) 71 len = sprintf(page, "%s\n", hwif->mate->name); 72 else 73 len = sprintf(page, "(none)\n"); 74 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 75} 76 77static int proc_ide_read_channel 78 (char *page, char **start, off_t off, int count, int *eof, void *data) 79{ 80 ide_hwif_t *hwif = (ide_hwif_t *) data; 81 int len; 82 83 page[0] = hwif->channel ? '1' : '0'; 84 page[1] = '\n'; 85 len = 2; 86 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 87} 88 89static int proc_ide_read_identify 90 (char *page, char **start, off_t off, int count, int *eof, void *data) 91{ 92 ide_drive_t *drive = (ide_drive_t *)data; 93 int len = 0, i = 0; 94 int err = 0; 95 96 len = sprintf(page, "\n"); 97 98 if (drive) { 99 __le16 *val = (__le16 *)page; 100 101 err = taskfile_lib_get_identify(drive, page); 102 if (!err) { 103 char *out = ((char *)page) + (SECTOR_WORDS * 4); 104 page = out; 105 do { 106 out += sprintf(out, "%04x%c", 107 le16_to_cpup(val), (++i & 7) ? ' ' : '\n'); 108 val += 1; 109 } while (i < (SECTOR_WORDS * 2)); 110 len = out - page; 111 } 112 } 113 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 114} 115 116/** 117 * __ide_add_setting - add an ide setting option 118 * @drive: drive to use 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 * 130 * Removes the setting named from the device if it is present. 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 238 * setting semaphore 239 */ 240 241static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) 242{ 243 ide_settings_t *setting = drive->settings; 244 245 while (setting) { 246 if (strcmp(setting->name, name) == 0) 247 break; 248 setting = setting->next; 249 } 250 return setting; 251} 252 253/** 254 * ide_read_setting - read an IDE setting 255 * @drive: drive to read from 256 * @setting: drive setting 257 * 258 * Read a drive setting and return the value. The caller 259 * must hold the ide_setting_mtx when making this call. 260 * 261 * BUGS: the data return and error are the same return value 262 * so an error -EINVAL and true return of the same value cannot 263 * be told apart 264 */ 265 266static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) 267{ 268 int val = -EINVAL; 269 unsigned long flags; 270 271 if ((setting->rw & SETTING_READ)) { 272 spin_lock_irqsave(&ide_lock, flags); 273 switch (setting->data_type) { 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); 285 } 286 return val; 287} 288 289/** 290 * ide_write_setting - read an IDE setting 291 * @drive: drive to read from 292 * @setting: drive setting 293 * @val: value 294 * 295 * Write a drive setting if it is possible. The caller 296 * must hold the ide_setting_mtx when making this call. 297 * 298 * BUGS: the data return and error are the same return value 299 * so an error -EINVAL and true return of the same value cannot 300 * be told apart 301 * 302 * FIXME: This should be changed to enqueue a special request 303 * to the driver to change settings, and then wait on a sema for completion. 304 * The current scheme of polling is kludgy, though safe enough. 305 */ 306 307static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) 308{ 309 if (!capable(CAP_SYS_ADMIN)) 310 return -EACCES; 311 if (setting->set) 312 return setting->set(drive, val); 313 if (!(setting->rw & SETTING_WRITE)) 314 return -EPERM; 315 if (val < setting->min || val > setting->max) 316 return -EINVAL; 317 if (ide_spin_wait_hwgroup(drive)) 318 return -EBUSY; 319 switch (setting->data_type) { 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); 331 return 0; 332} 333 334static int set_xfer_rate (ide_drive_t *drive, int arg) 335{ 336 ide_task_t task; 337 int err; 338 339 if (arg < XFER_PIO_0 || arg > XFER_UDMA_6) 340 return -EINVAL; 341 342 memset(&task, 0, sizeof(task)); 343 task.tf.command = ATA_CMD_SET_FEATURES; 344 task.tf.feature = SETFEATURES_XFER; 345 task.tf.nsect = (u8)arg; 346 task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | 347 IDE_TFLAG_IN_NSECT; 348 349 err = ide_no_data_taskfile(drive, &task); 350 351 if (!err) { 352 ide_set_xfer_rate(drive, (u8) arg); 353 ide_driveid_update(drive); 354 } 355 return err; 356} 357 358/** 359 * ide_add_generic_settings - generic ide settings 360 * @drive: drive being configured 361 * 362 * Add the generic parts of the system settings to the /proc files. 363 * The caller must not be holding the ide_setting_mtx. 364 */ 365 366void ide_add_generic_settings (ide_drive_t *drive) 367{ 368/* 369 * drive setting name read/write access data type min max mul_factor div_factor data pointer set function 370 */ 371 __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); 372 __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); 373 __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); 374 __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); 375 __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); 376 __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); 377 __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); 378 __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); 379 __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); 380} 381 382static void proc_ide_settings_warn(void) 383{ 384 static int warned; 385 386 if (warned) 387 return; 388 389 printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is " 390 "obsolete, and will be removed soon!\n"); 391 warned = 1; 392} 393 394static int proc_ide_read_settings 395 (char *page, char **start, off_t off, int count, int *eof, void *data) 396{ 397 ide_drive_t *drive = (ide_drive_t *) data; 398 ide_settings_t *setting = (ide_settings_t *) drive->settings; 399 char *out = page; 400 int len, rc, mul_factor, div_factor; 401 402 proc_ide_settings_warn(); 403 404 mutex_lock(&ide_setting_mtx); 405 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"); 407 while (setting) { 408 mul_factor = setting->mul_factor; 409 div_factor = setting->div_factor; 410 out += sprintf(out, "%-24s", setting->name); 411 rc = ide_read_setting(drive, setting); 412 if (rc >= 0) 413 out += sprintf(out, "%-16d", rc * mul_factor / div_factor); 414 else 415 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); 417 if (setting->rw & SETTING_READ) 418 out += sprintf(out, "r"); 419 if (setting->rw & SETTING_WRITE) 420 out += sprintf(out, "w"); 421 out += sprintf(out, "\n"); 422 setting = setting->next; 423 } 424 len = out - page; 425 mutex_unlock(&ide_setting_mtx); 426 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 427} 428 429#define MAX_LEN 30 430 431static int proc_ide_write_settings(struct file *file, const char __user *buffer, 432 unsigned long count, void *data) 433{ 434 ide_drive_t *drive = (ide_drive_t *) data; 435 char name[MAX_LEN + 1]; 436 int for_real = 0; 437 unsigned long n; 438 ide_settings_t *setting; 439 char *buf, *s; 440 441 if (!capable(CAP_SYS_ADMIN)) 442 return -EACCES; 443 444 proc_ide_settings_warn(); 445 446 if (count >= PAGE_SIZE) 447 return -EINVAL; 448 449 s = buf = (char *)__get_free_page(GFP_USER); 450 if (!buf) 451 return -ENOMEM; 452 453 if (copy_from_user(buf, buffer, count)) { 454 free_page((unsigned long)buf); 455 return -EFAULT; 456 } 457 458 buf[count] = '\0'; 459 460 /* 461 * Skip over leading whitespace 462 */ 463 while (count && isspace(*s)) { 464 --count; 465 ++s; 466 } 467 /* 468 * Do one full pass to verify all parameters, 469 * then do another to actually write the new settings. 470 */ 471 do { 472 char *p = s; 473 n = count; 474 while (n > 0) { 475 unsigned val; 476 char *q = p; 477 478 while (n > 0 && *p != ':') { 479 --n; 480 p++; 481 } 482 if (*p != ':') 483 goto parse_error; 484 if (p - q > MAX_LEN) 485 goto parse_error; 486 memcpy(name, q, p - q); 487 name[p - q] = 0; 488 489 if (n > 0) { 490 --n; 491 p++; 492 } else 493 goto parse_error; 494 495 val = simple_strtoul(p, &q, 10); 496 n -= q - p; 497 p = q; 498 if (n > 0 && !isspace(*p)) 499 goto parse_error; 500 while (n > 0 && isspace(*p)) { 501 --n; 502 ++p; 503 } 504 505 mutex_lock(&ide_setting_mtx); 506 setting = ide_find_setting_by_name(drive, name); 507 if (!setting) { 508 mutex_unlock(&ide_setting_mtx); 509 goto parse_error; 510 } 511 if (for_real) 512 ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor); 513 mutex_unlock(&ide_setting_mtx); 514 } 515 } while (!for_real++); 516 free_page((unsigned long)buf); 517 return count; 518parse_error: 519 free_page((unsigned long)buf); 520 printk("proc_ide_write_settings(): parse error\n"); 521 return -EINVAL; 522} 523 524int proc_ide_read_capacity 525 (char *page, char **start, off_t off, int count, int *eof, void *data) 526{ 527 int len = sprintf(page, "%llu\n", (long long)0x7fffffff); 528 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 529} 530 531EXPORT_SYMBOL_GPL(proc_ide_read_capacity); 532 533int proc_ide_read_geometry 534 (char *page, char **start, off_t off, int count, int *eof, void *data) 535{ 536 ide_drive_t *drive = (ide_drive_t *) data; 537 char *out = page; 538 int len; 539 540 out += sprintf(out, "physical %d/%d/%d\n", 541 drive->cyl, drive->head, drive->sect); 542 out += sprintf(out, "logical %d/%d/%d\n", 543 drive->bios_cyl, drive->bios_head, drive->bios_sect); 544 545 len = out - page; 546 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 547} 548 549EXPORT_SYMBOL(proc_ide_read_geometry); 550 551static int proc_ide_read_dmodel 552 (char *page, char **start, off_t off, int count, int *eof, void *data) 553{ 554 ide_drive_t *drive = (ide_drive_t *) data; 555 char *m = (char *)&drive->id[ATA_ID_PROD]; 556 int len; 557 558 len = sprintf(page, "%.40s\n", m[0] ? m : "(none)"); 559 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 560} 561 562static int proc_ide_read_driver 563 (char *page, char **start, off_t off, int count, int *eof, void *data) 564{ 565 ide_drive_t *drive = (ide_drive_t *) data; 566 struct device *dev = &drive->gendev; 567 ide_driver_t *ide_drv; 568 int len; 569 570 if (dev->driver) { 571 ide_drv = container_of(dev->driver, ide_driver_t, gen_driver); 572 len = sprintf(page, "%s version %s\n", 573 dev->driver->name, ide_drv->version); 574 } else 575 len = sprintf(page, "ide-default version 0.9.newide\n"); 576 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 577} 578 579static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) 580{ 581 struct device *dev = &drive->gendev; 582 int ret = 1; 583 int err; 584 585 device_release_driver(dev); 586 /* FIXME: device can still be in use by previous driver */ 587 strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); 588 err = device_attach(dev); 589 if (err < 0) 590 printk(KERN_WARNING "IDE: %s: device_attach error: %d\n", 591 __func__, err); 592 drive->driver_req[0] = 0; 593 if (dev->driver == NULL) { 594 err = device_attach(dev); 595 if (err < 0) 596 printk(KERN_WARNING 597 "IDE: %s: device_attach(2) error: %d\n", 598 __func__, err); 599 } 600 if (dev->driver && !strcmp(dev->driver->name, driver)) 601 ret = 0; 602 603 return ret; 604} 605 606static int proc_ide_write_driver 607 (struct file *file, const char __user *buffer, unsigned long count, void *data) 608{ 609 ide_drive_t *drive = (ide_drive_t *) data; 610 char name[32]; 611 612 if (!capable(CAP_SYS_ADMIN)) 613 return -EACCES; 614 if (count > 31) 615 count = 31; 616 if (copy_from_user(name, buffer, count)) 617 return -EFAULT; 618 name[count] = '\0'; 619 if (ide_replace_subdriver(drive, name)) 620 return -EINVAL; 621 return count; 622} 623 624static int proc_ide_read_media 625 (char *page, char **start, off_t off, int count, int *eof, void *data) 626{ 627 ide_drive_t *drive = (ide_drive_t *) data; 628 const char *media; 629 int len; 630 631 switch (drive->media) { 632 case ide_disk: media = "disk\n"; break; 633 case ide_cdrom: media = "cdrom\n"; break; 634 case ide_tape: media = "tape\n"; break; 635 case ide_floppy: media = "floppy\n"; break; 636 case ide_optical: media = "optical\n"; break; 637 default: media = "UNKNOWN\n"; break; 638 } 639 strcpy(page, media); 640 len = strlen(media); 641 PROC_IDE_READ_RETURN(page, start, off, count, eof, len); 642} 643 644static ide_proc_entry_t generic_drive_entries[] = { 645 { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, 646 proc_ide_write_driver }, 647 { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, 648 { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, 649 { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, 650 { "settings", S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings, 651 proc_ide_write_settings }, 652 { NULL, 0, NULL, NULL } 653}; 654 655static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) 656{ 657 struct proc_dir_entry *ent; 658 659 if (!dir || !p) 660 return; 661 while (p->name != NULL) { 662 ent = create_proc_entry(p->name, p->mode, dir); 663 if (!ent) return; 664 ent->data = data; 665 ent->read_proc = p->read_proc; 666 ent->write_proc = p->write_proc; 667 p++; 668 } 669} 670 671static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) 672{ 673 if (!dir || !p) 674 return; 675 while (p->name != NULL) { 676 remove_proc_entry(p->name, dir); 677 p++; 678 } 679} 680 681void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) 682{ 683 ide_add_proc_entries(drive->proc, driver->proc, drive); 684} 685 686EXPORT_SYMBOL(ide_proc_register_driver); 687 688/** 689 * ide_proc_unregister_driver - remove driver specific data 690 * @drive: drive 691 * @driver: driver 692 * 693 * Clean up the driver specific /proc files and IDE settings 694 * for a given drive. 695 * 696 * Takes ide_setting_mtx and ide_lock. 697 * Caller must hold none of the locks. 698 */ 699 700void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) 701{ 702 unsigned long flags; 703 704 ide_remove_proc_entries(drive->proc, driver->proc); 705 706 mutex_lock(&ide_setting_mtx); 707 spin_lock_irqsave(&ide_lock, flags); 708 /* 709 * ide_setting_mtx protects the settings list 710 * ide_lock protects the use of settings 711 * 712 * so we need to hold both, ide_settings_sem because we want to 713 * modify the settings list, and ide_lock because we cannot take 714 * a setting out that is being used. 715 * 716 * OTOH both ide_{read,write}_setting are only ever used under 717 * ide_setting_mtx. 718 */ 719 auto_remove_settings(drive); 720 spin_unlock_irqrestore(&ide_lock, flags); 721 mutex_unlock(&ide_setting_mtx); 722} 723EXPORT_SYMBOL(ide_proc_unregister_driver); 724 725void ide_proc_port_register_devices(ide_hwif_t *hwif) 726{ 727 int d; 728 struct proc_dir_entry *ent; 729 struct proc_dir_entry *parent = hwif->proc; 730 char name[64]; 731 732 for (d = 0; d < MAX_DRIVES; d++) { 733 ide_drive_t *drive = &hwif->drives[d]; 734 735 if (!drive->present) 736 continue; 737 if (drive->proc) 738 continue; 739 740 drive->proc = proc_mkdir(drive->name, parent); 741 if (drive->proc) 742 ide_add_proc_entries(drive->proc, generic_drive_entries, drive); 743 sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name); 744 ent = proc_symlink(drive->name, proc_ide_root, name); 745 if (!ent) return; 746 } 747} 748 749void ide_proc_unregister_device(ide_drive_t *drive) 750{ 751 if (drive->proc) { 752 ide_remove_proc_entries(drive->proc, generic_drive_entries); 753 remove_proc_entry(drive->name, proc_ide_root); 754 remove_proc_entry(drive->name, drive->hwif->proc); 755 drive->proc = NULL; 756 } 757} 758 759static ide_proc_entry_t hwif_entries[] = { 760 { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, 761 { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, 762 { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, 763 { NULL, 0, NULL, NULL } 764}; 765 766void ide_proc_register_port(ide_hwif_t *hwif) 767{ 768 if (!hwif->proc) { 769 hwif->proc = proc_mkdir(hwif->name, proc_ide_root); 770 771 if (!hwif->proc) 772 return; 773 774 ide_add_proc_entries(hwif->proc, hwif_entries, hwif); 775 } 776} 777 778void ide_proc_unregister_port(ide_hwif_t *hwif) 779{ 780 if (hwif->proc) { 781 ide_remove_proc_entries(hwif->proc, hwif_entries); 782 remove_proc_entry(hwif->name, proc_ide_root); 783 hwif->proc = NULL; 784 } 785} 786 787static int proc_print_driver(struct device_driver *drv, void *data) 788{ 789 ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver); 790 struct seq_file *s = data; 791 792 seq_printf(s, "%s version %s\n", drv->name, ide_drv->version); 793 794 return 0; 795} 796 797static int ide_drivers_show(struct seq_file *s, void *p) 798{ 799 int err; 800 801 err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver); 802 if (err < 0) 803 printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n", 804 __func__, err); 805 return 0; 806} 807 808static int ide_drivers_open(struct inode *inode, struct file *file) 809{ 810 return single_open(file, &ide_drivers_show, NULL); 811} 812 813static const struct file_operations ide_drivers_operations = { 814 .owner = THIS_MODULE, 815 .open = ide_drivers_open, 816 .read = seq_read, 817 .llseek = seq_lseek, 818 .release = single_release, 819}; 820 821void proc_ide_create(void) 822{ 823 proc_ide_root = proc_mkdir("ide", NULL); 824 825 if (!proc_ide_root) 826 return; 827 828 proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations); 829} 830 831void proc_ide_destroy(void) 832{ 833 remove_proc_entry("drivers", proc_ide_root); 834 remove_proc_entry("ide", NULL); 835} 836