Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 292985
b: refs/heads/master
c: b1124cd
h: refs/heads/master
i:
  292983: 7938398
v: v3
  • Loading branch information
Dan Williams authored and James Bottomley committed Feb 19, 2012
1 parent 794cda5 commit 9866237
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f8daa6e6d83f60a721752cb53433bfdc1503b45f
refs/heads/master: b1124cd3ec97406c767b90bf7e93ecd2d2915592
2 changes: 1 addition & 1 deletion trunk/drivers/scsi/aic94xx/aic94xx_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
if (time < HZ)
return 0;
/* Wait for discovery to finish */
scsi_flush_work(shost);
sas_drain_work(SHOST_TO_SAS_HA(shost));
return 1;
}

Expand Down
8 changes: 3 additions & 5 deletions trunk/drivers/scsi/isci/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,15 +650,13 @@ static void isci_host_start_complete(struct isci_host *ihost, enum sci_status co

int isci_host_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct isci_host *ihost = SHOST_TO_SAS_HA(shost)->lldd_ha;
struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
struct isci_host *ihost = ha->lldd_ha;

if (test_bit(IHOST_START_PENDING, &ihost->flags))
return 0;

/* todo: use sas_flush_discovery once it is upstream */
scsi_flush_work(shost);

scsi_flush_work(shost);
sas_drain_work(ha);

dev_dbg(&ihost->pdev->dev,
"%s: ihost->status = %d, time = %ld\n",
Expand Down
21 changes: 20 additions & 1 deletion trunk/drivers/scsi/libsas/sas_discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,25 @@ static void sas_revalidate_domain(struct work_struct *work)

/* ---------- Events ---------- */

static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work)
{
/* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */
scsi_queue_work(ha->core.shost, work);
}

static void sas_chain_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_chain_work(ha, work);
spin_unlock_irqrestore(&ha->state_lock, flags);
}
}

int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
{
struct sas_discovery *disc;
Expand All @@ -377,7 +396,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)

BUG_ON(ev >= DISC_NUM_EVENTS);

sas_queue_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha);
sas_chain_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha);

return 0;
}
Expand Down
55 changes: 55 additions & 0 deletions trunk/drivers/scsi/libsas/sas_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,65 @@
*
*/

#include <linux/export.h>
#include <scsi/scsi_host.h>
#include "sas_internal.h"
#include "sas_dump.h"

static 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);
}
}

int sas_drain_work(struct sas_ha_struct *ha)
{
struct workqueue_struct *wq = ha->core.shost->work_q;
struct work_struct *w, *_w;
int err;

err = mutex_lock_interruptible(&ha->drain_mutex);
if (err)
return err;

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);
mutex_unlock(&ha->drain_mutex);

return 0;
}
EXPORT_SYMBOL_GPL(sas_drain_work);

static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
{
BUG_ON(event >= HA_NUM_EVENTS);
Expand Down
9 changes: 6 additions & 3 deletions trunk/drivers/scsi/libsas/sas_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)

set_bit(SAS_HA_REGISTERED, &sas_ha->state);
spin_lock_init(&sas_ha->state_lock);
mutex_init(&sas_ha->drain_mutex);
INIT_LIST_HEAD(&sas_ha->defer_q);

error = sas_register_phys(sas_ha);
if (error) {
Expand Down Expand Up @@ -157,12 +159,13 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
{
unsigned long flags;

/* Set the state to unregistered to avoid further
* events to be queued */
/* Set the state to unregistered to avoid further unchained
* events to be queued
*/
spin_lock_irqsave(&sas_ha->state_lock, flags);
clear_bit(SAS_HA_REGISTERED, &sas_ha->state);
spin_unlock_irqrestore(&sas_ha->state_lock, flags);
scsi_flush_work(sas_ha->core.shost);
sas_drain_work(sas_ha);

sas_unregister_ports(sas_ha);

Expand Down
14 changes: 0 additions & 14 deletions trunk/drivers/scsi/libsas/sas_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@ static inline int sas_smp_host_handler(struct Scsi_Host *shost,
}
#endif

static inline void sas_queue_event(int event, unsigned long *pending,
struct work_struct *work,
struct sas_ha_struct *sas_ha)
{
if (!test_and_set_bit(event, pending)) {
unsigned long flags;

spin_lock_irqsave(&sas_ha->state_lock, flags);
if (test_bit(SAS_HA_REGISTERED, &sas_ha->state))
scsi_queue_work(sas_ha->core.shost, work);
spin_unlock_irqrestore(&sas_ha->state_lock, flags);
}
}

static inline void sas_fill_in_rphy(struct domain_device *dev,
struct sas_rphy *rphy)
{
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/scsi/mvsas/mv_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)
if (mvs_prv->scan_finished == 0)
return 0;

scsi_flush_work(shost);
sas_drain_work(sha);
return 1;
}

Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/scsi/pm8001/pm8001_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,14 @@ void pm8001_scan_start(struct Scsi_Host *shost)

int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);

/* give the phy enabling interrupt event time to come in (1s
* is empirically about all it takes) */
if (time < HZ)
return 0;
/* Wait for discovery to finish */
scsi_flush_work(shost);
sas_drain_work(ha);
return 1;
}

Expand Down
4 changes: 4 additions & 0 deletions trunk/include/scsi/libsas.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,13 +330,16 @@ struct sas_ha_event {

enum sas_ha_state {
SAS_HA_REGISTERED,
SAS_HA_DRAINING,
};

struct sas_ha_struct {
/* private: */
struct sas_ha_event ha_events[HA_NUM_EVENTS];
unsigned long pending;

struct list_head defer_q; /* work queued while draining */
struct mutex drain_mutex;
unsigned long state;
spinlock_t state_lock;

Expand Down Expand Up @@ -657,6 +660,7 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd);
extern void sas_target_destroy(struct scsi_target *);
extern int sas_slave_alloc(struct scsi_device *);
extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
extern int sas_drain_work(struct sas_ha_struct *ha);

extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
struct request *req);
Expand Down

0 comments on commit 9866237

Please sign in to comment.