diff options
author | Tejun Heo <tj@kernel.org> | 2012-04-01 12:30:01 -0700 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-04-01 12:55:00 -0700 |
commit | 959d851caa48829eb85cb85aa949fd6b4c5d5bc6 (patch) | |
tree | 3ba9c94ec346275fb44c4f0d1cd2537cdff8d811 /drivers/scsi/libsas/sas_event.c | |
parent | a5567932fc926739e29e98487128080f40c61710 (diff) | |
parent | 48ddbe194623ae089cc0576e60363f2d2e85662a (diff) |
Merge branch 'for-3.5' of ../cgroup into block/for-3.5/core-merged
cgroup/for-3.5 contains the following changes which blk-cgroup needs
to proceed with the on-going cleanup.
* Dynamic addition and removal of cftypes to make config/stat file
handling modular for policies.
* cgroup removal update to not wait for css references to drain to fix
blkcg removal hang caused by cfq caching cfqgs.
Pull in cgroup/for-3.5 into block/for-3.5/core. This causes the
following conflicts in block/blk-cgroup.c.
* 761b3ef50e "cgroup: remove cgroup_subsys argument from callbacks"
conflicts with blkiocg_pre_destroy() addition and blkiocg_attach()
removal. Resolved by removing @subsys from all subsys methods.
* 676f7c8f84 "cgroup: relocate cftype and cgroup_subsys definitions in
controllers" conflicts with ->pre_destroy() and ->attach() updates
and removal of modular config. Resolved by dropping forward
declarations of the methods and applying updates to the relocated
blkio_subsys.
* 4baf6e3325 "cgroup: convert all non-memcg controllers to the new
cftype interface" builds upon the previous item. Resolved by adding
->base_cftypes to the relocated blkio_subsys.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/scsi/libsas/sas_event.c')
-rw-r--r-- | drivers/scsi/libsas/sas_event.c | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 9db30fb5caf..16639bbae62 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -22,15 +22,103 @@ * */ +#include <linux/export.h> #include <scsi/scsi_host.h> #include "sas_internal.h" #include "sas_dump.h" +void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work) +{ + if (!test_bit(SAS_HA_REGISTERED, &ha->state)) + return; + + if (test_bit(SAS_HA_DRAINING, &ha->state)) + list_add(&work->entry, &ha->defer_q); + else + scsi_queue_work(ha->core.shost, work); +} + +static void sas_queue_event(int event, unsigned long *pending, + struct work_struct *work, + struct sas_ha_struct *ha) +{ + if (!test_and_set_bit(event, pending)) { + unsigned long flags; + + spin_lock_irqsave(&ha->state_lock, flags); + sas_queue_work(ha, work); + spin_unlock_irqrestore(&ha->state_lock, flags); + } +} + + +void __sas_drain_work(struct sas_ha_struct *ha) +{ + struct workqueue_struct *wq = ha->core.shost->work_q; + struct work_struct *w, *_w; + + set_bit(SAS_HA_DRAINING, &ha->state); + /* flush submitters */ + spin_lock_irq(&ha->state_lock); + spin_unlock_irq(&ha->state_lock); + + drain_workqueue(wq); + + spin_lock_irq(&ha->state_lock); + clear_bit(SAS_HA_DRAINING, &ha->state); + list_for_each_entry_safe(w, _w, &ha->defer_q, entry) { + list_del_init(&w->entry); + sas_queue_work(ha, w); + } + spin_unlock_irq(&ha->state_lock); +} + +int sas_drain_work(struct sas_ha_struct *ha) +{ + int err; + + err = mutex_lock_interruptible(&ha->drain_mutex); + if (err) + return err; + if (test_bit(SAS_HA_REGISTERED, &ha->state)) + __sas_drain_work(ha); + mutex_unlock(&ha->drain_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(sas_drain_work); + +void sas_disable_revalidation(struct sas_ha_struct *ha) +{ + mutex_lock(&ha->disco_mutex); + set_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state); + mutex_unlock(&ha->disco_mutex); +} + +void sas_enable_revalidation(struct sas_ha_struct *ha) +{ + int i; + + mutex_lock(&ha->disco_mutex); + clear_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state); + for (i = 0; i < ha->num_phys; i++) { + struct asd_sas_port *port = ha->sas_port[i]; + const int ev = DISCE_REVALIDATE_DOMAIN; + struct sas_discovery *d = &port->disc; + + if (!test_and_clear_bit(ev, &d->pending)) + continue; + + sas_queue_event(ev, &d->pending, &d->disc_work[ev].work, ha); + } + mutex_unlock(&ha->disco_mutex); +} + static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) { BUG_ON(event >= HA_NUM_EVENTS); - sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, + sas_queue_event(event, &sas_ha->pending, &sas_ha->ha_events[event].work, sas_ha); } @@ -40,7 +128,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); - sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, + sas_queue_event(event, &phy->port_events_pending, &phy->port_events[event].work, ha); } @@ -50,7 +138,7 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); - sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, + sas_queue_event(event, &phy->phy_events_pending, &phy->phy_events[event].work, ha); } @@ -62,8 +150,6 @@ int sas_init_events(struct sas_ha_struct *sas_ha) int i; - spin_lock_init(&sas_ha->event_lock); - for (i = 0; i < HA_NUM_EVENTS; i++) { INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]); sas_ha->ha_events[i].ha = sas_ha; |