Skip to content

Commit

Permalink
[SCSI] aic94xx: Lock DDB read/write accesses
Browse files Browse the repository at this point in the history
Extend the use of the DDB lock to include all DDB accesses, because
DDB updates now occur from multiple threads.  This fixes the SMP timeout
problems that we were occasionally seeing with a x260, because the
controller got confused when the DDBs got corrupted.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Darrick J. Wong authored and James Bottomley committed Jan 13, 2007
1 parent 3b709df commit 57ba07d
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 8 deletions.
16 changes: 8 additions & 8 deletions drivers/scsi/aic94xx/aic94xx_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,14 @@

static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
{
unsigned long flags;
int ddb, i;

spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
ddb = FIND_FREE_DDB(asd_ha);
if (ddb >= asd_ha->hw_prof.max_ddbs) {
ddb = -ENOMEM;
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
goto out;
}
SET_DDB(ddb, asd_ha);
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);

for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
asd_ddbsite_write_dword(asd_ha, ddb, i, 0);
Expand Down Expand Up @@ -77,14 +73,10 @@ static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)

static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
{
unsigned long flags;

if (!ddb || ddb >= 0xFFFF)
return;
asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED);
spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
CLEAR_DDB(ddb, asd_ha);
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
}

static inline void asd_set_ddb_type(struct domain_device *dev)
Expand Down Expand Up @@ -320,8 +312,11 @@ static int asd_init_sata_pm_ddb(struct domain_device *dev)

int asd_dev_found(struct domain_device *dev)
{
unsigned long flags;
int res = 0;
struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;

spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
switch (dev->dev_type) {
case SATA_PM:
res = asd_init_sata_pm_ddb(dev);
Expand All @@ -335,19 +330,24 @@ int asd_dev_found(struct domain_device *dev)
else
res = asd_init_initiator_ddb(dev);
}
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);

return res;
}

void asd_dev_gone(struct domain_device *dev)
{
int ddb, sister_ddb;
unsigned long flags;
struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;

spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
ddb = (int) (unsigned long) dev->lldd_dev;
sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB);

if (sister_ddb != 0xFFFF)
asd_free_ddb(asd_ha, sister_ddb);
asd_free_ddb(asd_ha, ddb);
dev->lldd_dev = NULL;
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
}
3 changes: 3 additions & 0 deletions drivers/scsi/aic94xx/aic94xx_seq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,9 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
u8 phy_is_up;
u8 mask;
int i, err;
unsigned long flags;

spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
for_each_phy(phy_mask, mask, i)
asd_ddbsite_write_byte(asd_ha, 0,
offsetof(struct asd_ddb_seq_shared,
Expand All @@ -1415,6 +1417,7 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
break;
}
}
spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);

if (err)
asd_printk("couldn't update DDB 0:error:%d\n", err);
Expand Down

0 comments on commit 57ba07d

Please sign in to comment.