diff -ruN dpt-orig/dpt/dptsig.h dpt-new-mike/dpt/dptsig.h --- dpt-orig/dpt/dptsig.h 2007-10-12 18:43:44.000000000 +0200 +++ dpt-new-mike/dpt/dptsig.h 2007-11-11 13:09:47.000000000 +0100 @@ -35,6 +35,8 @@ typedef unsigned short sigWORD; #if (defined(_MULTI_DATAMODEL) && defined(sun) && !defined(_ILP32)) typedef uint32_t sigLONG; +#elif defined(__linux__) +typedef u32 sigLONG; #else typedef unsigned long sigLONG; #endif diff -ruN dpt-orig/dpt/osd_util.h dpt-new-mike/dpt/osd_util.h --- dpt-orig/dpt/osd_util.h 2007-10-12 18:43:44.000000000 +0200 +++ dpt-new-mike/dpt/osd_util.h 2007-11-11 13:10:51.000000000 +0100 @@ -185,7 +185,11 @@ typedef unsigned char uCHAR; typedef unsigned short uSHORT; typedef unsigned int uINT; +#if defined(__linux__) + typedef u32 uLONG; +#else typedef unsigned long uLONG; +#endif typedef union { uCHAR u8[4]; diff -ruN dpt-orig/dpt_i2o.c dpt-new-mike/dpt_i2o.c --- dpt-orig/dpt_i2o.c 2007-10-12 18:43:44.000000000 +0200 +++ dpt-new-mike/dpt_i2o.c 2007-11-14 00:18:03.000000000 +0100 @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,10 @@ #include "dpt/dptsig.h" #include "dpti.h" +#define DPT_DMA64(pHba) (sizeof(dma_addr_t) > 4 && (pHba)->pae_support) +#define DPT_DMA64_ADDROVER4G(pHba, addr) \ + (DPT_DMA64(pHba) && ((u64)(addr) >> 32) != 0) + /*============================================================================ * Create a binary signature - this is read by dptsig * Needed for our management apps @@ -108,17 +113,23 @@ static DEFINE_MUTEX(adpt_configuration_lock); -static struct i2o_sys_tbl *sys_tbl = NULL; -static int sys_tbl_ind = 0; -static int sys_tbl_len = 0; +static struct i2o_sys_tbl *sys_tbl; +static dma_addr_t sys_tbl_pa; +static int sys_tbl_ind; +static int sys_tbl_len; static adpt_hba* hba_chain = NULL; static int hba_count = 0; +static long compat_adpt_ioctl(struct file *, unsigned int, unsigned long); + static const struct file_operations adpt_fops = { .ioctl = adpt_ioctl, .open = adpt_open, - .release = adpt_close + .release = adpt_close, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_adpt_ioctl, +#endif }; #ifdef REBOOT_NOTIFIER @@ -153,6 +164,11 @@ static u8 adpt_read_blink_led(adpt_hba* host) { + if (sizeof(void *) > sizeof(u32)) { + /* TODO 64bit fix - oopses sometimes in 64-bit mode */ + return 0; + } + if(host->FwDebugBLEDflag_P != 0) { if( readb(host->FwDebugBLEDflag_P) == 0xbc ){ return readb(host->FwDebugBLEDvalue_P); @@ -289,11 +305,12 @@ u32 len; u32 reqlen; u8* buf; + dma_addr_t addr; u8 scb[16]; s32 rcode; memset(msg, 0, sizeof(msg)); - buf = kmalloc(80,GFP_KERNEL|ADDR32); + buf = (u8*)pci_alloc_consistent(pHba->pDev, 80, &addr); if(!buf){ printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name); return; @@ -337,8 +354,18 @@ /* Now fill in the SGList and command */ *lenptr = len; - *mptr++ = 0xD0000000|direction|len; - *mptr++ = virt_to_bus(buf); + if (DPT_DMA64_ADDROVER4G(pHba, addr)) { + *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ + *mptr++ = 1 << PAGE_SHIFT; + *mptr++ = 0xD0000000|direction|len; + *mptr++ = (u32)addr; + *mptr++ = (u32)(addr >> 32); + reqlen += 3; + msg[0] = reqlen<<16 | SGL_OFFSET_12; + } else { + *mptr++ = 0xD0000000|direction|len; + *mptr++ = addr; + } // Send it on it's way rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120); @@ -346,7 +373,7 @@ sprintf(pHba->detail, "Adaptec I2O RAID"); printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); if (rcode != -ETIME && rcode != -EINTR) - kfree(buf); + pci_free_consistent(pHba->pDev, 80, buf, addr); } else { memset(pHba->detail, 0, sizeof(pHba->detail)); memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); @@ -355,7 +382,7 @@ memcpy(&(pHba->detail[40]), " FW: ", 4); memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); pHba->detail[48] = '\0'; /* precautionary */ - kfree(buf); + pci_free_consistent(pHba->pDev, 80, buf, addr); } adpt_i2o_status_get(pHba); return ; @@ -659,7 +686,10 @@ msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; msg[2] = 0; msg[3]= 0; - msg[4] = (u32)cmd; + if (sizeof(cmd) > sizeof(u32)) + msg[4] = (u32)cmd->serial_number; + else + msg[4] = (u32)(unsigned long)cmd; if (pHba->host) spin_lock_irq(pHba->host->host_lock); rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER); @@ -892,6 +922,7 @@ u32 hba_map1_area_size = 0; void __iomem *base_addr_virt = NULL; void __iomem *msg_addr_virt = NULL; + int pae_support = 0; int raptorFlag = FALSE; @@ -905,9 +936,26 @@ } pci_set_master(pDev); - if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) && - pci_set_dma_mask(pDev, DMA_32BIT_MASK)) - return -EINVAL; + + /* + * Only enable PAE mode if the dma_addr_t is larger than + * 32 bit addressing, and we have more than 32 bit addressing + * worth of memory. + */ + if (sizeof(dma_addr_t) > 4 && + max_pfn > (0xFFFFFFFFULL >> PAGE_SHIFT)) { + if (pci_set_dma_mask(pDev, DMA_64BIT_MASK)) { + if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) + return -EINVAL; + } else + pae_support = 1; + } else { + if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) + return -EINVAL; + } + + /* Make sure pci_alloc_consistent returns 32 bit addresses */ + pci_set_consistent_dma_mask(pDev, DMA_32BIT_MASK); base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); @@ -929,6 +977,19 @@ raptorFlag = TRUE; } + /* x86_64 machines need more optimal mappings */ + if (sizeof(void *) > sizeof(u32)) { + if (raptorFlag == TRUE) { + if (hba_map0_area_size > 128) + hba_map0_area_size = 128; + if (hba_map1_area_size > 524288) + hba_map1_area_size = 524288; + } else { + if (hba_map0_area_size > 524288) + hba_map0_area_size = 524288; + } + } + base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { pci_release_regions(pDev); @@ -993,6 +1054,7 @@ pHba->state = DPTI_STATE_RESET; pHba->pDev = pDev; pHba->devices = NULL; + pHba->pae_support = pae_support; // Initializing the spinlocks spin_lock_init(&pHba->state_lock); @@ -1053,10 +1115,24 @@ if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } - kfree(pHba->hrt); - kfree(pHba->lct); - kfree(pHba->status_block); - kfree(pHba->reply_pool); + if(pHba->hrt) { + pci_free_consistent(pHba->pDev, + pHba->hrt->num_entries * pHba->hrt->entry_len << 2, + pHba->hrt, pHba->hrt_pa); + } + if(pHba->lct) { + pci_free_consistent(pHba->pDev, pHba->lct_size, + pHba->lct, pHba->lct_pa); + } + if(pHba->status_block) { + pci_free_consistent(pHba->pDev, sizeof(i2o_status_block), + pHba->status_block, pHba->status_block_pa); + } + if(pHba->reply_pool) { + pci_free_consistent(pHba->pDev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + pHba->reply_pool, pHba->reply_pool_pa); + } for(d = pHba->devices; d ; d = next){ next = d->next; @@ -1272,6 +1348,7 @@ { u32 msg[8]; u8* status; + dma_addr_t addr; u32 m = EMPTY_QUEUE ; ulong timeout = jiffies + (TMOUT_IOPRESET*HZ); @@ -1294,12 +1371,13 @@ schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); - status = kzalloc(4, GFP_KERNEL|ADDR32); + status = (u8*)pci_alloc_consistent(pHba->pDev, 4, &addr); if(status == NULL) { adpt_send_nop(pHba, m); printk(KERN_ERR"IOP reset failed - no free memory.\n"); return -ENOMEM; } + memset(status,0,4); msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; @@ -1307,8 +1385,8 @@ msg[3]=0; msg[4]=0; msg[5]=0; - msg[6]=virt_to_bus(status); - msg[7]=0; + msg[6]=(u32)addr; + msg[7]=(u32)(addr >> 32); memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg)); wmb(); @@ -1318,7 +1396,10 @@ while(*status == 0){ if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name); - kfree(status); + /* We lose 4 bytes of "status" here, but we cannot + free these because controller may awake and corrupt + those bytes at any time */ + /* pci_free_consistent(pHba->pDev, 4, buf, addr); */ return -ETIMEDOUT; } rmb(); @@ -1337,6 +1418,10 @@ } if(time_after(jiffies,timeout)){ printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); + /* We lose 4 bytes of "status" here, but we + cannot free these because controller may + awake and corrupt those bytes at any time */ + /* pci_free_consistent(pHba->pDev, 4, buf, addr); */ return -ETIMEDOUT; } schedule_timeout_uninterruptible(1); @@ -1353,7 +1438,7 @@ PDEBUG("%s: Reset completed.\n", pHba->name); } - kfree(status); + pci_free_consistent(pHba->pDev, 4, status, addr); #ifdef UARTDELAY // This delay is to allow someone attached to the card through the debug UART to // set up the dump levels that they want before the rest of the initialization sequence @@ -1623,8 +1708,10 @@ u32 sg_count = 0; int sg_index = 0; u32 i = 0; + u32 nr; u32 rcode = 0; void *p = NULL; + dma_addr_t addr; ulong flags = 0; memset(&msg, 0, MAX_MESSAGE_SIZE*4); @@ -1657,7 +1744,26 @@ } sg_offset = (msg[0]>>4)&0xf; msg[2] = 0x40000000; // IOCTL context - msg[3] = (u32)reply; + if (sizeof(reply) > sizeof(u32)) { + spin_lock_irqsave(pHba->host->host_lock, flags); + nr = sizeof(pHba->ioctl_reply_context) / + sizeof(pHba->ioctl_reply_context[0]); + for (i = 0; i < nr; i++) { + if (pHba->ioctl_reply_context[i] == NULL) { + pHba->ioctl_reply_context[i] = reply; + break; + } + } + spin_unlock_irqrestore(pHba->host->host_lock, flags); + if (i >= nr) { + kfree (reply); + printk(KERN_WARNING"%s: Too many outstanding " + "ioctl commands\n", pHba->name); + return -EBUSY; + } + msg[3] = i; + } else + msg[3] = (u32)(unsigned long)reply; memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize); if(sg_offset) { // TODO 64bit fix @@ -1679,7 +1785,7 @@ } sg_size = sg[i].flag_count & 0xffffff; /* Allocate memory for the transfer */ - p = kmalloc(sg_size, GFP_KERNEL|ADDR32); + p = pci_alloc_consistent(pHba->pDev, sg_size, &addr); if(!p) { printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", pHba->name,sg_size,i,sg_count); @@ -1697,7 +1803,7 @@ } } //TODO 64bit fix - sg[i].addr_bus = (u32)virt_to_bus(p); + sg[i].addr_bus = addr; } } @@ -1751,7 +1857,7 @@ /* Copy out the SG list to user's buffer if necessary */ if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { sg_size = sg[j].flag_count & 0xffffff; - // TODO 64bit fix + // TODO 64bit fix, source currently 32 bit app if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) { printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus); rcode = -EFAULT; @@ -1776,12 +1882,17 @@ cleanup: - if (rcode != -ETIME && rcode != -EINTR) + if (rcode != -ETIME && rcode != -EINTR) { + struct sg_simple_element *sg = + (struct sg_simple_element*) (msg +sg_offset); kfree (reply); - while(sg_index) { - if(sg_list[--sg_index]) { - if (rcode != -ETIME && rcode != -EINTR) - kfree(sg_list[sg_index]); + while(sg_index) { + if(sg_list[--sg_index]) { + pci_free_consistent(pHba->pDev, + sg[sg_index].flag_count & 0xffffff, + sg_list[sg_index], + sg[sg_index].addr_bus); + } } } return rcode; @@ -1967,6 +2078,69 @@ return error; } +#ifdef CONFIG_COMPAT +static long compat_adpt_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct inode *inode; + long ret; + + inode = file->f_dentry->d_inode; + + lock_kernel(); + + switch(cmd) { + case DPT_SIGNATURE: + case I2OUSRCMD: + case DPT_CTRLINFO: + case DPT_SYSINFO: + case DPT_BLINKLED: + case I2ORESETCMD: + case I2ORESCANCMD: + case (DPT_TARGET_BUSY & 0xFFFF): + case DPT_TARGET_BUSY: + ret = adpt_ioctl(inode, file, cmd, arg); + break; + default: + ret = -ENOIOCTLCMD; + } + + unlock_kernel(); + + return ret; +} +#endif + +static inline struct scsi_cmnd * + adpt_cmd_from_context(adpt_hba * pHba, u32 context) +{ + struct scsi_cmnd * cmd; + struct scsi_device * d; + + if (context == 0) + return NULL; + + if (sizeof(cmd) <= sizeof(u32)) + return (struct scsi_cmnd*)(unsigned long)context; + + spin_unlock(pHba->host->host_lock); + shost_for_each_device(d, pHba->host) { + unsigned long flags; + spin_lock_irqsave(&d->list_lock, flags); + list_for_each_entry(cmd, &d->cmd_list, list) { + if (((u32)cmd->serial_number == context)) { + spin_unlock_irqrestore(&d->list_lock, flags); + scsi_device_put(d); + spin_lock(pHba->host->host_lock); + return cmd; + } + } + spin_unlock_irqrestore(&d->list_lock, flags); + } + spin_lock(pHba->host->host_lock); + + return NULL; +} static irqreturn_t adpt_isr(int irq, void *dev_id) { @@ -1998,7 +2172,16 @@ goto out; } } - reply = bus_to_virt(m); + if (pHba->reply_pool_pa <= m && + m < pHba->reply_pool_pa + + (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) { + reply = (u8 *)pHba->reply_pool + + (m - pHba->reply_pool_pa); + } else { + /* Ick, we should *never* be here */ + printk(KERN_ERR "dpti: replay frame not from pool\n"); + reply = (u8 *)bus_to_virt(m); + } if (readl(reply) & MSG_FAIL) { u32 old_m = readl(reply+28); @@ -2018,7 +2201,13 @@ } context = readl(reply+8); if(context & 0x40000000){ // IOCTL - void *p = (void *)readl(reply+12); + u32 context = readl(reply+12); + void *p; + if (sizeof(reply) > sizeof(u32)) { + p = pHba->ioctl_reply_context[context]; + pHba->ioctl_reply_context[context] = NULL; + } else + p = (void *)(unsigned long)(readl(reply+12)); if( p != NULL) { memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4); } @@ -2032,15 +2221,17 @@ status = I2O_POST_WAIT_OK; } if(!(context & 0x40000000)) { - cmd = (struct scsi_cmnd*) readl(reply+12); + cmd = adpt_cmd_from_context(pHba, + readl(reply+12)); if(cmd != NULL) { printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); } } adpt_i2o_post_wait_complete(context, status); } else { // SCSI message - cmd = (struct scsi_cmnd*) readl(reply+12); + cmd = adpt_cmd_from_context (pHba, readl(reply+12)); if(cmd != NULL){ + scsi_dma_unmap(cmd); if(cmd->serial_number != 0) { // If not timedout adpt_i2o_to_scsi(reply, cmd); } @@ -2061,6 +2252,7 @@ int i; u32 msg[MAX_MESSAGE_SIZE]; u32* mptr; + u32* lptr; u32 *lenptr; int direction; int scsidir; @@ -2068,6 +2260,7 @@ u32 len; u32 reqlen; s32 rcode; + dma_addr_t addr; memset(msg, 0 , sizeof(msg)); len = scsi_bufflen(cmd); @@ -2107,7 +2300,10 @@ // I2O_CMD_SCSI_EXEC msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); msg[2] = 0; - msg[3] = (u32)cmd; /* We want the SCSI control block back */ + if (sizeof(cmd) > sizeof(u32)) + msg[3] = (u32)cmd->serial_number; + else + msg[3] = (u32)(unsigned long)cmd; /* We want the SCSI control block back */ // Our cards use the transaction context as the tag for queueing // Adaptec/DPT Private stuff msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); @@ -2126,6 +2322,11 @@ mptr+=4; lenptr=mptr++; /* Remember me - fill in when we know */ reqlen = 14; // SINGLE SGE + if (DPT_DMA64(pHba)) { + *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ + *mptr++ = 1 << PAGE_SHIFT; + reqlen += 2; + } /* Now fill in the SGList and command */ nseg = scsi_dma_map(cmd); @@ -2135,12 +2336,19 @@ len = 0; scsi_for_each_sg(cmd, sg, nseg, i) { + lptr = mptr; *mptr++ = direction|0x10000000|sg_dma_len(sg); len+=sg_dma_len(sg); - *mptr++ = sg_dma_address(sg); + if (DPT_DMA64(pHba)) { + addr = sg_dma_address(sg); + *mptr++ = (u32)addr; + *mptr++ = (u32)(addr >> 32); + } else { + *mptr++ = sg_dma_address(sg); + } /* Make this an end of list */ if (i == nseg - 1) - mptr[-2] = direction|0xD0000000|sg_dma_len(sg); + *lptr = direction|0xD0000000|sg_dma_len(sg); } reqlen = mptr - msg; *lenptr = len; @@ -2599,11 +2807,10 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) { u8 *status; + dma_addr_t addr; u32 __iomem *msg = NULL; int i; ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ; - u32* ptr; - u32 outbound_frame; // This had to be a 32 bit address u32 m; do { @@ -2622,7 +2829,7 @@ msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - status = kmalloc(4,GFP_KERNEL|ADDR32); + status = (u8*)pci_alloc_consistent(pHba->pDev, 4, &addr); if (status==NULL) { adpt_send_nop(pHba, m); printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", @@ -2638,7 +2845,7 @@ writel(4096, &msg[4]); /* Host page frame size */ writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */ writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */ - writel(virt_to_bus(status), &msg[7]); + writel((u32)addr, &msg[7]); writel(m, pHba->post_port); wmb(); @@ -2653,6 +2860,10 @@ rmb(); if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); + /* We lose 4 bytes of "status" here, but we + cannot free these because controller may + awake and corrupt those bytes at any time */ + /* pci_free_consistent(pHba->pDev, 4, status, addr); */ return -ETIMEDOUT; } schedule_timeout_uninterruptible(1); @@ -2661,26 +2872,31 @@ // If the command was successful, fill the fifo with our reply // message packets if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { - kfree(status); + pci_free_consistent(pHba->pDev, 4, status, addr); return -2; } - kfree(status); + pci_free_consistent(pHba->pDev, 4, status, addr); + + if(pHba->reply_pool != NULL) { + pci_free_consistent(pHba->pDev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + pHba->reply_pool, pHba->reply_pool_pa); + } - kfree(pHba->reply_pool); - pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); - if(!pHba->reply_pool){ + pHba->reply_pool = (u32*)pci_alloc_consistent(pHba->pDev, + pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, + &pHba->reply_pool_pa); + if(!pHba->reply_pool) { printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name); return -1; } memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); - ptr = pHba->reply_pool; for(i = 0; i < pHba->reply_fifo_size; i++) { - outbound_frame = (u32)virt_to_bus(ptr); - writel(outbound_frame, pHba->reply_port); + writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4), + pHba->reply_port); wmb(); - ptr += REPLY_FRAME_SIZE; } adpt_i2o_status_get(pHba); return 0; @@ -2704,11 +2920,11 @@ u32 m; u32 __iomem *msg; u8 *status_block=NULL; - ulong status_block_bus; if(pHba->status_block == NULL) { pHba->status_block = (i2o_status_block*) - kmalloc(sizeof(i2o_status_block),GFP_KERNEL|ADDR32); + pci_alloc_consistent(pHba->pDev, sizeof(i2o_status_block), + &pHba->status_block_pa); if(pHba->status_block == NULL) { printk(KERN_ERR "dpti%d: Get Status Block failed; Out of memory. \n", @@ -2718,7 +2934,6 @@ } memset(pHba->status_block, 0, sizeof(i2o_status_block)); status_block = (u8*)(pHba->status_block); - status_block_bus = virt_to_bus(pHba->status_block); timeout = jiffies+TMOUT_GETSTATUS*HZ; do { rmb(); @@ -2743,8 +2958,8 @@ writel(0, &msg[3]); writel(0, &msg[4]); writel(0, &msg[5]); - writel(((u32)status_block_bus)&0xffffffff, &msg[6]); - writel(0, &msg[7]); + writel( (u32)pHba->status_block_pa, &msg[6]); + writel( (u32)(pHba->status_block_pa >> 32), &msg[7]); writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes //post message @@ -2773,7 +2988,18 @@ } // Calculate the Scatter Gather list size - pHba->sg_tablesize = (pHba->status_block->inbound_frame_size * 4 -40)/ sizeof(struct sg_simple_element); + if (DPT_DMA64(pHba)) { + pHba->sg_tablesize + = ((pHba->status_block->inbound_frame_size * 4 + - 14 * sizeof(u32)) + / (sizeof(struct sg_simple_element) + sizeof(u32))); + } else { + pHba->sg_tablesize + = ((pHba->status_block->inbound_frame_size * 4 + - 12 * sizeof(u32)) + / sizeof(struct sg_simple_element)); + } + if (pHba->sg_tablesize > SG_LIST_ELEMENTS) { pHba->sg_tablesize = SG_LIST_ELEMENTS; } @@ -2824,7 +3050,8 @@ } do { if (pHba->lct == NULL) { - pHba->lct = kmalloc(pHba->lct_size, GFP_KERNEL|ADDR32); + pHba->lct = pci_alloc_consistent(pHba->pDev, + pHba->lct_size, &pHba->lct_pa); if(pHba->lct == NULL) { printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n", pHba->name); @@ -2840,7 +3067,7 @@ msg[4] = 0xFFFFFFFF; /* All devices */ msg[5] = 0x00000000; /* Report now */ msg[6] = 0xD0000000|pHba->lct_size; - msg[7] = virt_to_bus(pHba->lct); + msg[7] = (u32)pHba->lct_pa; if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) { printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", @@ -2851,7 +3078,8 @@ if ((pHba->lct->table_size << 2) > pHba->lct_size) { pHba->lct_size = pHba->lct->table_size << 2; - kfree(pHba->lct); + pci_free_consistent(pHba->pDev, pHba->lct_size, + pHba->lct, pHba->lct_pa); pHba->lct = NULL; } } while (pHba->lct == NULL); @@ -2876,15 +3104,17 @@ static int adpt_i2o_build_sys_table(void) { - adpt_hba* pHba = NULL; + adpt_hba* pHba = hba_chain; int count = 0; + if (sys_tbl) + pci_free_consistent(pHba->pDev, sys_tbl_len, + sys_tbl, sys_tbl_pa); + sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs (hba_count) * sizeof(struct i2o_sys_tbl_entry); - kfree(sys_tbl); - - sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32); + sys_tbl = pci_alloc_consistent(pHba->pDev, sys_tbl_len, &sys_tbl_pa); if(!sys_tbl) { printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); return -ENOMEM; @@ -2896,6 +3126,7 @@ sys_tbl->change_ind = sys_tbl_ind++; for(pHba = hba_chain; pHba; pHba = pHba->next) { + u64 addr; // Get updated Status Block so we have the latest information if (adpt_i2o_status_get(pHba)) { sys_tbl->num_entries--; @@ -2911,8 +3142,9 @@ sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size; sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities; - sys_tbl->iops[count].inbound_low = (u32)virt_to_bus(pHba->post_port); - sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus(pHba->post_port)>>32); + addr = pHba->base_addr_phys + 0x40; + sys_tbl->iops[count].inbound_low = (u32)addr; + sys_tbl->iops[count].inbound_high = (u32)(addr >> 32); count++; } @@ -3048,7 +3280,8 @@ do { if (pHba->hrt == NULL) { - pHba->hrt=kmalloc(size, GFP_KERNEL|ADDR32); + pHba->hrt = pci_alloc_consistent(pHba->pDev, + size, &pHba->hrt_pa); if (pHba->hrt == NULL) { printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name); return -ENOMEM; @@ -3060,7 +3293,7 @@ msg[2]= 0; msg[3]= 0; msg[4]= (0xD0000000 | size); /* Simple transaction */ - msg[5]= virt_to_bus(pHba->hrt); /* Dump it here */ + msg[5]= (u32)pHba->hrt_pa; /* Dump it here */ if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) { printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret); @@ -3068,8 +3301,9 @@ } if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) { + pci_free_consistent(pHba->pDev, size, + pHba->hrt, pHba->hrt_pa); size = pHba->hrt->num_entries * pHba->hrt->entry_len << 2; - kfree(pHba->hrt); pHba->hrt = NULL; } } while(pHba->hrt == NULL); @@ -3083,33 +3317,53 @@ int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 *resblk; + u8 *opblk_va; + dma_addr_t opblk_pa; + u8 *resblk_va; + dma_addr_t resblk_pa; int size; /* 8 bytes for header */ - resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32); - if (resblk == NULL) { + resblk_va = pci_alloc_consistent(pHba->pDev, sizeof(u8) * (8 + buflen), + &resblk_pa); + if (resblk_va == NULL) { printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); return -ENOMEM; } + opblk_va = pci_alloc_consistent(pHba->pDev, sizeof(opblk), &opblk_pa); + if (opblk_va == NULL) { + pci_free_consistent(pHba->pDev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); + printk(KERN_CRIT "%s: query operatio failed; Out of memory.\n", + pHba->name); + return -ENOMEM; + } if (field == -1) /* whole group */ opblk[4] = -1; + memcpy(opblk_va, opblk, sizeof(opblk)); size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen)); + opblk_va, opblk_pa, sizeof(opblk), + resblk_va, resblk_pa, sizeof(u8)*(8+buflen)); + pci_free_consistent(pHba->pDev, sizeof(opblk), opblk_va, opblk_pa); if (size == -ETIME) { + pci_free_consistent(pHba->pDev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); return -ETIME; } else if (size == -EINTR) { + pci_free_consistent(pHba->pDev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); return -EINTR; } - memcpy(buf, resblk+8, buflen); /* cut off header */ + memcpy(buf, resblk_va+8, buflen); /* cut off header */ - kfree(resblk); + pci_free_consistent(pHba->pDev, sizeof(u8) * (8+buflen), + resblk_va, resblk_pa); if (size < 0) return size; @@ -3126,10 +3380,11 @@ * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk, int oplen, void *resblk, int reslen) + void *opblk_va, dma_addr_t opblk_pa, int oplen, + void *resblk_va, dma_addr_t resblk_pa, int reslen) { u32 msg[9]; - u32 *res = (u32 *)resblk; + u32 *res = (u32 *)resblk_va; int wait_status; msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; @@ -3138,12 +3393,12 @@ msg[3] = 0; msg[4] = 0; msg[5] = 0x54000000 | oplen; /* OperationBlock */ - msg[6] = virt_to_bus(opblk); + msg[6] = (u32)opblk_pa; msg[7] = 0xD0000000 | reslen; /* ResultBlock */ - msg[8] = virt_to_bus(resblk); + msg[8] = (u32)resblk_pa; if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { - printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk); + printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va); return wait_status; /* -DetailedStatus */ } @@ -3246,7 +3501,7 @@ * Private i/o space declaration */ msg[6] = 0x54000000 | sys_tbl_len; - msg[7] = virt_to_phys(sys_tbl); + msg[7] = (u32)sys_tbl_pa; msg[8] = 0x54000000 | 0; msg[9] = 0; msg[10] = 0xD4000000 | 0; @@ -3324,8 +3579,8 @@ host->max_id = 16; host->max_lun = 256; host->max_channel = pHba->top_scsi_channel + 1; - host->cmd_per_lun = 1; - host->unique_id = (uint) pHba; + host->cmd_per_lun = 1, + host->unique_id = (u32)sys_tbl_pa + pHba->unit; host->sg_tablesize = pHba->sg_tablesize; host->can_queue = pHba->post_fifo_size; diff -ruN dpt-orig/dpti.h dpt-new-mike/dpti.h --- dpt-orig/dpti.h 2007-10-12 18:43:44.000000000 +0200 +++ dpt-new-mike/dpti.h 2007-11-13 01:11:59.000000000 +0100 @@ -225,14 +225,19 @@ u32 post_fifo_size; u32 reply_fifo_size; u32* reply_pool; + dma_addr_t reply_pool_pa; u32 sg_tablesize; // Scatter/Gather List Size. u8 top_scsi_channel; u8 top_scsi_id; u8 top_scsi_lun; + u8 pae_support; i2o_status_block* status_block; + dma_addr_t status_block_pa; i2o_hrt* hrt; + dma_addr_t hrt_pa; i2o_lct* lct; + dma_addr_t lct_pa; uint lct_size; struct i2o_device* devices; struct adpt_channel channel[MAX_CHANNEL]; @@ -245,6 +250,7 @@ void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED u32 FwDebugFlags; + u32 *ioctl_reply_context[4]; } adpt_hba; struct sg_simple_element { @@ -271,7 +277,8 @@ static const char *adpt_i2o_get_class_name(int class); #endif static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk, int oplen, void *resblk, int reslen); + void *opblk, dma_addr_t opblk_pa, int oplen, + void *resblk, dma_addr_t resblk_pa, int reslen); static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout); static int adpt_i2o_lct_get(adpt_hba* pHba); static int adpt_i2o_parse_lct(adpt_hba* pHba);