diff options
| -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: */ |
