aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx/aic94xx_dev.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2007-01-11 17:15:32 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-01-13 17:19:42 -0500
commit57ba07dc54b7657e69fe8ac42d83df21e415c85b (patch)
tree493da7233a4d7116c6302099a81c6c087b106165 /drivers/scsi/aic94xx/aic94xx_dev.c
parent3b709df5f7c83b6b0907217a248a1414a37ffcb6 (diff)
[SCSI] aic94xx: Lock DDB read/write accesses
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>
Diffstat (limited to 'drivers/scsi/aic94xx/aic94xx_dev.c')
-rw-r--r--drivers/scsi/aic94xx/aic94xx_dev.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 6f8901b748f7..c520e5b41fb5 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -37,18 +37,14 @@
37 37
38static inline int asd_get_ddb(struct asd_ha_struct *asd_ha) 38static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
39{ 39{
40 unsigned long flags;
41 int ddb, i; 40 int ddb, i;
42 41
43 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
44 ddb = FIND_FREE_DDB(asd_ha); 42 ddb = FIND_FREE_DDB(asd_ha);
45 if (ddb >= asd_ha->hw_prof.max_ddbs) { 43 if (ddb >= asd_ha->hw_prof.max_ddbs) {
46 ddb = -ENOMEM; 44 ddb = -ENOMEM;
47 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
48 goto out; 45 goto out;
49 } 46 }
50 SET_DDB(ddb, asd_ha); 47 SET_DDB(ddb, asd_ha);
51 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
52 48
53 for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) 49 for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)
54 asd_ddbsite_write_dword(asd_ha, ddb, i, 0); 50 asd_ddbsite_write_dword(asd_ha, ddb, i, 0);
@@ -77,14 +73,10 @@ out:
77 73
78static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) 74static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
79{ 75{
80 unsigned long flags;
81
82 if (!ddb || ddb >= 0xFFFF) 76 if (!ddb || ddb >= 0xFFFF)
83 return; 77 return;
84 asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); 78 asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED);
85 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
86 CLEAR_DDB(ddb, asd_ha); 79 CLEAR_DDB(ddb, asd_ha);
87 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
88} 80}
89 81
90static inline void asd_set_ddb_type(struct domain_device *dev) 82static inline void asd_set_ddb_type(struct domain_device *dev)
@@ -320,8 +312,11 @@ out:
320 312
321int asd_dev_found(struct domain_device *dev) 313int asd_dev_found(struct domain_device *dev)
322{ 314{
315 unsigned long flags;
323 int res = 0; 316 int res = 0;
317 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
324 318
319 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
325 switch (dev->dev_type) { 320 switch (dev->dev_type) {
326 case SATA_PM: 321 case SATA_PM:
327 res = asd_init_sata_pm_ddb(dev); 322 res = asd_init_sata_pm_ddb(dev);
@@ -335,14 +330,18 @@ int asd_dev_found(struct domain_device *dev)
335 else 330 else
336 res = asd_init_initiator_ddb(dev); 331 res = asd_init_initiator_ddb(dev);
337 } 332 }
333 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
334
338 return res; 335 return res;
339} 336}
340 337
341void asd_dev_gone(struct domain_device *dev) 338void asd_dev_gone(struct domain_device *dev)
342{ 339{
343 int ddb, sister_ddb; 340 int ddb, sister_ddb;
341 unsigned long flags;
344 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 342 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
345 343
344 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
346 ddb = (int) (unsigned long) dev->lldd_dev; 345 ddb = (int) (unsigned long) dev->lldd_dev;
347 sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); 346 sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB);
348 347
@@ -350,4 +349,5 @@ void asd_dev_gone(struct domain_device *dev)
350 asd_free_ddb(asd_ha, sister_ddb); 349 asd_free_ddb(asd_ha, sister_ddb);
351 asd_free_ddb(asd_ha, ddb); 350 asd_free_ddb(asd_ha, ddb);
352 dev->lldd_dev = NULL; 351 dev->lldd_dev = NULL;
352 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);
353} 353}