--- /opt/kernel/linux-2.4.21/drivers/scsi/gdth.c 2004-06-09 14:07:40.819599975 +0200 +++ linux-2.4.21/drivers/scsi/gdth.c 2004-06-09 14:25:36.842926661 +0200 @@ -377,7 +377,7 @@ gdth_evt_str *estr); static void gdth_clear_events(void); -static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count); +static void gdth_copy_internal_data(int, Scsi_Cmnd *scp,char *buffer,ushort count); static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp); static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive); @@ -1236,6 +1236,7 @@ ha->stype = (ulong32)pcistr->device_id; ha->subdevice_id = pcistr->subdevice_id; ha->irq = pcistr->irq; + ha->pdev = pcistr->pdev; if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); @@ -1841,7 +1842,7 @@ if (ha->type == GDT_EISA) { if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */ - outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG); + outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); @@ -1917,7 +1918,7 @@ cmd_ptr->u.ioctl.subfunc = p1; cmd_ptr->u.ioctl.channel = p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; - cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch); + cmd_ptr->u.ioctl.p_param = ha->scratch_phys; } else { cmd_ptr->u.cache.DeviceNo = (ushort)p1; cmd_ptr->u.cache.BlockNo = p2; @@ -2646,27 +2647,35 @@ } } -static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count) +static void gdth_copy_internal_data(int hanum, Scsi_Cmnd *scp,char *buffer,ushort count) { ushort cpcount,i; ushort cpsum,cpnow; struct scatterlist *sl; + gdth_ha_str *ha; + int sgcnt; + char *address; cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + ha = HADATA(gdth_ctr_tab[hanum]); if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; - for (i=0,cpsum=0; iuse_sg; ++i,++sl) { - cpnow = (ushort)sl->length; + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE); + for (i=0,cpsum=0; ibufflen)); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - memcpy((char*)sl->address,buffer,cpnow); + address = (char *)phys_to_virt(sg_dma_address(sl)); + memcpy(address,buffer,cpnow); if (cpsum == cpcount) break; buffer += cpnow; } + pci_unmap_sg(ha->pdev,scp->request_buffer, + scp->use_sg,PCI_DMA_FROMDEVICE); } else { TRACE(("copy_internal() count %d\n",cpcount)); memcpy((char*)scp->request_buffer,buffer,cpcount); @@ -2713,7 +2722,7 @@ strcpy(inq.vendor,"ICP "); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); - gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); + gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data)); break; case REQUEST_SENSE: @@ -2723,7 +2732,7 @@ sd.key = NO_SENSE; sd.info = 0; sd.add_length= 0; - gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); + gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data)); break; case MODE_SENSE: @@ -2735,14 +2744,14 @@ mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); - gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); + gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data)); break; case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",t)); rdc.last_block_no = ntohl(ha->hdr[t].size-1); rdc.block_length = ntohl(SECTOR_SIZE); - gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data)); + gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; default: @@ -2767,8 +2776,8 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i, cnt; - ulong32 no; - int cmd_index, read_write; + ulong32 no, phys_addr; + int cmd_index, read_write, sgcnt; ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -2836,9 +2845,15 @@ if (scp->use_sg) { cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; - for (i=0; iuse_sg; ++i,++sl) { - cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; + scp->SCp.Status = GDTH_MAP_SG; + if (read_write == 1) + scp->SCp.Message = PCI_DMA_TODEVICE; + else + scp->SCp.Message = PCI_DMA_FROMDEVICE; + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); + cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); } cmdp->u.cache.sg_canz = (ulong32)i; @@ -2851,15 +2866,21 @@ if (iu.cache.sg_lst[i].sg_len = 0; } else { + scp->SCp.Status = GDTH_MAP_SINGLE; + if (read_write == 1) + scp->SCp.Message = PCI_DMA_TODEVICE; + else + scp->SCp.Message = PCI_DMA_FROMDEVICE; + phys_addr = pci_map_single(ha->pdev,scp->request_buffer,scp->request_bufflen,scp->SCp.Message); + scp->SCp.dma_handle = phys_addr; if (ha->cache_feat & SCATTER_GATHER) { cmdp->u.cache.DestAddr = 0xffffffff; cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = - virt_to_bus(scp->request_buffer); + cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; cmdp->u.cache.sg_lst[1].sg_len = 0; } else { - cmdp->u.cache.DestAddr = virt_to_bus(scp->request_buffer); + cmdp->u.cache.DestAddr = phys_addr; cmdp->u.cache.sg_canz= 0; } } @@ -2897,7 +2918,7 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; - int cmd_index; + int cmd_index, sgcnt; unchar t,l; ha = HADATA(gdth_ctr_tab[hanum]); @@ -2945,7 +2966,8 @@ cmdp->u.raw.link_p = 0; cmdp->u.raw.sdlen = scp->request_bufflen; cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer); + cmdp->u.raw.sense_data = pci_map_single(ha->pdev,scp->sense_buffer,16,PCI_DMA_FROMDEVICE); + scp->SCp.buffer = (struct scatterlist *) cmdp->u.raw.sense_data; cmdp->u.raw.direction = gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; memcpy(cmdp->u.raw.cmd,scp->cmnd,12); @@ -2953,9 +2975,12 @@ if (scp->use_sg) { cmdp->u.raw.sdata = 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; - for (i=0; iuse_sg; ++i,++sl) { - cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + scp->SCp.Status = GDTH_MAP_SG; + scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); + cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); } cmdp->u.raw.sg_ranz = (ulong32)i; @@ -2968,14 +2993,17 @@ if (iu.raw.sg_lst[i].sg_len = 0; } else { + scp->SCp.Status = GDTH_MAP_SINGLE; + scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; + scp->SCp.dma_handle = pci_map_single(ha->pdev,scp->request_buffer,scp->request_bufflen,scp->SCp.Message); if (ha->raw_feat & SCATTER_GATHER) { cmdp->u.raw.sdata = 0xffffffff; cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sg_lst[0].sg_ptr = scp->SCp.dma_handle; cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; cmdp->u.raw.sg_lst[1].sg_len = 0; } else { - cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sdata = scp->SCp.dma_handle; cmdp->u.raw.sg_ranz= 0; } } @@ -3414,7 +3442,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -3449,7 +3477,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -3466,6 +3494,23 @@ if (scp->SCp.sent_command == -1 && b != ha->virt_bus) { ha->raw[BUS_L2P(ha,b)].io_cnt[scp->target]--; } + if (ha->status == S_BSY) { + TRACE2(("Controller busy -> retry !\n")); + scp->SCp.Status = S_BSY; + scp->SCp.Message = ha->info; + if (scp->SCp.sent_command == GDT_MOUNT) + scp->SCp.sent_command = GDT_CLUST_INFO; + /* retry */ + return 2; + } + + if (scp->SCp.Status == GDTH_MAP_SG) + pci_unmap_sg(ha->pdev,scp->request_buffer,scp->use_sg,scp->SCp.Message); + else if (scp->SCp.Status == GDTH_MAP_SINGLE) + pci_unmap_single(ha->pdev,scp->SCp.dma_handle,scp->request_bufflen,scp->SCp.Message); + if (scp->SCp.buffer) + pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer,16,PCI_DMA_FROMDEVICE); + /* cache or raw service */ if (ha->status == S_OK) { scp->SCp.Status = S_OK; @@ -3511,14 +3556,6 @@ scp->result = DID_OK << 16; scp->sense_buffer[0] = 0; } - } else if (ha->status == S_BSY) { - TRACE2(("Controller busy -> retry !\n")); - scp->SCp.Status = S_BSY; - scp->SCp.Message = ha->info; - if (scp->SCp.sent_command == GDT_MOUNT) - scp->SCp.sent_command = GDT_CLUST_INFO; - /* retry */ - return 2; } else { scp->SCp.Status = ha->status; scp->SCp.Message = ha->info; @@ -3766,7 +3803,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -3991,8 +4028,9 @@ gdth_ha_str *ha; ulong32 isa_bios; ushort eisa_slot; - int i,hanum,cnt,ctr; + int i,hanum,cnt,ctr, err = 0; unchar b; + dma_addr_t dma; #ifdef DEBUG_GDTH @@ -4074,12 +4112,9 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); -#endif + ha->ccb_phys = 0; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &dma); + ha->scratch_phys = dma; ha->scratch_busy = FALSE; ha->req_first = NULL; ha->tid_cnt = MAX_HDRIVES; @@ -4089,7 +4124,12 @@ ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); + err = 1; + } + + if (err || ha->pscratch == NULL || !gdth_search_drives(hanum)) { printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; @@ -4178,12 +4218,11 @@ NUMDATA(shp)->hanum)); ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); -#endif + ha->ccb_phys = 0; + ha->pdev = NULL; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &dma); + ha->scratch_phys = (ulong32) dma; + ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb,sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); ha->scratch_busy = FALSE; ha->req_first = NULL; ha->tid_cnt = MAX_HDRIVES; @@ -4197,12 +4236,10 @@ printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif + if (ha->pscratch != NULL) { + pci_free_consistent(ha->pdev, GDTH_SCRATCH,ha->pscratch, ha->scratch_phys); + pci_unmap_single(ha->pdev,ha->ccb_phys,sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); + } #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); #else @@ -4291,12 +4328,9 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); -#endif + ha->ccb_phys = 0; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &dma); + ha->scratch_phys = (ulong32) dma; ha->scratch_busy = FALSE; ha->req_first = NULL; ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; @@ -4397,11 +4431,9 @@ free_dma(shp->dma_channel); } #endif -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#endif + pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); + if (ha->ccb_phys) + pci_unmap_single(ha->pdev,ha->ccb_phys,sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); gdth_ctr_released++; TRACE2(("gdth_release(): HA %d of %d\n", gdth_ctr_released, gdth_ctr_count)); @@ -4600,6 +4632,8 @@ scp->SCp.have_data_in = 1; scp->SCp.phase = -1; scp->SCp.sent_command = -1; + scp->SCp.Status = GDTH_MAP_NONE; + scp->SCp.buffer = NULL; hanum = NUMDATA(scp->host)->hanum; #ifdef GDTH_STATISTICS ++act_ios; --- /opt/kernel/linux-2.4.21/drivers/scsi/gdth.h 2004-06-09 14:07:40.813600620 +0200 +++ linux-2.4.21/drivers/scsi/gdth.h 2004-06-09 14:22:42.525647669 +0200 @@ -292,6 +292,12 @@ #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ #define EISAREG 0x0cc0 /* EISA configuration */ +/* DMA memory mappings */ +#define GDTH_MAP_NONE 0 +#define GDTH_MAP_SINGLE 1 +#define GDTH_MAP_SG 2 +#define GDTH_MAP_IOCTL 3 + /* other defines */ #define LINUX_OS 8 /* used for cache optim. */ #define SCATTER_GATHER 1 /* s/g feature */ @@ -889,7 +895,9 @@ ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ gdth_cmd_str *pccb; /* address command structure */ + ulong32 ccb_phys; char *pscratch; /* scratch (DMA) buffer */ + ulong32 scratch_phys; unchar scratch_busy; /* in use? */ unchar scan_mode; /* current scan mode */ unchar irq; /* IRQ */ @@ -946,6 +954,7 @@ #if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; #endif + struct pci_dev *pdev; } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */