On Sun, 2006-03-12 at 10:06 -0600, James Bottomley wrote: > This patch moves the discovery and event processing entirely over to > being workqueue based. Additionally, it tries to ensure discovery gets > time to proceed before finishing the module load. There's still a > non-determinism in there since it starts with a port interrupt for a > connected phy after phys are enabled, so there's a ssleep(1) in there to > capture this before the scsi_flush_work() waits for it to complete. Er, OK, this time with the actual correct patch. James diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 924075d..161106e 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -30,6 +30,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/delay.h> #include <scsi/scsi_host.h> @@ -632,6 +633,11 @@ static int __devinit asd_pci_probe(struc goto Err_en_phys; } ASD_DPRINTK("enabled phys\n"); + /* give the phy enabling interrupt event time to come in (1s + * is empirically about all it takes) */ + ssleep(1); + /* Wait for discovery to finish */ + scsi_flush_work(asd_ha->sas_ha.core.shost); return 0; Err_en_phys: diff --git a/drivers/scsi/sas/sas_discover.c b/drivers/scsi/sas/sas_discover.c index 05ff2ed..c10b453 100644 --- a/drivers/scsi/sas/sas_discover.c +++ b/drivers/scsi/sas/sas_discover.c @@ -567,9 +567,13 @@ void sas_unregister_dev(struct domain_de sas_rphy_delete(dev->rphy); } -static void sas_unregister_domain_devices(struct sas_port *port) +static void sas_unregister_domain_devices(void *data) { struct domain_device *dev, *n; + struct sas_port *port = data; + + sas_begin_event(DISCE_PORT_GONE, &port->disc.disc_event_lock, + &port->disc.pending); list_for_each_entry_reverse_safe(dev,n,&port->dev_list,dev_list_node) sas_unregister_dev(dev); @@ -586,16 +590,20 @@ static void sas_unregister_domain_device * Discover process only interrogates devices in order to discover the * domain. */ -static int sas_discover_domain(struct sas_port *port) +static void sas_discover_domain(void *data) { int error = 0; + struct sas_port *port = data; + + sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock, + &port->disc.pending); if (port->port_dev) - return 0; + return ; else { error = sas_get_port_device(port); if (error) - return error; + return; } SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id, @@ -625,13 +633,15 @@ static int sas_discover_domain(struct sa SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, current->pid, error); - - return error; } -static int sas_revalidate_domain(struct sas_port *port) +static void sas_revalidate_domain(void *data) { int res = 0; + struct sas_port *port = data; + + sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock, + &port->disc.pending); SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, current->pid); @@ -640,81 +650,20 @@ static int sas_revalidate_domain(struct SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", port->id, current->pid, res); - return res; } -/* ---------- Threads and events ---------- */ - -static void sas_discover_work_fn(void *_sas_port) -{ - struct sas_port *port = _sas_port; - struct sas_discovery *disc = &port->disc; - - spin_lock(&disc->disc_event_lock); - disc->disc_thread = 1; - while (!disc->disc_thread_quit && !list_empty(&disc->disc_event_list)){ - struct list_head *head = disc->disc_event_list.next; - enum discover_event disc_ev = container_of(head, - struct sas_event, - el)->event; - list_del_init(head); - spin_unlock(&disc->disc_event_lock); - - switch (disc_ev) { - case DISCE_DISCOVER_DOMAIN: - sas_discover_domain(port); - break; - case DISCE_REVALIDATE_DOMAIN: - sas_revalidate_domain(port); - break; - case DISCE_PORT_GONE: - sas_unregister_domain_devices(port); - complete(&port->port_gone_completion); - break; - } - spin_lock(&disc->disc_event_lock); - } - INIT_LIST_HEAD(&disc->disc_event_list); - disc->disc_thread = 0; - spin_unlock(&disc->disc_event_lock); - up(&disc->disc_sema); -} +/* ---------- Events ---------- */ int sas_discover_event(struct sas_port *port, enum discover_event ev) { struct sas_discovery *disc = &port->disc; - spin_lock(&disc->disc_event_lock); - list_move_tail(&disc->disc_events[ev].el, - &disc->disc_event_list); - if (disc->disc_thread) { - spin_unlock(&disc->disc_event_lock); - return 0; - } - down_interruptible(&disc->disc_sema); - disc->disc_thread_quit = 0; - spin_unlock(&disc->disc_event_lock); - - /* The event thread (caller) is single threaded so this is safe. */ - INIT_WORK(&port->work, sas_discover_work_fn, port); - scsi_queue_work(port->ha->core.shost, &port->work); + BUG_ON(ev >= DISC_NUM_EVENTS); - return 0; -} - -void sas_kill_disc_thread(struct sas_port *port) -{ - struct sas_discovery *disc = &port->disc; + sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, + &disc->disc_work[ev], port->ha->core.shost); - spin_lock(&disc->disc_event_lock); - disc->disc_thread_quit = 1; - if (disc->disc_thread) { - spin_unlock(&disc->disc_event_lock); - scsi_flush_work(port->ha->core.shost); - down_interruptible(&disc->disc_sema); - return; - } - spin_unlock(&disc->disc_event_lock); + return 0; } /** @@ -727,17 +676,16 @@ void sas_init_disc(struct sas_discovery { int i; + static void (*sas_event_fns[DISC_NUM_EVENTS])(void *) = { + [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, + [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, + [DISCE_PORT_GONE] = sas_unregister_domain_devices, + }; + spin_lock_init(&disc->disc_event_lock); - INIT_LIST_HEAD(&disc->disc_event_list); - init_MUTEX(&disc->disc_sema); - disc->disc_thread = 0; - disc->disc_thread_quit = 0; - - for (i = 0; i < DISC_NUM_EVENTS; i++) { - struct sas_event *ev = &disc->disc_events[i]; - ev->event = i; - INIT_LIST_HEAD(&ev->el); - } + disc->pending = 0; + for (i = 0; i < DISC_NUM_EVENTS; i++) + INIT_WORK(&disc->disc_work[i], sas_event_fns[i], port); } void sas_unregister_devices(struct sas_ha_struct *sas_ha) diff --git a/drivers/scsi/sas/sas_event.c b/drivers/scsi/sas/sas_event.c index f06f4a3..587368b 100644 --- a/drivers/scsi/sas/sas_event.c +++ b/drivers/scsi/sas/sas_event.c @@ -68,227 +68,50 @@ #include "sas_dump.h" #include <scsi/sas/sas_discover.h> -static void sas_process_phy_event(struct asd_sas_phy *phy) -{ - unsigned long flags; - struct sas_ha_struct *sas_ha = phy->ha; - enum phy_event phy_event; - - spin_lock_irqsave(&sas_ha->event_lock, flags); - while (!list_empty(&phy->phy_event_list)) { - struct list_head *head = phy->phy_event_list.next; - phy_event = container_of(head, struct sas_event, el)->event; - list_del_init(head); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); - - sas_dprint_phye(phy->id, phy_event); - - switch(phy_event) { - case PHYE_LOSS_OF_SIGNAL: - sas_phye_loss_of_signal(phy); - break; - case PHYE_OOB_DONE: - sas_phye_oob_done(phy); - break; - case PHYE_OOB_ERROR: - sas_phye_oob_error(phy); - break; - case PHYE_SPINUP_HOLD: - sas_phye_spinup_hold(phy); - break; - } - spin_lock_irqsave(&sas_ha->event_lock, flags); - } - /* Clear the bit in case we received events in due time. */ - sas_ha->phye_mask &= ~(1 << phy->id); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); -} - -static void sas_process_port_event(struct asd_sas_phy *phy) -{ - unsigned long flags; - struct sas_ha_struct *sas_ha = phy->ha; - enum port_event port_event; - - spin_lock_irqsave(&sas_ha->event_lock, flags); - while (!list_empty(&phy->port_event_list)) { - struct list_head *head = phy->port_event_list.next; - port_event = container_of(head, struct sas_event, el)->event; - list_del_init(head); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); - - sas_dprint_porte(phy->id, port_event); - - switch (port_event) { - case PORTE_BYTES_DMAED: - sas_porte_bytes_dmaed(phy); - break; - case PORTE_BROADCAST_RCVD: - sas_porte_broadcast_rcvd(phy); - break; - case PORTE_LINK_RESET_ERR: - sas_porte_link_reset_err(phy); - break; - case PORTE_TIMER_EVENT: - sas_porte_timer_event(phy); - break; - case PORTE_HARD_RESET: - sas_porte_hard_reset(phy); - break; - } - spin_lock_irqsave(&sas_ha->event_lock, flags); - } - /* Clear the bit in case we received events in due time. */ - sas_ha->porte_mask &= ~(1 << phy->id); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); -} - -static void sas_process_ha_event(struct sas_ha_struct *sas_ha) -{ - unsigned long flags; - enum ha_event ha_event; - - spin_lock_irqsave(&sas_ha->event_lock, flags); - while (!list_empty(&sas_ha->ha_event_list)) { - struct list_head *head = sas_ha->ha_event_list.next; - ha_event = container_of(head, struct sas_event, el)->event; - list_del_init(head); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); - - sas_dprint_hae(sas_ha, ha_event); - - switch (ha_event) { - case HAE_RESET: - sas_hae_reset(sas_ha); - break; - } - spin_lock_irqsave(&sas_ha->event_lock, flags); - } - spin_unlock_irqrestore(&sas_ha->event_lock, flags); -} - -static void sas_process_events(struct sas_ha_struct *sas_ha) -{ - unsigned long flags; - u32 porte_mask, phye_mask; - int p; - - spin_lock_irqsave(&sas_ha->event_lock, flags); - phye_mask = sas_ha->phye_mask; - sas_ha->phye_mask = 0; - spin_unlock_irqrestore(&sas_ha->event_lock, flags); - - for (p = 0; phye_mask != 0; phye_mask >>= 1, p++) - if (phye_mask & 01) - sas_process_phy_event(sas_ha->sas_phy[p]); - - spin_lock_irqsave(&sas_ha->event_lock, flags); - porte_mask = sas_ha->porte_mask; - sas_ha->porte_mask = 0; - spin_unlock_irqrestore(&sas_ha->event_lock, flags); - - for (p = 0; porte_mask != 0; porte_mask >>= 1, p++) - if (porte_mask & 01) - sas_process_port_event(sas_ha->sas_phy[p]); - - sas_process_ha_event(sas_ha); -} - static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) { - unsigned long flags; + BUG_ON(event >= HA_NUM_EVENTS); - spin_lock_irqsave(&sas_ha->event_lock, flags); - list_move_tail(&sas_ha->ha_events[event].el, &sas_ha->ha_event_list); - up(&sas_ha->event_sema); - spin_unlock_irqrestore(&sas_ha->event_lock, flags); + sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, + &sas_ha->ha_events[event], sas_ha->core.shost); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) { struct sas_ha_struct *ha = phy->ha; - unsigned long flags; - spin_lock_irqsave(&ha->event_lock, flags); - list_move_tail(&phy->port_events[event].el, &phy->port_event_list); - ha->porte_mask |= (1 << phy->id); - up(&ha->event_sema); - spin_unlock_irqrestore(&ha->event_lock, flags); + BUG_ON(event >= PORT_NUM_EVENTS); + + sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, + &phy->port_events[event], ha->core.shost); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) { struct sas_ha_struct *ha = phy->ha; - unsigned long flags; - - spin_lock_irqsave(&ha->event_lock, flags); - list_move_tail(&phy->phy_events[event].el, &phy->phy_event_list); - ha->phye_mask |= (1 << phy->id); - up(&ha->event_sema); - spin_unlock_irqrestore(&ha->event_lock, flags); -} -static DECLARE_COMPLETION(event_th_comp); + BUG_ON(event >= PHY_NUM_EVENTS); -static int sas_event_thread(void *_sas_ha) -{ - struct sas_ha_struct *sas_ha = _sas_ha; - - daemonize("sas_event_%d", sas_ha->core.shost->host_no); - current->flags |= PF_NOFREEZE; - - complete(&event_th_comp); - - while (1) { - down_interruptible(&sas_ha->event_sema); - if (sas_ha->event_thread_kill) - break; - sas_process_events(sas_ha); - } - - complete(&event_th_comp); - - return 0; + sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, + &phy->phy_events[event], ha->core.shost); } -int sas_start_event_thread(struct sas_ha_struct *sas_ha) +int sas_init_events(struct sas_ha_struct *sas_ha) { - int i; + static void (*sas_ha_event_fns[HA_NUM_EVENTS])(void *) = { + [HAE_RESET] = sas_hae_reset, + }; - init_MUTEX_LOCKED(&sas_ha->event_sema); - sas_ha->event_thread_kill = 0; + int i; spin_lock_init(&sas_ha->event_lock); - INIT_LIST_HEAD(&sas_ha->ha_event_list); - sas_ha->porte_mask = 0; - sas_ha->phye_mask = 0; - - for (i = 0; i < HA_NUM_EVENTS; i++) { - struct sas_event *ev = &sas_ha->ha_events[i]; - ev->event = i; - INIT_LIST_HEAD(&ev->el); - } + + for (i = 0; i < HA_NUM_EVENTS; i++) + INIT_WORK(&sas_ha->ha_events[i], sas_ha_event_fns[i], sas_ha); sas_ha->notify_ha_event = notify_ha_event; sas_ha->notify_port_event = notify_port_event; sas_ha->notify_phy_event = notify_phy_event; - i = kernel_thread(sas_event_thread, sas_ha, 0); - if (i >= 0) - wait_for_completion(&event_th_comp); - - return i < 0 ? i : 0; -} - -void sas_kill_event_thread(struct sas_ha_struct *sas_ha) -{ - int i; - - init_completion(&event_th_comp); - sas_ha->event_thread_kill = 1; - up(&sas_ha->event_sema); - wait_for_completion(&event_th_comp); - - for (i = 0; i < sas_ha->num_phys; i++) - sas_kill_disc_thread(sas_ha->sas_port[i]); + return 0; } diff --git a/drivers/scsi/sas/sas_init.c b/drivers/scsi/sas/sas_init.c index 4f89cf5..39d4f99 100644 --- a/drivers/scsi/sas/sas_init.c +++ b/drivers/scsi/sas/sas_init.c @@ -40,9 +40,12 @@ kmem_cache_t *sas_task_cache; /* ---------- HA events ---------- */ -void sas_hae_reset(struct sas_ha_struct *sas_ha) +void sas_hae_reset(void *data) { - ; + struct sas_ha_struct *ha = data; + + sas_begin_event(HAE_RESET, &ha->event_lock, + &ha->pending); } int sas_register_ha(struct sas_ha_struct *sas_ha, @@ -77,7 +80,7 @@ int sas_register_ha(struct sas_ha_struct goto Undo_phys; } - error = sas_start_event_thread(sas_ha); + error = sas_init_events(sas_ha); if (error) { printk(KERN_NOTICE "couldn't start event thread:%d\n", error); goto Undo_ports; @@ -92,8 +95,6 @@ int sas_register_ha(struct sas_ha_struct } } - /* wait for discovery to finish */ - scsi_flush_work(sas_ha->core.shost); return 0; Undo_ports: @@ -113,8 +114,6 @@ int sas_unregister_ha(struct sas_ha_stru sas_shutdown_queue(sas_ha); } - sas_kill_event_thread(sas_ha); - sas_unregister_ports(sas_ha); sas_unregister_scsi_host(sas_ha); diff --git a/drivers/scsi/sas/sas_internal.h b/drivers/scsi/sas/sas_internal.h index bc9c1cb..90d772e 100644 --- a/drivers/scsi/sas/sas_internal.h +++ b/drivers/scsi/sas/sas_internal.h @@ -28,6 +28,7 @@ #define _SAS_INTERNAL_H_ #include <scsi/sas/sas_class.h> +#include <scsi/scsi_host.h> #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__) @@ -53,29 +54,43 @@ extern int sas_register_scsi_host(struc struct scsi_transport_template *); void sas_unregister_scsi_host(struct sas_ha_struct *sas_ha); -int sas_start_event_thread(struct sas_ha_struct *sas_ha); -void sas_kill_event_thread(struct sas_ha_struct *sas_ha); - int sas_init_queue(struct sas_ha_struct *sas_ha); +int sas_init_events(struct sas_ha_struct *sas_ha); void sas_shutdown_queue(struct sas_ha_struct *sas_ha); -void sas_phye_loss_of_signal(struct asd_sas_phy *phy); -void sas_phye_oob_done(struct asd_sas_phy *phy); -void sas_phye_oob_error(struct asd_sas_phy *phy); -void sas_phye_spinup_hold(struct asd_sas_phy *phy); - void sas_deform_port(struct asd_sas_phy *phy); -void sas_porte_bytes_dmaed(struct asd_sas_phy *phy); -void sas_porte_broadcast_rcvd(struct asd_sas_phy *phy); -void sas_porte_link_reset_err(struct asd_sas_phy *phy); -void sas_porte_timer_event(struct asd_sas_phy *phy); -void sas_porte_hard_reset(struct asd_sas_phy *phy); - -int sas_reserve_free_id(struct sas_port *port); -void sas_reserve_scsi_id(struct sas_port *port, int id); -void sas_release_scsi_id(struct sas_port *port, int id); - -void sas_hae_reset(struct sas_ha_struct *sas_ha); +void sas_porte_bytes_dmaed(void *); +void sas_porte_broadcast_rcvd(void *); +void sas_porte_link_reset_err(void *); +void sas_porte_timer_event(void *); +void sas_porte_hard_reset(void *); + +void sas_hae_reset(void *); + +static inline void sas_queue_event(int event, spinlock_t *lock, u32 *pending, + struct work_struct *work, + struct Scsi_Host *shost) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + if (*pending & (1 << event)) { + spin_unlock_irqrestore(lock, flags); + return; + } + *pending |= (1 << event); + spin_unlock_irqrestore(lock, flags); + scsi_queue_work(shost, work); +} + +static inline void sas_begin_event(int event, spinlock_t *lock, u32 *pending) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + *pending &= ~(1 << event); + spin_unlock_irqrestore(lock, flags); +} #endif /* _SAS_INTERNAL_H_ */ diff --git a/drivers/scsi/sas/sas_phy.c b/drivers/scsi/sas/sas_phy.c index 6014351..bc2834c 100644 --- a/drivers/scsi/sas/sas_phy.c +++ b/drivers/scsi/sas/sas_phy.c @@ -29,22 +29,34 @@ /* ---------- Phy events ---------- */ -void sas_phye_loss_of_signal(struct asd_sas_phy *phy) +static void sas_phye_loss_of_signal(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, + &phy->phy_events_pending); phy->error = 0; sas_deform_port(phy); } -void sas_phye_oob_done(struct asd_sas_phy *phy) +static void sas_phye_oob_done(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PHYE_OOB_DONE, &phy->ha->event_lock, + &phy->phy_events_pending); phy->error = 0; } -void sas_phye_oob_error(struct asd_sas_phy *phy) +static void sas_phye_oob_error(void *data) { + struct asd_sas_phy *phy = data; struct sas_ha_struct *sas_ha = phy->ha; struct sas_port *port = phy->port; + sas_begin_event(PHYE_OOB_ERROR, &phy->ha->event_lock, + &phy->phy_events_pending); + sas_deform_port(phy); if (!port && phy->enabled && sas_ha->lldd_control_phy) { @@ -64,10 +76,14 @@ void sas_phye_oob_error(struct asd_sas_p } } -void sas_phye_spinup_hold(struct asd_sas_phy *phy) +static void sas_phye_spinup_hold(void *data) { + struct asd_sas_phy *phy = data; struct sas_ha_struct *sas_ha = phy->ha; + sas_begin_event(PHYE_SPINUP_HOLD, &phy->ha->event_lock, + &phy->phy_events_pending); + phy->error = 0; sas_ha->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD); } @@ -78,6 +94,21 @@ int sas_register_phys(struct sas_ha_stru { int i; + static void (*sas_phy_event_fns[PHY_NUM_EVENTS])(void *) = { + [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal, + [PHYE_OOB_DONE] = sas_phye_oob_done, + [PHYE_OOB_ERROR] = sas_phye_oob_error, + [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold, + }; + + static void (*sas_port_event_fns[PORT_NUM_EVENTS])(void *) = { + [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed, + [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd, + [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err, + [PORTE_TIMER_EVENT] = sas_porte_timer_event, + [PORTE_HARD_RESET] = sas_porte_hard_reset, + }; + /* Now register the phys. */ for (i = 0; i < sas_ha->num_phys; i++) { int k; @@ -85,18 +116,13 @@ int sas_register_phys(struct sas_ha_stru phy->error = 0; INIT_LIST_HEAD(&phy->port_phy_el); - INIT_LIST_HEAD(&phy->port_event_list); - INIT_LIST_HEAD(&phy->phy_event_list); - for (k = 0; k < PORT_NUM_EVENTS; k++) { - struct sas_event *ev = &phy->port_events[k]; - ev->event = k; - INIT_LIST_HEAD(&ev->el); - } - for (k = 0; k < PHY_NUM_EVENTS; k++) { - struct sas_event *ev = &phy->phy_events[k]; - ev->event = k; - INIT_LIST_HEAD(&ev->el); - } + for (k = 0; k < PORT_NUM_EVENTS; k++) + INIT_WORK(&phy->port_events[k], sas_port_event_fns[k], + phy); + + for (k = 0; k < PHY_NUM_EVENTS; k++) + INIT_WORK(&phy->phy_events[k], sas_phy_event_fns[k], + phy); phy->port = NULL; phy->ha = sas_ha; spin_lock_init(&phy->frame_rcvd_lock); diff --git a/drivers/scsi/sas/sas_port.c b/drivers/scsi/sas/sas_port.c index 53117e4..6177423 100644 --- a/drivers/scsi/sas/sas_port.c +++ b/drivers/scsi/sas/sas_port.c @@ -167,15 +167,24 @@ void sas_deform_port(struct asd_sas_phy /* ---------- SAS port events ---------- */ -void sas_porte_bytes_dmaed(struct asd_sas_phy *phy) +void sas_porte_bytes_dmaed(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock, + &phy->port_events_pending); + sas_form_port(phy); } -void sas_porte_broadcast_rcvd(struct asd_sas_phy *phy) +void sas_porte_broadcast_rcvd(void *data) { unsigned long flags; u32 prim; + struct asd_sas_phy *phy = data; + + sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock, + &phy->port_events_pending); spin_lock_irqsave(&phy->sas_prim_lock, flags); prim = phy->sas_prim; @@ -185,18 +194,33 @@ void sas_porte_broadcast_rcvd(struct asd sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN); } -void sas_porte_link_reset_err(struct asd_sas_phy *phy) +void sas_porte_link_reset_err(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, + &phy->port_events_pending); + sas_deform_port(phy); } -void sas_porte_timer_event(struct asd_sas_phy *phy) +void sas_porte_timer_event(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, + &phy->port_events_pending); + sas_deform_port(phy); } -void sas_porte_hard_reset(struct asd_sas_phy *phy) +void sas_porte_hard_reset(void *data) { + struct asd_sas_phy *phy = data; + + sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, + &phy->port_events_pending); + sas_deform_port(phy); } diff --git a/include/scsi/sas/sas_class.h b/include/scsi/sas/sas_class.h index f7b8a26..e275fb6 100644 --- a/include/scsi/sas/sas_class.h +++ b/include/scsi/sas/sas_class.h @@ -86,21 +86,17 @@ enum discover_event { }; #define DISC_NUM_EVENTS 3 -struct sas_event { - int event; - struct list_head el; -}; - /* The phy pretty much is controlled by the LLDD. * The class only reads those fields. */ struct asd_sas_phy { /* private: */ /* protected by ha->event_lock */ - struct list_head port_event_list; - struct list_head phy_event_list; - struct sas_event port_events[PORT_NUM_EVENTS]; - struct sas_event phy_events[PHY_NUM_EVENTS]; + struct work_struct port_events[PORT_NUM_EVENTS]; + struct work_struct phy_events[PHY_NUM_EVENTS]; + + u32 port_events_pending; + u32 phy_events_pending; int error; @@ -142,12 +138,8 @@ struct sas_port; struct sas_discovery { spinlock_t disc_event_lock; - unsigned disc_thread_quit:1; - unsigned disc_thread:1; - struct list_head disc_event_list; - struct sas_event disc_events[DISC_NUM_EVENTS]; - struct semaphore disc_sema; - + struct work_struct disc_work[DISC_NUM_EVENTS]; + u32 pending; u8 fanout_sas_addr[8]; u8 eeds_a[8]; u8 eeds_b[8]; @@ -207,14 +199,9 @@ struct scsi_core { struct sas_ha_struct { /* private: */ - struct semaphore event_sema; - int event_thread_kill; - spinlock_t event_lock; - struct list_head ha_event_list; - struct sas_event ha_events[HA_NUM_EVENTS]; - u32 porte_mask; /* mask of phys for port events */ - u32 phye_mask; /* mask of phys for phy events */ + struct work_struct ha_events[HA_NUM_EVENTS]; + u32 pending; struct scsi_core core; diff --git a/include/scsi/sas/sas_discover.h b/include/scsi/sas/sas_discover.h index 2aa56f3..df0cdcb 100644 --- a/include/scsi/sas/sas_discover.h +++ b/include/scsi/sas/sas_discover.h @@ -171,7 +171,6 @@ static inline void sas_init_dev(struct d } void sas_init_disc(struct sas_discovery *disc, struct sas_port *port); -void sas_kill_disc_thread(struct sas_port *port); int sas_discover_event(struct sas_port *sas_port, enum discover_event ev); int sas_discover_sata(struct domain_device *dev); - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html