aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/gdth.c111
-rw-r--r--drivers/scsi/gdth.h10
-rw-r--r--drivers/scsi/gdth_proc.c6
3 files changed, 91 insertions, 36 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 4248b041c9b5..e002c391e0d2 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -86,8 +86,8 @@
86/* The meaning of the Scsi_Pointer members in this driver is as follows: 86/* The meaning of the Scsi_Pointer members in this driver is as follows:
87 * ptr: Chaining 87 * ptr: Chaining
88 * this_residual: Command priority 88 * this_residual: Command priority
89 * buffer: phys. DMA sense buffer 89 * buffer: unused
90 * dma_handle: phys. DMA buffer (kernel >= 2.4.0) 90 * dma_handle: will drop in !use_sg patch.
91 * buffers_residual: Timeout value 91 * buffers_residual: Timeout value
92 * Status: Command status (gdth_do_cmd()), DMA mem. mappings 92 * Status: Command status (gdth_do_cmd()), DMA mem. mappings
93 * Message: Additional info (gdth_do_cmd()), DMA direction 93 * Message: Additional info (gdth_do_cmd()), DMA direction
@@ -184,6 +184,8 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
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); 185static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
186static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); 186static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
187static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
188 struct gdth_cmndinfo *cmndinfo);
187static void gdth_scsi_done(struct scsi_cmnd *scp); 189static void gdth_scsi_done(struct scsi_cmnd *scp);
188 190
189#ifdef DEBUG_GDTH 191#ifdef DEBUG_GDTH
@@ -371,9 +373,6 @@ static const struct file_operations gdth_fops = {
371 .release = gdth_close, 373 .release = gdth_close,
372}; 374};
373 375
374#define GDTH_MAGIC 0xc2e7c389 /* I got it from /dev/urandom */
375#define IS_GDTH_INTERNAL_CMD(scp) (scp->underflow == GDTH_MAGIC)
376
377#include "gdth_proc.h" 376#include "gdth_proc.h"
378#include "gdth_proc.c" 377#include "gdth_proc.c"
379 378
@@ -394,6 +393,34 @@ static gdth_ha_str *gdth_find_ha(int hanum)
394 return NULL; 393 return NULL;
395} 394}
396 395
396static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha)
397{
398 struct gdth_cmndinfo *priv = NULL;
399 ulong flags;
400 int i;
401
402 spin_lock_irqsave(&ha->smp_lock, flags);
403
404 for (i=0; i<GDTH_MAXCMDS; ++i) {
405 if (ha->cmndinfo[i].index == 0) {
406 priv = &ha->cmndinfo[i];
407 priv->index = i+1;
408 memset(priv, 0, sizeof(*priv));
409 break;
410 }
411 }
412
413 spin_unlock_irqrestore(&ha->smp_lock, flags);
414
415 return priv;
416}
417
418static void gdth_put_cmndinfo(struct gdth_cmndinfo *priv)
419{
420 BUG_ON(!priv);
421 priv->index = 0;
422}
423
397static void gdth_delay(int milliseconds) 424static void gdth_delay(int milliseconds)
398{ 425{
399 if (milliseconds == 0) { 426 if (milliseconds == 0) {
@@ -405,9 +432,15 @@ static void gdth_delay(int milliseconds)
405 432
406static void gdth_scsi_done(struct scsi_cmnd *scp) 433static void gdth_scsi_done(struct scsi_cmnd *scp)
407{ 434{
435 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
436 int internal_command = cmndinfo->internal_command;
437
408 TRACE2(("gdth_scsi_done()\n")); 438 TRACE2(("gdth_scsi_done()\n"));
409 439
410 if (IS_GDTH_INTERNAL_CMD(scp)) 440 gdth_put_cmndinfo(cmndinfo);
441 scp->host_scribble = NULL;
442
443 if (internal_command)
411 complete((struct completion *)scp->request); 444 complete((struct completion *)scp->request);
412 else 445 else
413 scp->scsi_done(scp); 446 scp->scsi_done(scp);
@@ -416,7 +449,9 @@ static void gdth_scsi_done(struct scsi_cmnd *scp)
416int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, 449int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
417 int timeout, u32 *info) 450 int timeout, u32 *info)
418{ 451{
452 gdth_ha_str *ha = shost_priv(sdev->host);
419 Scsi_Cmnd *scp; 453 Scsi_Cmnd *scp;
454 struct gdth_cmndinfo cmndinfo;
420 DECLARE_COMPLETION_ONSTACK(wait); 455 DECLARE_COMPLETION_ONSTACK(wait);
421 int rval; 456 int rval;
422 457
@@ -425,6 +460,8 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
425 return -ENOMEM; 460 return -ENOMEM;
426 461
427 scp->device = sdev; 462 scp->device = sdev;
463 memset(&cmndinfo, 0, sizeof(cmndinfo));
464
428 /* use request field to save the ptr. to completion struct. */ 465 /* use request field to save the ptr. to completion struct. */
429 scp->request = (struct request *)&wait; 466 scp->request = (struct request *)&wait;
430 scp->timeout_per_command = timeout*HZ; 467 scp->timeout_per_command = timeout*HZ;
@@ -432,8 +469,11 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
432 scp->cmd_len = 12; 469 scp->cmd_len = 12;
433 memcpy(scp->cmnd, cmnd, 12); 470 memcpy(scp->cmnd, cmnd, 12);
434 scp->SCp.this_residual = IOCTL_PRI; /* priority */ 471 scp->SCp.this_residual = IOCTL_PRI; /* priority */
435 scp->underflow = GDTH_MAGIC; 472 cmndinfo.internal_command = 1;
436 gdth_queuecommand(scp, NULL); 473
474 TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
475 __gdth_queuecommand(ha, scp, &cmndinfo);
476
437 wait_for_completion(&wait); 477 wait_for_completion(&wait);
438 478
439 rval = scp->SCp.Status; 479 rval = scp->SCp.Status;
@@ -1966,6 +2006,7 @@ static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive)
1966 2006
1967static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) 2007static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority)
1968{ 2008{
2009 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
1969 register Scsi_Cmnd *pscp; 2010 register Scsi_Cmnd *pscp;
1970 register Scsi_Cmnd *nscp; 2011 register Scsi_Cmnd *nscp;
1971 ulong flags; 2012 ulong flags;
@@ -1974,7 +2015,7 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority)
1974 TRACE(("gdth_putq() priority %d\n",priority)); 2015 TRACE(("gdth_putq() priority %d\n",priority));
1975 spin_lock_irqsave(&ha->smp_lock, flags); 2016 spin_lock_irqsave(&ha->smp_lock, flags);
1976 2017
1977 if (!IS_GDTH_INTERNAL_CMD(scp)) { 2018 if (!cmndinfo->internal_command) {
1978 scp->SCp.this_residual = (int)priority; 2019 scp->SCp.this_residual = (int)priority;
1979 b = scp->device->channel; 2020 b = scp->device->channel;
1980 t = scp->device->id; 2021 t = scp->device->id;
@@ -2035,7 +2076,7 @@ static void gdth_next(gdth_ha_str *ha)
2035 for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { 2076 for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
2036 if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) 2077 if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
2037 pscp = (Scsi_Cmnd *)pscp->SCp.ptr; 2078 pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2038 if (!IS_GDTH_INTERNAL_CMD(nscp)) { 2079 if (!gdth_cmnd_priv(nscp)->internal_command) {
2039 b = nscp->device->channel; 2080 b = nscp->device->channel;
2040 t = nscp->device->id; 2081 t = nscp->device->id;
2041 l = nscp->device->lun; 2082 l = nscp->device->lun;
@@ -2060,7 +2101,7 @@ static void gdth_next(gdth_ha_str *ha)
2060 firsttime = FALSE; 2101 firsttime = FALSE;
2061 } 2102 }
2062 2103
2063 if (!IS_GDTH_INTERNAL_CMD(nscp)) { 2104 if (!gdth_cmnd_priv(nscp)->internal_command) {
2064 if (nscp->SCp.phase == -1) { 2105 if (nscp->SCp.phase == -1) {
2065 nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ 2106 nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */
2066 if (nscp->cmnd[0] == TEST_UNIT_READY) { 2107 if (nscp->cmnd[0] == TEST_UNIT_READY) {
@@ -2123,7 +2164,7 @@ static void gdth_next(gdth_ha_str *ha)
2123 else 2164 else
2124 gdth_scsi_done(nscp); 2165 gdth_scsi_done(nscp);
2125 } 2166 }
2126 } else if (IS_GDTH_INTERNAL_CMD(nscp)) { 2167 } else if (gdth_cmnd_priv(nscp)->internal_command) {
2127 if (!(cmd_index=gdth_special_cmd(ha, nscp))) 2168 if (!(cmd_index=gdth_special_cmd(ha, nscp)))
2128 this_cmd = FALSE; 2169 this_cmd = FALSE;
2129 next_cmd = FALSE; 2170 next_cmd = FALSE;
@@ -2622,6 +2663,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
2622 unchar t,l; 2663 unchar t,l;
2623 struct page *page; 2664 struct page *page;
2624 ulong offset; 2665 ulong offset;
2666 struct gdth_cmndinfo *cmndinfo;
2625 2667
2626 t = scp->device->id; 2668 t = scp->device->id;
2627 l = scp->device->lun; 2669 l = scp->device->lun;
@@ -2645,6 +2687,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
2645 if (ha->cmd_cnt == 0) 2687 if (ha->cmd_cnt == 0)
2646 gdth_set_sema0(ha); 2688 gdth_set_sema0(ha);
2647 2689
2690 cmndinfo = gdth_cmnd_priv(scp);
2648 /* fill command */ 2691 /* fill command */
2649 if (scp->SCp.sent_command != -1) { 2692 if (scp->SCp.sent_command != -1) {
2650 cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ 2693 cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */
@@ -2668,9 +2711,8 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
2668 offset = (ulong)scp->sense_buffer & ~PAGE_MASK; 2711 offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
2669 sense_paddr = pci_map_page(ha->pdev,page,offset, 2712 sense_paddr = pci_map_page(ha->pdev,page,offset,
2670 16,PCI_DMA_FROMDEVICE); 2713 16,PCI_DMA_FROMDEVICE);
2671 *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; 2714
2672 /* high part, if 64bit */ 2715 cmndinfo->sense_paddr = sense_paddr;
2673 *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32);
2674 cmdp->OpCode = GDT_WRITE; /* always */ 2716 cmdp->OpCode = GDT_WRITE; /* always */
2675 cmdp->BoardNode = LOCALBOARD; 2717 cmdp->BoardNode = LOCALBOARD;
2676 if (mode64) { 2718 if (mode64) {
@@ -3271,6 +3313,7 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
3271 gdth_msg_str *msg; 3313 gdth_msg_str *msg;
3272 gdth_cmd_str *cmdp; 3314 gdth_cmd_str *cmdp;
3273 unchar b, t; 3315 unchar b, t;
3316 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
3274 3317
3275 cmdp = ha->pccb; 3318 cmdp = ha->pccb;
3276 TRACE(("gdth_sync_event() serv %d status %d\n", 3319 TRACE(("gdth_sync_event() serv %d status %d\n",
@@ -3364,14 +3407,9 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
3364 else if (scp->SCp.Status == GDTH_MAP_SINGLE) 3407 else if (scp->SCp.Status == GDTH_MAP_SINGLE)
3365 pci_unmap_page(ha->pdev,scp->SCp.dma_handle, 3408 pci_unmap_page(ha->pdev,scp->SCp.dma_handle,
3366 scp->request_bufflen,scp->SCp.Message); 3409 scp->request_bufflen,scp->SCp.Message);
3367 if (scp->SCp.buffer) { 3410 if (cmndinfo->sense_paddr)
3368 dma_addr_t addr; 3411 pci_unmap_page(ha->pdev, cmndinfo->sense_paddr, 16,
3369 addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer; 3412 PCI_DMA_FROMDEVICE);
3370 if (scp->host_scribble)
3371 addr += (dma_addr_t)
3372 ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32);
3373 pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
3374 }
3375 3413
3376 if (ha->status == S_OK) { 3414 if (ha->status == S_OK) {
3377 scp->SCp.Status = S_OK; 3415 scp->SCp.Status = S_OK;
@@ -3450,7 +3488,7 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
3450 scp->sense_buffer[2] = NOT_READY; 3488 scp->sense_buffer[2] = NOT_READY;
3451 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); 3489 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
3452 } 3490 }
3453 if (!IS_GDTH_INTERNAL_CMD(scp)) { 3491 if (!cmndinfo->internal_command) {
3454 ha->dvr.size = sizeof(ha->dvr.eu.sync); 3492 ha->dvr.size = sizeof(ha->dvr.eu.sync);
3455 ha->dvr.eu.sync.ionode = ha->hanum; 3493 ha->dvr.eu.sync.ionode = ha->hanum;
3456 ha->dvr.eu.sync.service = service; 3494 ha->dvr.eu.sync.service = service;
@@ -3995,28 +4033,33 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
3995 void (*done)(struct scsi_cmnd *)) 4033 void (*done)(struct scsi_cmnd *))
3996{ 4034{
3997 gdth_ha_str *ha = shost_priv(scp->device->host); 4035 gdth_ha_str *ha = shost_priv(scp->device->host);
3998 int priority; 4036 struct gdth_cmndinfo *cmndinfo;
3999 4037
4000 TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0])); 4038 TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
4001 4039
4040 cmndinfo = gdth_get_cmndinfo(ha);
4041 BUG_ON(!cmndinfo);
4042
4002 scp->scsi_done = done; 4043 scp->scsi_done = done;
4044 gdth_update_timeout(scp, scp->timeout_per_command * 6);
4045 scp->SCp.this_residual = DEFAULT_PRI;
4046 return __gdth_queuecommand(ha, scp, cmndinfo);
4047}
4048
4049static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
4050 struct gdth_cmndinfo *cmndinfo)
4051{
4052 scp->host_scribble = (unsigned char *)cmndinfo;
4003 scp->SCp.have_data_in = 1; 4053 scp->SCp.have_data_in = 1;
4004 scp->SCp.phase = -1; 4054 scp->SCp.phase = -1;
4005 scp->SCp.sent_command = -1; 4055 scp->SCp.sent_command = -1;
4006 scp->SCp.Status = GDTH_MAP_NONE; 4056 scp->SCp.Status = GDTH_MAP_NONE;
4007 scp->SCp.buffer = (struct scatterlist *)NULL;
4008 4057
4009#ifdef GDTH_STATISTICS 4058#ifdef GDTH_STATISTICS
4010 ++act_ios; 4059 ++act_ios;
4011#endif 4060#endif
4012 4061
4013 priority = DEFAULT_PRI; 4062 gdth_putq(ha, scp, scp->SCp.this_residual);
4014 if (IS_GDTH_INTERNAL_CMD(scp))
4015 priority = scp->SCp.this_residual;
4016 else
4017 gdth_update_timeout(scp, scp->timeout_per_command * 6);
4018
4019 gdth_putq(ha, scp, priority);
4020 gdth_next(ha); 4063 gdth_next(ha);
4021 return 0; 4064 return 0;
4022} 4065}
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index e6178c421855..be4ae5abd5c3 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -919,6 +919,11 @@ typedef struct {
919 Scsi_Cmnd *cmnd; /* pending request */ 919 Scsi_Cmnd *cmnd; /* pending request */
920 ushort service; /* service */ 920 ushort service; /* service */
921 } cmd_tab[GDTH_MAXCMDS]; /* table of pend. requests */ 921 } cmd_tab[GDTH_MAXCMDS]; /* table of pend. requests */
922 struct gdth_cmndinfo { /* per-command private info */
923 int index;
924 int internal_command; /* don't call scsi_done */
925 dma_addr_t sense_paddr; /* sense dma-addr */
926 } cmndinfo[GDTH_MAXCMDS]; /* index==0 is free */
922 unchar bus_cnt; /* SCSI bus count */ 927 unchar bus_cnt; /* SCSI bus count */
923 unchar tid_cnt; /* Target ID count */ 928 unchar tid_cnt; /* Target ID count */
924 unchar bus_id[MAXBUS]; /* IOP IDs */ 929 unchar bus_id[MAXBUS]; /* IOP IDs */
@@ -941,6 +946,11 @@ typedef struct {
941 struct scsi_device *sdev; 946 struct scsi_device *sdev;
942} gdth_ha_str; 947} gdth_ha_str;
943 948
949static inline struct gdth_cmndinfo *gdth_cmnd_priv(struct scsi_cmnd* cmd)
950{
951 return (struct gdth_cmndinfo *)cmd->host_scribble;
952}
953
944/* INQUIRY data format */ 954/* INQUIRY data format */
945typedef struct { 955typedef struct {
946 unchar type_qual; 956 unchar type_qual;
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index fe070ab991a0..ad1b60dbcf9c 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -758,7 +758,8 @@ static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id)
758 spin_lock_irqsave(&ha->smp_lock, flags); 758 spin_lock_irqsave(&ha->smp_lock, flags);
759 759
760 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { 760 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
761 if (!IS_GDTH_INTERNAL_CMD(scp)) { 761 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
762 if (!cmndinfo->internal_command) {
762 b = scp->device->channel; 763 b = scp->device->channel;
763 t = scp->device->id; 764 t = scp->device->id;
764 if (t == (unchar)id && b == (unchar)busnum) { 765 if (t == (unchar)id && b == (unchar)busnum) {
@@ -779,7 +780,8 @@ static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id)
779 spin_lock_irqsave(&ha->smp_lock, flags); 780 spin_lock_irqsave(&ha->smp_lock, flags);
780 781
781 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { 782 for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
782 if (!IS_GDTH_INTERNAL_CMD(scp)) { 783 struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
784 if (!cmndinfo->internal_command) {
783 b = scp->device->channel; 785 b = scp->device->channel;
784 t = scp->device->id; 786 t = scp->device->id;
785 if (t == (unchar)id && b == (unchar)busnum) { 787 if (t == (unchar)id && b == (unchar)busnum) {