diff options
author | Peter Jones <pjones@redhat.com> | 2011-01-06 15:31:29 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-01-24 13:01:07 -0500 |
commit | 38a039be2e7bda32517642ecfce54c9317292a9c (patch) | |
tree | 2eb828510c3ee4a40295d73f4414fd8f9625128c | |
parent | 716163ff908be72f6b74752ad0796cc7c00b047a (diff) |
[SCSI] Add scsi_dev_info_list_del_keyed()
For scsi_dh.c to use devinfo lists, we have to be able to remove entries
before rmmod.
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/scsi_devinfo.c | 85 | ||||
-rw-r--r-- | drivers/scsi/scsi_priv.h | 1 |
2 files changed, 86 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 43fad4c09beb..82e9e5c0476e 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -382,6 +382,91 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model, | |||
382 | EXPORT_SYMBOL(scsi_dev_info_list_add_keyed); | 382 | EXPORT_SYMBOL(scsi_dev_info_list_add_keyed); |
383 | 383 | ||
384 | /** | 384 | /** |
385 | * scsi_dev_info_list_del_keyed - remove one dev_info list entry. | ||
386 | * @vendor: vendor string | ||
387 | * @model: model (product) string | ||
388 | * @key: specify list to use | ||
389 | * | ||
390 | * Description: | ||
391 | * Remove and destroy one dev_info entry for @vendor, @model | ||
392 | * in list specified by @key. | ||
393 | * | ||
394 | * Returns: 0 OK, -error on failure. | ||
395 | **/ | ||
396 | int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key) | ||
397 | { | ||
398 | struct scsi_dev_info_list *devinfo, *found = NULL; | ||
399 | struct scsi_dev_info_list_table *devinfo_table = | ||
400 | scsi_devinfo_lookup_by_key(key); | ||
401 | |||
402 | if (IS_ERR(devinfo_table)) | ||
403 | return PTR_ERR(devinfo_table); | ||
404 | |||
405 | list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list, | ||
406 | dev_info_list) { | ||
407 | if (devinfo->compatible) { | ||
408 | /* | ||
409 | * Behave like the older version of get_device_flags. | ||
410 | */ | ||
411 | size_t max; | ||
412 | /* | ||
413 | * XXX why skip leading spaces? If an odd INQUIRY | ||
414 | * value, that should have been part of the | ||
415 | * scsi_static_device_list[] entry, such as " FOO" | ||
416 | * rather than "FOO". Since this code is already | ||
417 | * here, and we don't know what device it is | ||
418 | * trying to work with, leave it as-is. | ||
419 | */ | ||
420 | max = 8; /* max length of vendor */ | ||
421 | while ((max > 0) && *vendor == ' ') { | ||
422 | max--; | ||
423 | vendor++; | ||
424 | } | ||
425 | /* | ||
426 | * XXX removing the following strlen() would be | ||
427 | * good, using it means that for a an entry not in | ||
428 | * the list, we scan every byte of every vendor | ||
429 | * listed in scsi_static_device_list[], and never match | ||
430 | * a single one (and still have to compare at | ||
431 | * least the first byte of each vendor). | ||
432 | */ | ||
433 | if (memcmp(devinfo->vendor, vendor, | ||
434 | min(max, strlen(devinfo->vendor)))) | ||
435 | continue; | ||
436 | /* | ||
437 | * Skip spaces again. | ||
438 | */ | ||
439 | max = 16; /* max length of model */ | ||
440 | while ((max > 0) && *model == ' ') { | ||
441 | max--; | ||
442 | model++; | ||
443 | } | ||
444 | if (memcmp(devinfo->model, model, | ||
445 | min(max, strlen(devinfo->model)))) | ||
446 | continue; | ||
447 | found = devinfo; | ||
448 | } else { | ||
449 | if (!memcmp(devinfo->vendor, vendor, | ||
450 | sizeof(devinfo->vendor)) && | ||
451 | !memcmp(devinfo->model, model, | ||
452 | sizeof(devinfo->model))) | ||
453 | found = devinfo; | ||
454 | } | ||
455 | if (found) | ||
456 | break; | ||
457 | } | ||
458 | |||
459 | if (found) { | ||
460 | list_del(&found->dev_info_list); | ||
461 | kfree(found); | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | return -ENOENT; | ||
466 | } | ||
467 | EXPORT_SYMBOL(scsi_dev_info_list_del_keyed); | ||
468 | |||
469 | /** | ||
385 | * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list. | 470 | * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list. |
386 | * @dev_list: string of device flags to add | 471 | * @dev_list: string of device flags to add |
387 | * | 472 | * |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index b4056d14f812..ce9e0adc8df8 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -56,6 +56,7 @@ extern int scsi_get_device_flags_keyed(struct scsi_device *sdev, | |||
56 | extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor, | 56 | extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor, |
57 | char *model, char *strflags, | 57 | char *model, char *strflags, |
58 | int flags, int key); | 58 | int flags, int key); |
59 | extern int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key); | ||
59 | extern int scsi_dev_info_add_list(int key, const char *name); | 60 | extern int scsi_dev_info_add_list(int key, const char *name); |
60 | extern int scsi_dev_info_remove_list(int key); | 61 | extern int scsi_dev_info_remove_list(int key); |
61 | 62 | ||