aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/gdth.c
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2007-10-02 17:08:10 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:55:51 -0400
commit10e1b4bc9238687a4b1311bd5b6769d6b8c704e6 (patch)
treeac3310787bccb0d62cfb73c255f9ac17d9c9f504 /drivers/scsi/gdth.c
parent45f1a41b2b2e02e91d29bde66a8da4d050959f65 (diff)
[SCSI] gdth: gdth_interrupt() gdth_get_status() & gdth_wait() fixes
- gdth_get_status() returns a single device interrupt IStatus - gdth_interrupt split to __gdth_interrupt() that receives flags if is called from gdth_wait(). - Use dev_id passed from kernel and do not loop on all controllers. - gdth_wait(), get read of all global variables and call the new __gdth_interrupt with these variables on the stack Signed-off-by Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/gdth.c')
-rw-r--r--drivers/scsi/gdth.c93
1 files changed, 43 insertions, 50 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index c90e407e1e42..ef67e664c9e6 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -139,6 +139,8 @@
139static void gdth_delay(int milliseconds); 139static void gdth_delay(int milliseconds);
140static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); 140static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
141static irqreturn_t gdth_interrupt(int irq, void *dev_id); 141static irqreturn_t gdth_interrupt(int irq, void *dev_id);
142static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq,
143 int gdth_from_wait, int* pIndex);
142static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, 144static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
143 Scsi_Cmnd *scp); 145 Scsi_Cmnd *scp);
144static int gdth_async_event(gdth_ha_str *ha); 146static int gdth_async_event(gdth_ha_str *ha);
@@ -161,7 +163,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
161static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); 163static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive);
162 164
163static void gdth_enable_int(gdth_ha_str *ha); 165static void gdth_enable_int(gdth_ha_str *ha);
164static int gdth_get_status(unchar *pIStatus,int irq); 166static unchar gdth_get_status(gdth_ha_str *ha, int irq);
165static int gdth_test_busy(gdth_ha_str *ha); 167static int gdth_test_busy(gdth_ha_str *ha);
166static int gdth_get_cmd_index(gdth_ha_str *ha); 168static int gdth_get_cmd_index(gdth_ha_str *ha);
167static void gdth_release_event(gdth_ha_str *ha); 169static void gdth_release_event(gdth_ha_str *ha);
@@ -295,8 +297,6 @@ static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */
295static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ 297static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */
296#endif 298#endif
297static unchar gdth_polling; /* polling if TRUE */ 299static unchar gdth_polling; /* polling if TRUE */
298static unchar gdth_from_wait = FALSE; /* gdth_wait() */
299static int wait_index,wait_hanum; /* gdth_wait() */
300static int gdth_ctr_count = 0; /* controller count */ 300static int gdth_ctr_count = 0; /* controller count */
301static int gdth_ctr_released = 0; /* gdth_release() */ 301static int gdth_ctr_released = 0; /* gdth_release() */
302static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */ 302static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */
@@ -1245,41 +1245,32 @@ static void __init gdth_enable_int(gdth_ha_str *ha)
1245 spin_unlock_irqrestore(&ha->smp_lock, flags); 1245 spin_unlock_irqrestore(&ha->smp_lock, flags);
1246} 1246}
1247 1247
1248 1248/* return IStatus if interrupt was from this card else 0 */
1249static int gdth_get_status(unchar *pIStatus,int irq) 1249static unchar gdth_get_status(gdth_ha_str *ha, int irq)
1250{ 1250{
1251 register gdth_ha_str *ha; 1251 unchar IStatus = 0;
1252 int i; 1252
1253 TRACE(("gdth_get_status() irq %d ctr_count %d\n", irq, gdth_ctr_count));
1253 1254
1254 TRACE(("gdth_get_status() irq %d ctr_count %d\n",
1255 irq,gdth_ctr_count));
1256
1257 *pIStatus = 0;
1258 for (i=0; i<gdth_ctr_count; ++i) {
1259 ha = shost_priv(gdth_ctr_tab[i]);
1260 if (ha->irq != (unchar)irq) /* check IRQ */ 1255 if (ha->irq != (unchar)irq) /* check IRQ */
1261 continue; 1256 return false;
1262 if (ha->type == GDT_EISA) 1257 if (ha->type == GDT_EISA)
1263 *pIStatus = inb((ushort)ha->bmic + EDOORREG); 1258 IStatus = inb((ushort)ha->bmic + EDOORREG);
1264 else if (ha->type == GDT_ISA) 1259 else if (ha->type == GDT_ISA)
1265 *pIStatus = 1260 IStatus =
1266 readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); 1261 readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
1267 else if (ha->type == GDT_PCI) 1262 else if (ha->type == GDT_PCI)
1268 *pIStatus = 1263 IStatus =
1269 readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); 1264 readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
1270 else if (ha->type == GDT_PCINEW) 1265 else if (ha->type == GDT_PCINEW)
1271 *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); 1266 IStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
1272 else if (ha->type == GDT_PCIMPR) 1267 else if (ha->type == GDT_PCIMPR)
1273 *pIStatus = 1268 IStatus =
1274 readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); 1269 readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
1275 1270
1276 if (*pIStatus) 1271 return IStatus;
1277 return i; /* board found */
1278 }
1279 return -1;
1280} 1272}
1281 1273
1282
1283static int gdth_test_busy(gdth_ha_str *ha) 1274static int gdth_test_busy(gdth_ha_str *ha)
1284{ 1275{
1285 register int gdtsema0 = 0; 1276 register int gdtsema0 = 0;
@@ -1436,22 +1427,21 @@ static void gdth_release_event(gdth_ha_str *ha)
1436static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time) 1427static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time)
1437{ 1428{
1438 int answer_found = FALSE; 1429 int answer_found = FALSE;
1430 int wait_index = 0;
1439 1431
1440 TRACE(("gdth_wait() hanum %d index %d time %d\n", ha->hanum, index, time)); 1432 TRACE(("gdth_wait() hanum %d index %d time %d\n", ha->hanum, index, time));
1441 1433
1442 if (index == 0) 1434 if (index == 0)
1443 return 1; /* no wait required */ 1435 return 1; /* no wait required */
1444 1436
1445 gdth_from_wait = TRUE;
1446 do { 1437 do {
1447 gdth_interrupt((int)ha->irq,ha); 1438 __gdth_interrupt(ha, (int)ha->irq, true, &wait_index);
1448 if (wait_hanum==ha->hanum && wait_index==index) { 1439 if (wait_index == index) {
1449 answer_found = TRUE; 1440 answer_found = TRUE;
1450 break; 1441 break;
1451 } 1442 }
1452 gdth_delay(1); 1443 gdth_delay(1);
1453 } while (--time); 1444 } while (--time);
1454 gdth_from_wait = FALSE;
1455 1445
1456 while (gdth_test_busy(ha)) 1446 while (gdth_test_busy(ha))
1457 gdth_delay(0); 1447 gdth_delay(0);
@@ -3010,15 +3000,14 @@ static void gdth_clear_events(void)
3010 3000
3011/* SCSI interface functions */ 3001/* SCSI interface functions */
3012 3002
3013static irqreturn_t gdth_interrupt(int irq,void *dev_id) 3003static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq,
3004 int gdth_from_wait, int* pIndex)
3014{ 3005{
3015 gdth_ha_str *ha2 = (gdth_ha_str *)dev_id;
3016 register gdth_ha_str *ha;
3017 gdt6m_dpram_str __iomem *dp6m_ptr = NULL; 3006 gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
3018 gdt6_dpram_str __iomem *dp6_ptr; 3007 gdt6_dpram_str __iomem *dp6_ptr;
3019 gdt2_dpram_str __iomem *dp2_ptr; 3008 gdt2_dpram_str __iomem *dp2_ptr;
3020 Scsi_Cmnd *scp; 3009 Scsi_Cmnd *scp;
3021 int hanum, rval, i; 3010 int rval, i;
3022 unchar IStatus; 3011 unchar IStatus;
3023 ushort Service; 3012 ushort Service;
3024 ulong flags = 0; 3013 ulong flags = 0;
@@ -3039,17 +3028,15 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3039 } 3028 }
3040 3029
3041 if (!gdth_polling) 3030 if (!gdth_polling)
3042 spin_lock_irqsave(&ha2->smp_lock, flags); 3031 spin_lock_irqsave(&ha->smp_lock, flags);
3043 wait_index = 0;
3044 3032
3045 /* search controller */ 3033 /* search controller */
3046 if ((hanum = gdth_get_status(&IStatus,irq)) == -1) { 3034 if (0 == (IStatus = gdth_get_status(ha, irq))) {
3047 /* spurious interrupt */ 3035 /* spurious interrupt */
3048 if (!gdth_polling) 3036 if (!gdth_polling)
3049 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3037 spin_unlock_irqrestore(&ha->smp_lock, flags);
3050 return IRQ_HANDLED; 3038 return IRQ_HANDLED;
3051 } 3039 }
3052 ha = shost_priv(gdth_ctr_tab[hanum]);
3053 3040
3054#ifdef GDTH_STATISTICS 3041#ifdef GDTH_STATISTICS
3055 ++act_ints; 3042 ++act_ints;
@@ -3181,7 +3168,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3181 } else { 3168 } else {
3182 TRACE2(("gdth_interrupt() unknown controller type\n")); 3169 TRACE2(("gdth_interrupt() unknown controller type\n"));
3183 if (!gdth_polling) 3170 if (!gdth_polling)
3184 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3171 spin_unlock_irqrestore(&ha->smp_lock, flags);
3185 return IRQ_HANDLED; 3172 return IRQ_HANDLED;
3186 } 3173 }
3187 3174
@@ -3189,15 +3176,14 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3189 IStatus,ha->status,ha->info)); 3176 IStatus,ha->status,ha->info));
3190 3177
3191 if (gdth_from_wait) { 3178 if (gdth_from_wait) {
3192 wait_hanum = hanum; 3179 *pIndex = (int)IStatus;
3193 wait_index = (int)IStatus;
3194 } 3180 }
3195 3181
3196 if (IStatus == ASYNCINDEX) { 3182 if (IStatus == ASYNCINDEX) {
3197 TRACE2(("gdth_interrupt() async. event\n")); 3183 TRACE2(("gdth_interrupt() async. event\n"));
3198 gdth_async_event(ha); 3184 gdth_async_event(ha);
3199 if (!gdth_polling) 3185 if (!gdth_polling)
3200 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3186 spin_unlock_irqrestore(&ha->smp_lock, flags);
3201 gdth_next(ha); 3187 gdth_next(ha);
3202 return IRQ_HANDLED; 3188 return IRQ_HANDLED;
3203 } 3189 }
@@ -3205,10 +3191,10 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3205 if (IStatus == SPEZINDEX) { 3191 if (IStatus == SPEZINDEX) {
3206 TRACE2(("Service unknown or not initialized !\n")); 3192 TRACE2(("Service unknown or not initialized !\n"));
3207 ha->dvr.size = sizeof(ha->dvr.eu.driver); 3193 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3208 ha->dvr.eu.driver.ionode = hanum; 3194 ha->dvr.eu.driver.ionode = ha->hanum;
3209 gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); 3195 gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
3210 if (!gdth_polling) 3196 if (!gdth_polling)
3211 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3197 spin_unlock_irqrestore(&ha->smp_lock, flags);
3212 return IRQ_HANDLED; 3198 return IRQ_HANDLED;
3213 } 3199 }
3214 scp = ha->cmd_tab[IStatus-2].cmnd; 3200 scp = ha->cmd_tab[IStatus-2].cmnd;
@@ -3217,24 +3203,24 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3217 if (scp == UNUSED_CMND) { 3203 if (scp == UNUSED_CMND) {
3218 TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); 3204 TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
3219 ha->dvr.size = sizeof(ha->dvr.eu.driver); 3205 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3220 ha->dvr.eu.driver.ionode = hanum; 3206 ha->dvr.eu.driver.ionode = ha->hanum;
3221 ha->dvr.eu.driver.index = IStatus; 3207 ha->dvr.eu.driver.index = IStatus;
3222 gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); 3208 gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
3223 if (!gdth_polling) 3209 if (!gdth_polling)
3224 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3210 spin_unlock_irqrestore(&ha->smp_lock, flags);
3225 return IRQ_HANDLED; 3211 return IRQ_HANDLED;
3226 } 3212 }
3227 if (scp == INTERNAL_CMND) { 3213 if (scp == INTERNAL_CMND) {
3228 TRACE(("gdth_interrupt() answer to internal command\n")); 3214 TRACE(("gdth_interrupt() answer to internal command\n"));
3229 if (!gdth_polling) 3215 if (!gdth_polling)
3230 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3216 spin_unlock_irqrestore(&ha->smp_lock, flags);
3231 return IRQ_HANDLED; 3217 return IRQ_HANDLED;
3232 } 3218 }
3233 3219
3234 TRACE(("gdth_interrupt() sync. status\n")); 3220 TRACE(("gdth_interrupt() sync. status\n"));
3235 rval = gdth_sync_event(ha,Service,IStatus,scp); 3221 rval = gdth_sync_event(ha,Service,IStatus,scp);
3236 if (!gdth_polling) 3222 if (!gdth_polling)
3237 spin_unlock_irqrestore(&ha2->smp_lock, flags); 3223 spin_unlock_irqrestore(&ha->smp_lock, flags);
3238 if (rval == 2) { 3224 if (rval == 2) {
3239 gdth_putq(ha, scp,scp->SCp.this_residual); 3225 gdth_putq(ha, scp,scp->SCp.this_residual);
3240 } else if (rval == 1) { 3226 } else if (rval == 1) {
@@ -3270,6 +3256,13 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id)
3270 return IRQ_HANDLED; 3256 return IRQ_HANDLED;
3271} 3257}
3272 3258
3259static irqreturn_t gdth_interrupt(int irq, void *dev_id)
3260{
3261 gdth_ha_str *ha = (gdth_ha_str *)dev_id;
3262
3263 return __gdth_interrupt(ha, irq, false, NULL);
3264}
3265
3273static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, 3266static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
3274 Scsi_Cmnd *scp) 3267 Scsi_Cmnd *scp)
3275{ 3268{