The patch titled Add thread to allow controllers to register for rescan for new devices has been added to the -mm tree. Its filename is add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find out what to do about this The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/ ------------------------------------------------------ Subject: Add thread to allow controllers to register for rescan for new devices From: "Stephen M. Cameron" <scameron@xxxxxxxxxxxxxxxxxx> Add thread to allow controllers to register for rescan for new devices (borrowed code from cciss.) Signed-off-by: Stephen M. Cameron <scameron@xxxxxxxxxxxxxxxxxx> Cc: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> Cc: Jens Axboe <jens.axboe@xxxxxxxxxx> Cc: Mike Miller <mikem@xxxxxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/scsi/hpsa.c | 147 +++++++++++++++++++++++++++++++++++++++++- drivers/scsi/hpsa.h | 5 + 2 files changed, 150 insertions(+), 2 deletions(-) diff -puN drivers/scsi/hpsa.c~add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices drivers/scsi/hpsa.c --- a/drivers/scsi/hpsa.c~add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices +++ a/drivers/scsi/hpsa.c @@ -47,6 +47,7 @@ #include <linux/string.h> #include <linux/bitmap.h> #include <asm/atomic.h> +#include <linux/kthread.h> #include "hpsa_cmd.h" #include "hpsa.h" @@ -145,6 +146,7 @@ static ssize_t lunid_show(struct device struct device_attribute *attr, char *buf); static ssize_t unique_id_show(struct device *dev, struct device_attribute *attr, char *buf); +static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); @@ -183,6 +185,129 @@ static inline struct ctlr_info *sdev_to_ return (struct ctlr_info *) *priv; } +static struct task_struct *hpsa_scan_thread; +static DEFINE_MUTEX(scan_mutex); +static LIST_HEAD(scan_q); +static int scan_thread(void *data); + +/** + * add_to_scan_list() - add controller to rescan queue + * @h: Pointer to the controller. + * + * Adds the controller to the rescan queue if not already on the queue. + * + * returns 1 if added to the queue, 0 if skipped (could be on the + * queue already, or the controller could be initializing or shutting + * down). + **/ +static int add_to_scan_list(struct ctlr_info *h) +{ + struct ctlr_info *test_h; + int found = 0; + int ret = 0; + + if (h->busy_initializing) + return 0; + + if (!mutex_trylock(&h->busy_shutting_down)) + return 0; + + mutex_lock(&scan_mutex); + list_for_each_entry(test_h, &scan_q, scan_list) { + if (test_h == h) { + found = 1; + break; + } + } + if (!found && !h->busy_scanning) { + INIT_COMPLETION(h->scan_wait); + list_add_tail(&h->scan_list, &scan_q); + ret = 1; + } + mutex_unlock(&scan_mutex); + mutex_unlock(&h->busy_shutting_down); + + return ret; +} + +/** + * remove_from_scan_list() - remove controller from rescan queue + * @h: Pointer to the controller. + * + * Removes the controller from the rescan queue if present. Blocks if + * the controller is currently conducting a rescan. The controller + * can be in one of three states: + * 1. Doesn't need a scan + * 2. On the scan list, but not scanning yet (we remove it) + * 3. Busy scanning (and not on the list). In this case we want to wait for + * the scan to complete to make sure the scanning thread for this + * controller is completely idle. + **/ +static void remove_from_scan_list(struct ctlr_info *h) +{ + struct ctlr_info *test_h, *tmp_h; + + mutex_lock(&scan_mutex); + list_for_each_entry_safe(test_h, tmp_h, &scan_q, scan_list) { + if (test_h == h) { /* state 2. */ + list_del(&h->scan_list); + complete_all(&h->scan_wait); + mutex_unlock(&scan_mutex); + return; + } + } + if (h->busy_scanning) { /* state 3. */ + mutex_unlock(&scan_mutex); + wait_for_completion(&h->scan_wait); + } else { /* state 1, nothing to do. */ + mutex_unlock(&scan_mutex); + } +} + +/* scan_thread() - kernel thread used to rescan controllers + * @data: Ignored. + * + * A kernel thread used scan for drive topology changes on + * controllers. The thread processes only one controller at a time + * using a queue. Controllers are added to the queue using + * add_to_scan_list() and removed from the queue either after done + * processing or using remove_from_scan_list(). + * + * returns 0. + **/ +static int scan_thread(__attribute__((unused)) void *data) +{ + struct ctlr_info *h; + int host_no; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + if (kthread_should_stop()) + break; + + while (1) { + mutex_lock(&scan_mutex); + if (list_empty(&scan_q)) { + mutex_unlock(&scan_mutex); + break; + } + h = list_entry(scan_q.next, struct ctlr_info, + scan_list); + list_del(&h->scan_list); + h->busy_scanning = 1; + mutex_unlock(&scan_mutex); + host_no = h->scsi_host ? h->scsi_host->host_no : -1; + hpsa_update_scsi_devices(h, host_no); + complete_all(&h->scan_wait); + mutex_lock(&scan_mutex); + h->busy_scanning = 0; + mutex_unlock(&scan_mutex); + } + } + return 0; +} + /* Enqueuing and dequeuing functions for cmdlists. */ static inline void addQ(struct hlist_head *list, struct CommandList *c) { @@ -3269,8 +3394,11 @@ static int __devinit hpsa_init_one(struc if (!h) return -1; + h->busy_initializing = 1; INIT_HLIST_HEAD(&h->cmpQ); INIT_HLIST_HEAD(&h->reqQ); + mutex_init(&h->busy_shutting_down); + init_completion(&h->scan_wait); if (hpsa_pci_init(h, pdev) != 0) goto clean1; @@ -3330,7 +3458,7 @@ static int __devinit hpsa_init_one(struc h->access.set_intr_mask(h, HPSA_INTR_ON); hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ - + h->busy_initializing = 0; return 1; clean4: @@ -3347,6 +3475,7 @@ clean4: free_irq(h->intr[SIMPLE_MODE_INT], h); clean2: clean1: + h->busy_initializing = 0; kfree(h); return -1; } @@ -3387,6 +3516,8 @@ static void __devexit hpsa_remove_one(st return; } h = pci_get_drvdata(pdev); + mutex_lock(&h->busy_shutting_down); + remove_from_scan_list(h); hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ hpsa_shutdown(pdev); iounmap(h->vaddr); @@ -3403,6 +3534,7 @@ static void __devexit hpsa_remove_one(st */ pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); + mutex_unlock(&h->busy_shutting_down); kfree(h); } @@ -3433,12 +3565,23 @@ static struct pci_driver hpsa_pci_driver */ static int __init hpsa_init(void) { - return pci_register_driver(&hpsa_pci_driver); + int err; + /* Start the scan thread */ + hpsa_scan_thread = kthread_run(scan_thread, NULL, "hpsa_scan"); + if (IS_ERR(hpsa_scan_thread)) { + err = PTR_ERR(hpsa_scan_thread); + return -ENODEV; + } + err = pci_register_driver(&hpsa_pci_driver); + if (err) + kthread_stop(hpsa_scan_thread); + return err; } static void __exit hpsa_cleanup(void) { pci_unregister_driver(&hpsa_pci_driver); + kthread_stop(hpsa_scan_thread); } module_init(hpsa_init); diff -puN drivers/scsi/hpsa.h~add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices drivers/scsi/hpsa.h --- a/drivers/scsi/hpsa.h~add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices +++ a/drivers/scsi/hpsa.h @@ -91,6 +91,11 @@ struct ctlr_info { unsigned long *cmd_pool_bits; int nr_allocs; int nr_frees; + int busy_initializing; + int busy_scanning; + struct mutex busy_shutting_down; + struct list_head scan_list; + struct completion scan_wait; struct Scsi_Host *scsi_host; spinlock_t devlock; /* to protect hba[ctlr]->dev[]; */ _ Patches currently in -mm which might be from scameron@xxxxxxxxxxxxxxxxxx are scsi-add-hpsa-driver-for-hp-smart-array-controllers.patch scsi-add-hpsa-driver-for-hp-smart-array-controllers-fix-hpsa_allow_any-test-for-vendor-id.patch scsi-add-hpsa-driver-for-hp-smart-array-controllers-fix.patch hpsa-fix-use-of-unallocated-memory-for-msa2xxx-enclosure-device-data.patch hpsa-allocate-the-correct-amount-of-extra-space-for-the-scsi-host.patch hpsa-use-shost_priv-instead-of-accessing-host-hostdata-directly.patch hpsa-factor-out-command-submission-sequence.patch hpsa-factor-out-some-pci_unmap-code.patch add-thread-to-allow-controllers-to-register-for-rescan-for-new-devices.patch hpsa-allow-device-rescan-to-be-triggered-via-sysfs.patch hpsa-make-hpsa_sdev_attrs-static.patch hpsa-decode-unit-attention-condition-and-retry-commands.patch hpsa-retry-driver-initiated-commands-on-unit-attention.patch hpsa-flush-cache-with-interrupts-still-enabled.patch hpsa-remove-sendcmd-in-no-case-are-we-required-to-poll-for-completions.patch hpsa-make-fill_cmd-return-void.patch hpsa-fix-typo-that-causes-scsi-status-to-be-lost.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html