Skip to content

Commit

Permalink
IB/ipath: Improved support for PowerPC
Browse files Browse the repository at this point in the history
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Bryan O'Sullivan authored and Roland Dreier committed Sep 28, 2006
1 parent 076fafc commit 1fd3b40
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 73 deletions.
60 changes: 36 additions & 24 deletions drivers/infiniband/hw/ipath/ipath_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,8 +755,8 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len)
static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
int err)
{
return dd->ipath_port0_skbs ?
(void *)dd->ipath_port0_skbs[bufnum]->data : NULL;
return dd->ipath_port0_skbinfo ?
(void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL;
}

/**
Expand All @@ -778,31 +778,34 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
*/

/*
* We need 4 extra bytes for unaligned transfer copying
* We need 2 extra bytes for ipath_ether data sent in the
* key header. In order to keep everything dword aligned,
* we'll reserve 4 bytes.
*/
len = dd->ipath_ibmaxlen + 4;

if (dd->ipath_flags & IPATH_4BYTE_TID) {
/* we need a 4KB multiple alignment, and there is no way
/* We need a 2KB multiple alignment, and there is no way
* to do it except to allocate extra and then skb_reserve
* enough to bring it up to the right alignment.
*/
len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1;
len += 2047;
}
else
len = dd->ipath_ibmaxlen + 4;

skb = __dev_alloc_skb(len, gfp_mask);
if (!skb) {
ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n",
len);
goto bail;
}

skb_reserve(skb, 4);

if (dd->ipath_flags & IPATH_4BYTE_TID) {
u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4);
u32 una = (unsigned long)skb->data & 2047;
if (una)
skb_reserve(skb, 4 + (1 << 11) - una);
else
skb_reserve(skb, 4);
} else
skb_reserve(skb, 4);
skb_reserve(skb, 2048 - una);
}

bail:
return skb;
Expand Down Expand Up @@ -1345,8 +1348,9 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; "
"hdrtailaddr@%p %llx physical\n",
pd->port_port, pd->port_rcvhdrq,
pd->port_rcvhdrq_phys, pd->port_rcvhdrtail_kvaddr,
(unsigned long long)pd->port_rcvhdrqtailaddr_phys);
(unsigned long long) pd->port_rcvhdrq_phys,
pd->port_rcvhdrtail_kvaddr, (unsigned long long)
pd->port_rcvhdrqtailaddr_phys);

/* clear for security and sanity on each use */
memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size);
Expand Down Expand Up @@ -1827,17 +1831,22 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
kfree(pd->port_rcvegrbuf_phys);
pd->port_rcvegrbuf_phys = NULL;
pd->port_rcvegrbuf_chunks = 0;
} else if (pd->port_port == 0 && dd->ipath_port0_skbs) {
} else if (pd->port_port == 0 && dd->ipath_port0_skbinfo) {
unsigned e;
struct sk_buff **skbs = dd->ipath_port0_skbs;
struct ipath_skbinfo *skbinfo = dd->ipath_port0_skbinfo;

dd->ipath_port0_skbs = NULL;
ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs "
"@ %p\n", pd->port_port, skbs);
dd->ipath_port0_skbinfo = NULL;
ipath_cdbg(VERBOSE, "free closed port %d "
"ipath_port0_skbinfo @ %p\n", pd->port_port,
skbinfo);
for (e = 0; e < dd->ipath_rcvegrcnt; e++)
if (skbs[e])
dev_kfree_skb(skbs[e]);
vfree(skbs);
if (skbinfo[e].skb) {
pci_unmap_single(dd->pcidev, skbinfo[e].phys,
dd->ipath_ibmaxlen,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(skbinfo[e].skb);
}
vfree(skbinfo);
}
kfree(pd->port_tid_pg_list);
vfree(pd->subport_uregbase);
Expand Down Expand Up @@ -1934,7 +1943,7 @@ static void cleanup_device(struct ipath_devdata *dd)

if (dd->ipath_pioavailregs_dma) {
dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
dd->ipath_pioavailregs_dma,
(void *) dd->ipath_pioavailregs_dma,
dd->ipath_pioavailregs_phys);
dd->ipath_pioavailregs_dma = NULL;
}
Expand All @@ -1947,6 +1956,7 @@ static void cleanup_device(struct ipath_devdata *dd)

if (dd->ipath_pageshadow) {
struct page **tmpp = dd->ipath_pageshadow;
dma_addr_t *tmpd = dd->ipath_physshadow;
int i, cnt = 0;

ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
Expand All @@ -1957,6 +1967,8 @@ static void cleanup_device(struct ipath_devdata *dd)
for (i = port_tidbase; i < maxtid; i++) {
if (!tmpp[i])
continue;
pci_unmap_page(dd->pcidev, tmpd[i],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
ipath_release_user_pages(&tmpp[i], 1);
tmpp[i] = NULL;
cnt++;
Expand Down
55 changes: 33 additions & 22 deletions drivers/infiniband/hw/ipath/ipath_file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,14 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
"vaddr %lx\n", i, tid + tidoff, vaddr);
/* we "know" system pages and TID pages are same size */
dd->ipath_pageshadow[porttid + tid] = pagep[i];
dd->ipath_physshadow[porttid + tid] = ipath_map_page(
dd->pcidev, pagep[i], 0, PAGE_SIZE,
PCI_DMA_FROMDEVICE);
/*
* don't need atomic or it's overhead
*/
__set_bit(tid, tidmap);
physaddr = page_to_phys(pagep[i]);
physaddr = dd->ipath_physshadow[porttid + tid];
ipath_stats.sps_pagelocks++;
ipath_cdbg(VERBOSE,
"TID %u, vaddr %lx, physaddr %llx pgp %p\n",
Expand Down Expand Up @@ -402,6 +405,9 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
tid);
dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
dd->ipath_tidinvalid);
pci_unmap_page(dd->pcidev,
dd->ipath_physshadow[porttid + tid],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
dd->ipath_pageshadow[porttid + tid] = NULL;
ipath_stats.sps_pageunlocks++;
}
Expand Down Expand Up @@ -515,6 +521,9 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport,
pd->port_pid, tid);
dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
dd->ipath_tidinvalid);
pci_unmap_page(dd->pcidev,
dd->ipath_physshadow[porttid + tid],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
ipath_release_user_pages(
&dd->ipath_pageshadow[porttid + tid], 1);
dd->ipath_pageshadow[porttid + tid] = NULL;
Expand Down Expand Up @@ -711,7 +720,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
* updated and correct itself, even in the face of software
* bugs.
*/
*pd->port_rcvhdrtail_kvaddr = 0;
*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
&dd->ipath_rcvctrl);
} else
Expand Down Expand Up @@ -923,11 +932,11 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)

