aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/gdth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/gdth.c')
-rw-r--r--drivers/scsi/gdth.c112
1 files changed, 40 insertions, 72 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 6d67f5c0eb8e..27ebd336409b 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -160,7 +160,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
160static void gdth_clear_events(void); 160static void gdth_clear_events(void);
161 161
162static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, 162static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
163 char *buffer, ushort count, int to_buffer); 163 char *buffer, ushort count);
164static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); 164static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
165static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); 165static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive);
166 166
@@ -182,7 +182,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
182 unsigned int cmd, unsigned long arg); 182 unsigned int cmd, unsigned long arg);
183 183
184static void gdth_flush(gdth_ha_str *ha); 184static void gdth_flush(gdth_ha_str *ha);
185static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
186static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); 185static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
187static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, 186static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
188 struct gdth_cmndinfo *cmndinfo); 187 struct gdth_cmndinfo *cmndinfo);
@@ -417,12 +416,6 @@ static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
417#include "gdth_proc.h" 416#include "gdth_proc.h"
418#include "gdth_proc.c" 417#include "gdth_proc.c"
419 418
420/* notifier block to get a notify on system shutdown/halt/reboot */
421static struct notifier_block gdth_notifier = {
422 gdth_halt, NULL, 0
423};
424static int notifier_disabled = 0;
425
426static gdth_ha_str *gdth_find_ha(int hanum) 419static gdth_ha_str *gdth_find_ha(int hanum)
427{ 420{
428 gdth_ha_str *ha; 421 gdth_ha_str *ha;
@@ -445,8 +438,8 @@ static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha)
445 for (i=0; i<GDTH_MAXCMDS; ++i) { 438 for (i=0; i<GDTH_MAXCMDS; ++i) {
446 if (ha->cmndinfo[i].index == 0) { 439 if (ha->cmndinfo[i].index == 0) {
447 priv = &ha->cmndinfo[i]; 440 priv = &ha->cmndinfo[i];
448 priv->index = i+1;
449 memset(priv, 0, sizeof(*priv)); 441 memset(priv, 0, sizeof(*priv));
442 priv->index = i+1;
450 break; 443 break;
451 } 444 }
452 } 445 }
@@ -493,7 +486,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
493 gdth_ha_str *ha = shost_priv(sdev->host); 486 gdth_ha_str *ha = shost_priv(sdev->host);
494 Scsi_Cmnd *scp; 487 Scsi_Cmnd *scp;
495 struct gdth_cmndinfo cmndinfo; 488 struct gdth_cmndinfo cmndinfo;
496 struct scatterlist one_sg;
497 DECLARE_COMPLETION_ONSTACK(wait); 489 DECLARE_COMPLETION_ONSTACK(wait);
498 int rval; 490 int rval;
499 491
@@ -507,13 +499,10 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
507 /* use request field to save the ptr. to completion struct. */ 499 /* use request field to save the ptr. to completion struct. */
508 scp->request = (struct request *)&wait; 500 scp->request = (struct request *)&wait;
509 scp->timeout_per_command = timeout*HZ; 501 scp->timeout_per_command = timeout*HZ;
510 sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd));
511 gdth_set_sglist(scp, &one_sg);
512 gdth_set_sg_count(scp, 1);
513 gdth_set_bufflen(scp, sizeof(*gdtcmd));
514 scp->cmd_len = 12; 502 scp->cmd_len = 12;
515 memcpy(scp->cmnd, cmnd, 12); 503 memcpy(scp->cmnd, cmnd, 12);
516 cmndinfo.priority = IOCTL_PRI; 504 cmndinfo.priority = IOCTL_PRI;
505 cmndinfo.internal_cmd_str = gdtcmd;
517 cmndinfo.internal_command = 1; 506 cmndinfo.internal_command = 1;
518 507
519 TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0])); 508 TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
@@ -2355,7 +2344,7 @@ static void gdth_next(gdth_ha_str *ha)
2355 * buffers, kmap_atomic() as needed. 2344 * buffers, kmap_atomic() as needed.
2356 */ 2345 */
2357static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, 2346static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
2358 char *buffer, ushort count, int to_buffer) 2347 char *buffer, ushort count)
2359{ 2348{
2360 ushort cpcount,i, max_sg = gdth_sg_count(scp); 2349 ushort cpcount,i, max_sg = gdth_sg_count(scp);
2361 ushort cpsum,cpnow; 2350 ushort cpsum,cpnow;
@@ -2381,10 +2370,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
2381 } 2370 }
2382 local_irq_save(flags); 2371 local_irq_save(flags);
2383 address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset; 2372 address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset;
2384 if (to_buffer) 2373 memcpy(address, buffer, cpnow);
2385 memcpy(buffer, address, cpnow);
2386 else
2387 memcpy(address, buffer, cpnow);
2388 flush_dcache_page(sg_page(sl)); 2374 flush_dcache_page(sg_page(sl));
2389 kunmap_atomic(address, KM_BIO_SRC_IRQ); 2375 kunmap_atomic(address, KM_BIO_SRC_IRQ);
2390 local_irq_restore(flags); 2376 local_irq_restore(flags);
@@ -2438,7 +2424,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2438 strcpy(inq.vendor,ha->oem_name); 2424 strcpy(inq.vendor,ha->oem_name);
2439 sprintf(inq.product,"Host Drive #%02d",t); 2425 sprintf(inq.product,"Host Drive #%02d",t);
2440 strcpy(inq.revision," "); 2426 strcpy(inq.revision," ");
2441 gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0); 2427 gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data));
2442 break; 2428 break;
2443 2429
2444 case REQUEST_SENSE: 2430 case REQUEST_SENSE:
@@ -2448,7 +2434,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2448 sd.key = NO_SENSE; 2434 sd.key = NO_SENSE;
2449 sd.info = 0; 2435 sd.info = 0;
2450 sd.add_length= 0; 2436 sd.add_length= 0;
2451 gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0); 2437 gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data));
2452 break; 2438 break;
2453 2439
2454 case MODE_SENSE: 2440 case MODE_SENSE:
@@ -2460,7 +2446,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2460 mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; 2446 mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
2461 mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; 2447 mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
2462 mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); 2448 mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
2463 gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0); 2449 gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data));
2464 break; 2450 break;
2465 2451
2466 case READ_CAPACITY: 2452 case READ_CAPACITY:
@@ -2470,7 +2456,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2470 else 2456 else
2471 rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); 2457 rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
2472 rdc.block_length = cpu_to_be32(SECTOR_SIZE); 2458 rdc.block_length = cpu_to_be32(SECTOR_SIZE);
2473 gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0); 2459 gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data));
2474 break; 2460 break;
2475 2461
2476 case SERVICE_ACTION_IN: 2462 case SERVICE_ACTION_IN:
@@ -2482,7 +2468,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2482 rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); 2468 rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
2483 rdc16.block_length = cpu_to_be32(SECTOR_SIZE); 2469 rdc16.block_length = cpu_to_be32(SECTOR_SIZE);
2484 gdth_copy_internal_data(ha, scp, (char*)&rdc16, 2470 gdth_copy_internal_data(ha, scp, (char*)&rdc16,
2485 sizeof(gdth_rdcap16_data), 0); 2471 sizeof(gdth_rdcap16_data));
2486 } else { 2472 } else {
2487 scp->result = DID_ABORT << 16; 2473 scp->result = DID_ABORT << 16;
2488 } 2474 }
@@ -2852,6 +2838,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
2852static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) 2838static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2853{ 2839{
2854 register gdth_cmd_str *cmdp; 2840 register gdth_cmd_str *cmdp;
2841 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
2855 int cmd_index; 2842 int cmd_index;
2856 2843
2857 cmdp= ha->pccb; 2844 cmdp= ha->pccb;
@@ -2860,7 +2847,7 @@ static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
2860 if (ha->type==GDT_EISA && ha->cmd_cnt>0) 2847 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
2861 return 0; 2848 return 0;
2862 2849
2863 gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1); 2850 *cmdp = *cmndinfo->internal_cmd_str;
2864 cmdp->RequestBuffer = scp; 2851 cmdp->RequestBuffer = scp;
2865 2852
2866 /* search free command index */ 2853 /* search free command index */
@@ -3794,6 +3781,8 @@ static void gdth_timeout(ulong data)
3794 gdth_ha_str *ha; 3781 gdth_ha_str *ha;
3795 ulong flags; 3782 ulong flags;
3796 3783
3784 BUG_ON(list_empty(&gdth_instances));
3785
3797 ha = list_first_entry(&gdth_instances, gdth_ha_str, list); 3786 ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
3798 spin_lock_irqsave(&ha->smp_lock, flags); 3787 spin_lock_irqsave(&ha->smp_lock, flags);
3799 3788
@@ -4669,45 +4658,6 @@ static void gdth_flush(gdth_ha_str *ha)
4669 } 4658 }
4670} 4659}
4671 4660
4672/* shutdown routine */
4673static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
4674{
4675 gdth_ha_str *ha;
4676#ifndef __alpha__
4677 gdth_cmd_str gdtcmd;
4678 char cmnd[MAX_COMMAND_SIZE];
4679#endif
4680
4681 if (notifier_disabled)
4682 return NOTIFY_OK;
4683
4684 TRACE2(("gdth_halt() event %d\n",(int)event));
4685 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
4686 return NOTIFY_DONE;
4687
4688 notifier_disabled = 1;
4689 printk("GDT-HA: Flushing all host drives .. ");
4690 list_for_each_entry(ha, &gdth_instances, list) {
4691 gdth_flush(ha);
4692
4693#ifndef __alpha__
4694 /* controller reset */
4695 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
4696 gdtcmd.BoardNode = LOCALBOARD;
4697 gdtcmd.Service = CACHESERVICE;
4698 gdtcmd.OpCode = GDT_RESET;
4699 TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum));
4700 gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL);
4701#endif
4702 }
4703 printk("Done.\n");
4704
4705#ifdef GDTH_STATISTICS
4706 del_timer(&gdth_timer);
4707#endif
4708 return NOTIFY_OK;
4709}
4710
4711/* configure lun */ 4661/* configure lun */
4712static int gdth_slave_configure(struct scsi_device *sdev) 4662static int gdth_slave_configure(struct scsi_device *sdev)
4713{ 4663{
@@ -5142,13 +5092,13 @@ static void gdth_remove_one(gdth_ha_str *ha)
5142 5092
5143 scsi_remove_host(shp); 5093 scsi_remove_host(shp);
5144 5094
5095 gdth_flush(ha);
5096
5145 if (ha->sdev) { 5097 if (ha->sdev) {
5146 scsi_free_host_dev(ha->sdev); 5098 scsi_free_host_dev(ha->sdev);
5147 ha->sdev = NULL; 5099 ha->sdev = NULL;
5148 } 5100 }
5149 5101
5150 gdth_flush(ha);
5151
5152 if (shp->irq) 5102 if (shp->irq)
5153 free_irq(shp->irq,ha); 5103 free_irq(shp->irq,ha);
5154 5104
@@ -5174,6 +5124,24 @@ static void gdth_remove_one(gdth_ha_str *ha)
5174 scsi_host_put(shp); 5124 scsi_host_put(shp);
5175} 5125}
5176 5126
5127static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
5128{
5129 gdth_ha_str *ha;
5130
5131 TRACE2(("gdth_halt() event %d\n", (int)event));
5132 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
5133 return NOTIFY_DONE;
5134
5135 list_for_each_entry(ha, &gdth_instances, list)
5136 gdth_flush(ha);
5137
5138 return NOTIFY_OK;
5139}
5140
5141static struct notifier_block gdth_notifier = {
5142 gdth_halt, NULL, 0
5143};
5144
5177static int __init gdth_init(void) 5145static int __init gdth_init(void)
5178{ 5146{
5179 if (disable) { 5147 if (disable) {
@@ -5236,7 +5204,6 @@ static int __init gdth_init(void)
5236 add_timer(&gdth_timer); 5204 add_timer(&gdth_timer);
5237#endif 5205#endif
5238 major = register_chrdev(0,"gdth", &gdth_fops); 5206 major = register_chrdev(0,"gdth", &gdth_fops);
5239 notifier_disabled = 0;
5240 register_reboot_notifier(&gdth_notifier); 5207 register_reboot_notifier(&gdth_notifier);
5241 gdth_polling = FALSE; 5208 gdth_polling = FALSE;
5242 return 0; 5209 return 0;
@@ -5246,14 +5213,15 @@ static void __exit gdth_exit(void)
5246{ 5213{
5247 gdth_ha_str *ha; 5214 gdth_ha_str *ha;
5248 5215
5249 list_for_each_entry(ha, &gdth_instances, list) 5216 unregister_chrdev(major, "gdth");
5250 gdth_remove_one(ha); 5217 unregister_reboot_notifier(&gdth_notifier);
5251 5218
5252#ifdef GDTH_STATISTICS 5219#ifdef GDTH_STATISTICS
5253 del_timer(&gdth_timer); 5220 del_timer_sync(&gdth_timer);
5254#endif 5221#endif
5255 unregister_chrdev(major,"gdth"); 5222
5256 unregister_reboot_notifier(&gdth_notifier); 5223 list_for_each_entry(ha, &gdth_instances, list)
5224 gdth_remove_one(ha);
5257} 5225}
5258 5226
5259module_init(gdth_init); 5227module_init(gdth_init);