diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2007-10-02 17:08:10 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:55:51 -0400 |
commit | 10e1b4bc9238687a4b1311bd5b6769d6b8c704e6 (patch) | |
tree | ac3310787bccb0d62cfb73c255f9ac17d9c9f504 /drivers/scsi/gdth.c | |
parent | 45f1a41b2b2e02e91d29bde66a8da4d050959f65 (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.c | 93 |
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 @@ | |||
139 | static void gdth_delay(int milliseconds); | 139 | static void gdth_delay(int milliseconds); |
140 | static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); | 140 | static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); |
141 | static irqreturn_t gdth_interrupt(int irq, void *dev_id); | 141 | static irqreturn_t gdth_interrupt(int irq, void *dev_id); |
142 | static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, | ||
143 | int gdth_from_wait, int* pIndex); | ||
142 | static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, | 144 | static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, |
143 | Scsi_Cmnd *scp); | 145 | Scsi_Cmnd *scp); |
144 | static int gdth_async_event(gdth_ha_str *ha); | 146 | static 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); | |||
161 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); | 163 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); |
162 | 164 | ||
163 | static void gdth_enable_int(gdth_ha_str *ha); | 165 | static void gdth_enable_int(gdth_ha_str *ha); |
164 | static int gdth_get_status(unchar *pIStatus,int irq); | 166 | static unchar gdth_get_status(gdth_ha_str *ha, int irq); |
165 | static int gdth_test_busy(gdth_ha_str *ha); | 167 | static int gdth_test_busy(gdth_ha_str *ha); |
166 | static int gdth_get_cmd_index(gdth_ha_str *ha); | 168 | static int gdth_get_cmd_index(gdth_ha_str *ha); |
167 | static void gdth_release_event(gdth_ha_str *ha); | 169 | static void gdth_release_event(gdth_ha_str *ha); |
@@ -295,8 +297,6 @@ static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ | |||
295 | static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ | 297 | static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ |
296 | #endif | 298 | #endif |
297 | static unchar gdth_polling; /* polling if TRUE */ | 299 | static unchar gdth_polling; /* polling if TRUE */ |
298 | static unchar gdth_from_wait = FALSE; /* gdth_wait() */ | ||
299 | static int wait_index,wait_hanum; /* gdth_wait() */ | ||
300 | static int gdth_ctr_count = 0; /* controller count */ | 300 | static int gdth_ctr_count = 0; /* controller count */ |
301 | static int gdth_ctr_released = 0; /* gdth_release() */ | 301 | static int gdth_ctr_released = 0; /* gdth_release() */ |
302 | static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */ | 302 | static 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 */ | |
1249 | static int gdth_get_status(unchar *pIStatus,int irq) | 1249 | static 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 | |||
1283 | static int gdth_test_busy(gdth_ha_str *ha) | 1274 | static 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) | |||
1436 | static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time) | 1427 | static 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 | ||
3013 | static irqreturn_t gdth_interrupt(int irq,void *dev_id) | 3003 | static 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 | ||
3259 | static 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 | |||
3273 | static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, | 3266 | static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, |
3274 | Scsi_Cmnd *scp) | 3267 | Scsi_Cmnd *scp) |
3275 | { | 3268 | { |