/* common code for the mappings on dma_alloc_coherent mem */
static int ipath_mmap_mem(struct vm_area_struct *vma,
struct ipath_portdata *pd, unsigned len,
int write_ok, dma_addr_t addr, char *what)
struct ipath_portdata *pd, unsigned len, int write_ok,
void *kvaddr, char *what)
{
struct ipath_devdata *dd = pd->port_dd;
unsigned pfn = (unsigned long)addr >> PAGE_SHIFT;
unsigned long pfn;
int ret;

if ((vma->vm_end - vma->vm_start) > len) {
Expand All @@ -950,17 +959,17 @@ static int ipath_mmap_mem(struct vm_area_struct *vma,
vma->vm_flags &= ~VM_MAYWRITE;
}

pfn = virt_to_phys(kvaddr) >> PAGE_SHIFT;
ret = remap_pfn_range(vma, vma->vm_start, pfn,
len, vma->vm_page_prot);
if (ret)
dev_info(&dd->pcidev->dev,
"%s port%u mmap of %lx, %x bytes r%c failed: %d\n",
what, pd->port_port, (unsigned long)addr, len,
write_ok?'w':'o', ret);
dev_info(&dd->pcidev->dev, "%s port%u mmap of %lx, %x "
"bytes r%c failed: %d\n", what, pd->port_port,
pfn, len, write_ok?'w':'o', ret);
else
ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes r%c\n",
what, pd->port_port, (unsigned long)addr, len,
write_ok?'w':'o');
ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes "
"r%c\n", what, pd->port_port, pfn, len,
write_ok?'w':'o');
bail:
return ret;
}
Expand Down Expand Up @@ -1049,7 +1058,7 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
struct ipath_devdata *dd = pd->port_dd;
unsigned long start, size;
size_t total_size, i;
dma_addr_t *phys;
unsigned long pfn;
int ret;

size = pd->port_rcvegrbuf_size;
Expand All @@ -1073,11 +1082,11 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma,
vma->vm_flags &= ~VM_MAYWRITE;

start = vma->vm_start;
phys = pd->port_rcvegrbuf_phys;

for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) {
ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT,
size, vma->vm_page_prot);
pfn = virt_to_phys(pd->port_rcvegrbuf[i]) >> PAGE_SHIFT;
ret = remap_pfn_range(vma, start, pfn, size,
vma->vm_page_prot);
if (ret < 0)
goto bail;
}
Expand Down Expand Up @@ -1290,7 +1299,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
else if (pgaddr == dd->ipath_pioavailregs_phys)
/* in-memory copy of pioavail registers */
ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0,
dd->ipath_pioavailregs_phys,
(void *) dd->ipath_pioavailregs_dma,
"pioavail registers");
else if (subport_fp(fp))
/* Subports don't mmap the physical receive buffers */
Expand All @@ -1304,12 +1313,12 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
* from an i/o perspective.
*/
ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1,
pd->port_rcvhdrq_phys,
pd->port_rcvhdrq,
"rcvhdrq");
else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys)
/* in-memory copy of rcvhdrq tail register */
ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0,
pd->port_rcvhdrqtailaddr_phys,
pd->port_rcvhdrtail_kvaddr,
"rcvhdrq tail");
else
ret = -EINVAL;
Expand Down Expand Up @@ -1802,7 +1811,7 @@ static int ipath_do_user_init(struct file *fp,
* We explictly set the in-memory copy to 0 beforehand, so we don't
* have to wait to be sure the DMA update has happened.
*/
*pd->port_rcvhdrtail_kvaddr = 0ULL;
*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
&dd->ipath_rcvctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
Expand Down Expand Up @@ -1832,6 +1841,8 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
if (!dd->ipath_pageshadow[i])
continue;

pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
1);
dd->ipath_pageshadow[i] = NULL;
Expand Down Expand Up @@ -1936,14 +1947,14 @@ static int ipath_close(struct inode *in, struct file *fp)
i = dd->ipath_pbufsport * (port - 1);
ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);

dd->ipath_f_clear_tids(dd, pd->port_port);

if (dd->ipath_pageshadow)
unlock_expected_tids(pd);
ipath_stats.sps_ports--;
ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
pd->port_comm, pd->port_pid,
dd->ipath_unit, port);

dd->ipath_f_clear_tids(dd, pd->port_port);
}

pd->port_pid = 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/ipath/ipath_iba6120.c
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
if (pa != dd->ipath_tidinvalid) {
if (pa & ((1U << 11) - 1)) {
dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
"not 4KB aligned!\n", pa);
"not 2KB aligned!\n", pa);
return;
}
pa >>= 11;
Expand Down
Loading

0 comments on commit 1fd3b40

Please sign in to comment.