diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2007-01-11 17:15:43 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-01-13 17:21:53 -0500 |
commit | 6b0efb8516a5298e12033df61f9e0c376a306adb (patch) | |
tree | 3f63587167905e86de330fb28219dbfb309aad9a | |
parent | 980fa2f9d64b9be96107c89e165953ace311af54 (diff) |
[SCSI] libsas: Add SAS_HA state flags to avoid queueing events while unloading
Track sas_ha_struct state so that we ignore events that come in while
we're shutting things down.
Signed-off-by: Malahal Naineni <malahal@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_event.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 12 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_internal.h | 9 | ||||
-rw-r--r-- | include/scsi/libsas.h | 8 |
5 files changed, 31 insertions, 6 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 21f538e4a0b5..b6ba0e053d1a 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
@@ -753,7 +753,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) | |||
753 | BUG_ON(ev >= DISC_NUM_EVENTS); | 753 | BUG_ON(ev >= DISC_NUM_EVENTS); |
754 | 754 | ||
755 | sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, | 755 | sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, |
756 | &disc->disc_work[ev].work, port->ha->core.shost); | 756 | &disc->disc_work[ev].work, port->ha); |
757 | 757 | ||
758 | return 0; | 758 | return 0; |
759 | } | 759 | } |
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index d83392ee6823..9db30fb5caf2 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c | |||
@@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) | |||
31 | BUG_ON(event >= HA_NUM_EVENTS); | 31 | BUG_ON(event >= HA_NUM_EVENTS); |
32 | 32 | ||
33 | sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, | 33 | sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, |
34 | &sas_ha->ha_events[event].work, sas_ha->core.shost); | 34 | &sas_ha->ha_events[event].work, sas_ha); |
35 | } | 35 | } |
36 | 36 | ||
37 | static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) | 37 | static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) |
@@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) | |||
41 | BUG_ON(event >= PORT_NUM_EVENTS); | 41 | BUG_ON(event >= PORT_NUM_EVENTS); |
42 | 42 | ||
43 | sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, | 43 | sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, |
44 | &phy->port_events[event].work, ha->core.shost); | 44 | &phy->port_events[event].work, ha); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) | 47 | static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) |
@@ -51,7 +51,7 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) | |||
51 | BUG_ON(event >= PHY_NUM_EVENTS); | 51 | BUG_ON(event >= PHY_NUM_EVENTS); |
52 | 52 | ||
53 | sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, | 53 | sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, |
54 | &phy->phy_events[event].work, ha->core.shost); | 54 | &phy->phy_events[event].work, ha); |
55 | } | 55 | } |
56 | 56 | ||
57 | int sas_init_events(struct sas_ha_struct *sas_ha) | 57 | int sas_init_events(struct sas_ha_struct *sas_ha) |
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 4df73d69bb3c..965698c8b7bf 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c | |||
@@ -87,6 +87,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) | |||
87 | else if (sas_ha->lldd_queue_size == -1) | 87 | else if (sas_ha->lldd_queue_size == -1) |
88 | sas_ha->lldd_queue_size = 128; /* Sanity */ | 88 | sas_ha->lldd_queue_size = 128; /* Sanity */ |
89 | 89 | ||
90 | sas_ha->state = SAS_HA_REGISTERED; | ||
91 | spin_lock_init(&sas_ha->state_lock); | ||
92 | |||
90 | error = sas_register_phys(sas_ha); | 93 | error = sas_register_phys(sas_ha); |
91 | if (error) { | 94 | if (error) { |
92 | printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); | 95 | printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); |
@@ -127,6 +130,15 @@ Undo_phys: | |||
127 | 130 | ||
128 | int sas_unregister_ha(struct sas_ha_struct *sas_ha) | 131 | int sas_unregister_ha(struct sas_ha_struct *sas_ha) |
129 | { | 132 | { |
133 | unsigned long flags; | ||
134 | |||
135 | /* Set the state to unregistered to avoid further | ||
136 | * events to be queued */ | ||
137 | spin_lock_irqsave(&sas_ha->state_lock, flags); | ||
138 | sas_ha->state = SAS_HA_UNREGISTERED; | ||
139 | spin_unlock_irqrestore(&sas_ha->state_lock, flags); | ||
140 | scsi_flush_work(sas_ha->core.shost); | ||
141 | |||
130 | sas_unregister_ports(sas_ha); | 142 | sas_unregister_ports(sas_ha); |
131 | 143 | ||
132 | if (sas_ha->lldd_max_execute_num > 1) { | 144 | if (sas_ha->lldd_max_execute_num > 1) { |
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 137d7e496b6d..a78638df2018 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h | |||
@@ -80,7 +80,7 @@ void sas_hae_reset(struct work_struct *work); | |||
80 | static inline void sas_queue_event(int event, spinlock_t *lock, | 80 | static inline void sas_queue_event(int event, spinlock_t *lock, |
81 | unsigned long *pending, | 81 | unsigned long *pending, |
82 | struct work_struct *work, | 82 | struct work_struct *work, |
83 | struct Scsi_Host *shost) | 83 | struct sas_ha_struct *sas_ha) |
84 | { | 84 | { |
85 | unsigned long flags; | 85 | unsigned long flags; |
86 | 86 | ||
@@ -91,7 +91,12 @@ static inline void sas_queue_event(int event, spinlock_t *lock, | |||
91 | } | 91 | } |
92 | __set_bit(event, pending); | 92 | __set_bit(event, pending); |
93 | spin_unlock_irqrestore(lock, flags); | 93 | spin_unlock_irqrestore(lock, flags); |
94 | scsi_queue_work(shost, work); | 94 | |
95 | spin_lock_irqsave(&sas_ha->state_lock, flags); | ||
96 | if (sas_ha->state != SAS_HA_UNREGISTERED) { | ||
97 | scsi_queue_work(sas_ha->core.shost, work); | ||
98 | } | ||
99 | spin_unlock_irqrestore(&sas_ha->state_lock, flags); | ||
95 | } | 100 | } |
96 | 101 | ||
97 | static inline void sas_begin_event(int event, spinlock_t *lock, | 102 | static inline void sas_begin_event(int event, spinlock_t *lock, |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index c83426344e8f..ca393929c10b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -323,12 +323,20 @@ struct sas_ha_event { | |||
323 | struct sas_ha_struct *ha; | 323 | struct sas_ha_struct *ha; |
324 | }; | 324 | }; |
325 | 325 | ||
326 | enum sas_ha_state { | ||
327 | SAS_HA_REGISTERED, | ||
328 | SAS_HA_UNREGISTERED | ||
329 | }; | ||
330 | |||
326 | struct sas_ha_struct { | 331 | struct sas_ha_struct { |
327 | /* private: */ | 332 | /* private: */ |
328 | spinlock_t event_lock; | 333 | spinlock_t event_lock; |
329 | struct sas_ha_event ha_events[HA_NUM_EVENTS]; | 334 | struct sas_ha_event ha_events[HA_NUM_EVENTS]; |
330 | unsigned long pending; | 335 | unsigned long pending; |
331 | 336 | ||
337 | enum sas_ha_state state; | ||
338 | spinlock_t state_lock; | ||
339 | |||
332 | struct scsi_core core; | 340 | struct scsi_core core; |
333 | 341 | ||
334 | /* public: */ | 342 | /* public: */ |