diff options
Diffstat (limited to 'drivers/scsi/scsi_proc.c')
-rw-r--r-- | drivers/scsi/scsi_proc.c | 110 |
1 files changed, 108 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index bb6f051beda8..ed395154a5b1 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -45,6 +45,16 @@ static struct proc_dir_entry *proc_scsi; | |||
45 | /* Protect sht->present and sht->proc_dir */ | 45 | /* Protect sht->present and sht->proc_dir */ |
46 | static DEFINE_MUTEX(global_host_template_mutex); | 46 | static DEFINE_MUTEX(global_host_template_mutex); |
47 | 47 | ||
48 | /** | ||
49 | * proc_scsi_read - handle read from /proc by calling host's proc_info() command | ||
50 | * @buffer: passed to proc_info | ||
51 | * @start: passed to proc_info | ||
52 | * @offset: passed to proc_info | ||
53 | * @length: passed to proc_info | ||
54 | * @eof: returns whether length read was less than requested | ||
55 | * @data: pointer to a &struct Scsi_Host | ||
56 | */ | ||
57 | |||
48 | static int proc_scsi_read(char *buffer, char **start, off_t offset, | 58 | static int proc_scsi_read(char *buffer, char **start, off_t offset, |
49 | int length, int *eof, void *data) | 59 | int length, int *eof, void *data) |
50 | { | 60 | { |
@@ -57,6 +67,13 @@ static int proc_scsi_read(char *buffer, char **start, off_t offset, | |||
57 | return n; | 67 | return n; |
58 | } | 68 | } |
59 | 69 | ||
70 | /** | ||
71 | * proc_scsi_write_proc - Handle write to /proc by calling host's proc_info() | ||
72 | * @file: not used | ||
73 | * @buf: source of data to write. | ||
74 | * @count: number of bytes (at most PROC_BLOCK_SIZE) to write. | ||
75 | * @data: pointer to &struct Scsi_Host | ||
76 | */ | ||
60 | static int proc_scsi_write_proc(struct file *file, const char __user *buf, | 77 | static int proc_scsi_write_proc(struct file *file, const char __user *buf, |
61 | unsigned long count, void *data) | 78 | unsigned long count, void *data) |
62 | { | 79 | { |
@@ -80,6 +97,13 @@ out: | |||
80 | return ret; | 97 | return ret; |
81 | } | 98 | } |
82 | 99 | ||
100 | /** | ||
101 | * scsi_proc_hostdir_add - Create directory in /proc for a scsi host | ||
102 | * @sht: owner of this directory | ||
103 | * | ||
104 | * Sets sht->proc_dir to the new directory. | ||
105 | */ | ||
106 | |||
83 | void scsi_proc_hostdir_add(struct scsi_host_template *sht) | 107 | void scsi_proc_hostdir_add(struct scsi_host_template *sht) |
84 | { | 108 | { |
85 | if (!sht->proc_info) | 109 | if (!sht->proc_info) |
@@ -97,6 +121,10 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) | |||
97 | mutex_unlock(&global_host_template_mutex); | 121 | mutex_unlock(&global_host_template_mutex); |
98 | } | 122 | } |
99 | 123 | ||
124 | /** | ||
125 | * scsi_proc_hostdir_rm - remove directory in /proc for a scsi host | ||
126 | * @sht: owner of directory | ||
127 | */ | ||
100 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) | 128 | void scsi_proc_hostdir_rm(struct scsi_host_template *sht) |
101 | { | 129 | { |
102 | if (!sht->proc_info) | 130 | if (!sht->proc_info) |
@@ -110,6 +138,11 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht) | |||
110 | mutex_unlock(&global_host_template_mutex); | 138 | mutex_unlock(&global_host_template_mutex); |
111 | } | 139 | } |
112 | 140 | ||
141 | |||
142 | /** | ||
143 | * scsi_proc_host_add - Add entry for this host to appropriate /proc dir | ||
144 | * @shost: host to add | ||
145 | */ | ||
113 | void scsi_proc_host_add(struct Scsi_Host *shost) | 146 | void scsi_proc_host_add(struct Scsi_Host *shost) |
114 | { | 147 | { |
115 | struct scsi_host_template *sht = shost->hostt; | 148 | struct scsi_host_template *sht = shost->hostt; |
@@ -133,6 +166,10 @@ void scsi_proc_host_add(struct Scsi_Host *shost) | |||
133 | p->owner = sht->module; | 166 | p->owner = sht->module; |
134 | } | 167 | } |
135 | 168 | ||
169 | /** | ||
170 | * scsi_proc_host_rm - remove this host's entry from /proc | ||
171 | * @shost: which host | ||
172 | */ | ||
136 | void scsi_proc_host_rm(struct Scsi_Host *shost) | 173 | void scsi_proc_host_rm(struct Scsi_Host *shost) |
137 | { | 174 | { |
138 | char name[10]; | 175 | char name[10]; |
@@ -143,7 +180,14 @@ void scsi_proc_host_rm(struct Scsi_Host *shost) | |||
143 | sprintf(name,"%d", shost->host_no); | 180 | sprintf(name,"%d", shost->host_no); |
144 | remove_proc_entry(name, shost->hostt->proc_dir); | 181 | remove_proc_entry(name, shost->hostt->proc_dir); |
145 | } | 182 | } |
146 | 183 | /** | |
184 | * proc_print_scsidevice - return data about this host | ||
185 | * @dev: A scsi device | ||
186 | * @data: &struct seq_file to output to. | ||
187 | * | ||
188 | * Description: prints Host, Channel, Id, Lun, Vendor, Model, Rev, Type, | ||
189 | * and revision. | ||
190 | */ | ||
147 | static int proc_print_scsidevice(struct device *dev, void *data) | 191 | static int proc_print_scsidevice(struct device *dev, void *data) |
148 | { | 192 | { |
149 | struct scsi_device *sdev = to_scsi_device(dev); | 193 | struct scsi_device *sdev = to_scsi_device(dev); |
@@ -189,6 +233,21 @@ static int proc_print_scsidevice(struct device *dev, void *data) | |||
189 | return 0; | 233 | return 0; |
190 | } | 234 | } |
191 | 235 | ||
236 | /** | ||
237 | * scsi_add_single_device - Respond to user request to probe for/add device | ||
238 | * @host: user-supplied decimal integer | ||
239 | * @channel: user-supplied decimal integer | ||
240 | * @id: user-supplied decimal integer | ||
241 | * @lun: user-supplied decimal integer | ||
242 | * | ||
243 | * Description: called by writing "scsi add-single-device" to /proc/scsi/scsi. | ||
244 | * | ||
245 | * does scsi_host_lookup() and either user_scan() if that transport | ||
246 | * type supports it, or else scsi_scan_host_selected() | ||
247 | * | ||
248 | * Note: this seems to be aimed exclusively at SCSI parallel busses. | ||
249 | */ | ||
250 | |||
192 | static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) | 251 | static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) |
193 | { | 252 | { |
194 | struct Scsi_Host *shost; | 253 | struct Scsi_Host *shost; |
@@ -206,6 +265,16 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) | |||
206 | return error; | 265 | return error; |
207 | } | 266 | } |
208 | 267 | ||
268 | /** | ||
269 | * scsi_remove_single_device - Respond to user request to remove a device | ||
270 | * @host: user-supplied decimal integer | ||
271 | * @channel: user-supplied decimal integer | ||
272 | * @id: user-supplied decimal integer | ||
273 | * @lun: user-supplied decimal integer | ||
274 | * | ||
275 | * Description: called by writing "scsi remove-single-device" to | ||
276 | * /proc/scsi/scsi. Does a scsi_device_lookup() and scsi_remove_device() | ||
277 | */ | ||
209 | static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) | 278 | static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) |
210 | { | 279 | { |
211 | struct scsi_device *sdev; | 280 | struct scsi_device *sdev; |
@@ -226,6 +295,25 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) | |||
226 | return error; | 295 | return error; |
227 | } | 296 | } |
228 | 297 | ||
298 | /** | ||
299 | * proc_scsi_write - handle writes to /proc/scsi/scsi | ||
300 | * @file: not used | ||
301 | * @buf: buffer to write | ||
302 | * @length: length of buf, at most PAGE_SIZE | ||
303 | * @ppos: not used | ||
304 | * | ||
305 | * Description: this provides a legacy mechanism to add or remove devices by | ||
306 | * Host, Channel, ID, and Lun. To use, | ||
307 | * "echo 'scsi add-single-device 0 1 2 3' > /proc/scsi/scsi" or | ||
308 | * "echo 'scsi remove-single-device 0 1 2 3' > /proc/scsi/scsi" with | ||
309 | * "0 1 2 3" replaced by the Host, Channel, Id, and Lun. | ||
310 | * | ||
311 | * Note: this seems to be aimed at parallel SCSI. Most modern busses (USB, | ||
312 | * SATA, Firewire, Fibre Channel, etc) dynamically assign these values to | ||
313 | * provide a unique identifier and nothing more. | ||
314 | */ | ||
315 | |||
316 | |||
229 | static ssize_t proc_scsi_write(struct file *file, const char __user *buf, | 317 | static ssize_t proc_scsi_write(struct file *file, const char __user *buf, |
230 | size_t length, loff_t *ppos) | 318 | size_t length, loff_t *ppos) |
231 | { | 319 | { |
@@ -291,6 +379,11 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, | |||
291 | return err; | 379 | return err; |
292 | } | 380 | } |
293 | 381 | ||
382 | /** | ||
383 | * proc_scsi_show - show contents of /proc/scsi/scsi (attached devices) | ||
384 | * @s: output goes here | ||
385 | * @p: not used | ||
386 | */ | ||
294 | static int proc_scsi_show(struct seq_file *s, void *p) | 387 | static int proc_scsi_show(struct seq_file *s, void *p) |
295 | { | 388 | { |
296 | seq_printf(s, "Attached devices:\n"); | 389 | seq_printf(s, "Attached devices:\n"); |
@@ -298,10 +391,17 @@ static int proc_scsi_show(struct seq_file *s, void *p) | |||
298 | return 0; | 391 | return 0; |
299 | } | 392 | } |
300 | 393 | ||
394 | /** | ||
395 | * proc_scsi_open - glue function | ||
396 | * @inode: not used | ||
397 | * @file: passed to single_open() | ||
398 | * | ||
399 | * Associates proc_scsi_show with this file | ||
400 | */ | ||
301 | static int proc_scsi_open(struct inode *inode, struct file *file) | 401 | static int proc_scsi_open(struct inode *inode, struct file *file) |
302 | { | 402 | { |
303 | /* | 403 | /* |
304 | * We don't really needs this for the write case but it doesn't | 404 | * We don't really need this for the write case but it doesn't |
305 | * harm either. | 405 | * harm either. |
306 | */ | 406 | */ |
307 | return single_open(file, proc_scsi_show, NULL); | 407 | return single_open(file, proc_scsi_show, NULL); |
@@ -315,6 +415,9 @@ static const struct file_operations proc_scsi_operations = { | |||
315 | .release = single_release, | 415 | .release = single_release, |
316 | }; | 416 | }; |
317 | 417 | ||
418 | /** | ||
419 | * scsi_init_procfs - create scsi and scsi/scsi in procfs | ||
420 | */ | ||
318 | int __init scsi_init_procfs(void) | 421 | int __init scsi_init_procfs(void) |
319 | { | 422 | { |
320 | struct proc_dir_entry *pde; | 423 | struct proc_dir_entry *pde; |
@@ -336,6 +439,9 @@ err1: | |||
336 | return -ENOMEM; | 439 | return -ENOMEM; |
337 | } | 440 | } |
338 | 441 | ||
442 | /** | ||
443 | * scsi_exit_procfs - Remove scsi/scsi and scsi from procfs | ||
444 | */ | ||
339 | void scsi_exit_procfs(void) | 445 | void scsi_exit_procfs(void) |
340 | { | 446 | { |
341 | remove_proc_entry("scsi/scsi", NULL); | 447 | remove_proc_entry("scsi/scsi", NULL); |