diff options
Diffstat (limited to 'drivers/staging/xillybus/xillybus_core.c')
-rw-r--r-- | drivers/staging/xillybus/xillybus_core.c | 541 |
1 files changed, 199 insertions, 342 deletions
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c index fe8f9d28b03b..0214009f7513 100644 --- a/drivers/staging/xillybus/xillybus_core.c +++ b/drivers/staging/xillybus/xillybus_core.c @@ -44,14 +44,14 @@ MODULE_LICENSE("GPL v2"); #define XILLY_RX_TIMEOUT (10*HZ/1000) #define XILLY_TIMEOUT (100*HZ/1000) -#define fpga_msg_ctrl_reg 0x0002 -#define fpga_dma_control_reg 0x0008 -#define fpga_dma_bufno_reg 0x0009 -#define fpga_dma_bufaddr_lowaddr_reg 0x000a -#define fpga_dma_bufaddr_highaddr_reg 0x000b -#define fpga_buf_ctrl_reg 0x000c -#define fpga_buf_offset_reg 0x000d -#define fpga_endian_reg 0x0010 +#define fpga_msg_ctrl_reg 0x0008 +#define fpga_dma_control_reg 0x0020 +#define fpga_dma_bufno_reg 0x0024 +#define fpga_dma_bufaddr_lowaddr_reg 0x0028 +#define fpga_dma_bufaddr_highaddr_reg 0x002c +#define fpga_buf_ctrl_reg 0x0030 +#define fpga_buf_offset_reg 0x0034 +#define fpga_endian_reg 0x0040 #define XILLYMSG_OPCODE_RELEASEBUF 1 #define XILLYMSG_OPCODE_QUIESCEACK 2 @@ -138,7 +138,6 @@ irqreturn_t xillybus_isr(int irq, void *data) * guaranteed no interrupt will occur, but in theory, the cache * lines may not be updated. So a memory barrier is issued. */ - smp_rmb(); buf = ep->msgbuf_addr; @@ -159,10 +158,10 @@ irqreturn_t xillybus_isr(int irq, void *data) ep->msg_counter, i/2); - if (++ep->failed_messages > 10) + if (++ep->failed_messages > 10) { dev_err(ep->dev, "Lost sync with interrupt messages. Stopping.\n"); - else { + } else { ep->ephw->hw_sync_sgl_for_device( ep, ep->msgbuf_dma_addr, @@ -170,7 +169,7 @@ irqreturn_t xillybus_isr(int irq, void *data) DMA_FROM_DEVICE); iowrite32(0x01, /* Message NACK */ - &ep->registers[fpga_msg_ctrl_reg]); + ep->registers + fpga_msg_ctrl_reg); } return IRQ_HANDLED; } else if (buf[i] & (1 << 22)) /* Last message */ @@ -267,6 +266,12 @@ irqreturn_t xillybus_isr(int irq, void *data) break; case XILLYMSG_OPCODE_FIFOEOF: + if ((msg_channel > ep->num_channels) || + (msg_channel == 0) || (!msg_dir) || + !ep->channels[msg_channel]->num_wr_buffers) { + malformed_message(ep, &buf[i]); + break; + } channel = ep->channels[msg_channel]; spin_lock(&channel->wr_spinlock); channel->wr_eof = msg_bufno; @@ -299,7 +304,7 @@ irqreturn_t xillybus_isr(int irq, void *data) ep->msg_counter = (ep->msg_counter + 1) & 0xf; ep->failed_messages = 0; - iowrite32(0x03, &ep->registers[fpga_msg_ctrl_reg]); /* Message ACK */ + iowrite32(0x03, ep->registers + fpga_msg_ctrl_reg); /* Message ACK */ return IRQ_HANDLED; } @@ -311,108 +316,142 @@ EXPORT_SYMBOL(xillybus_isr); * no locks are applied! */ -void xillybus_do_cleanup(struct xilly_cleanup *mem, - struct xilly_endpoint *endpoint) +static void xillybus_autoflush(struct work_struct *work); + +struct xilly_alloc_state { + void *salami; + int left_of_salami; + int nbuffer; + enum dma_data_direction direction; + u32 regdirection; +}; + +static int xilly_get_dma_buffers(struct xilly_endpoint *ep, + struct xilly_alloc_state *s, + struct xilly_buffer **buffers, + int bufnum, int bytebufsize) { - struct list_head *this, *next; + int i, rc; + dma_addr_t dma_addr; + struct device *dev = ep->dev; + struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */ - list_for_each_safe(this, next, &mem->to_unmap) { - struct xilly_dma *entry = - list_entry(this, struct xilly_dma, node); + if (buffers) { /* Not the message buffer */ + this_buffer = devm_kzalloc( + dev, bufnum * sizeof(struct xilly_buffer), + GFP_KERNEL); - endpoint->ephw->unmap_single(entry); - kfree(entry); + if (!this_buffer) + return -ENOMEM; } - INIT_LIST_HEAD(&mem->to_unmap); - - list_for_each_safe(this, next, &mem->to_kfree) - kfree(this); + for (i = 0; i < bufnum; i++) { + /* + * Buffers are expected in descending size order, so there + * is either enough space for this buffer or none at all. + */ - INIT_LIST_HEAD(&mem->to_kfree); + if ((s->left_of_salami < bytebufsize) && + (s->left_of_salami > 0)) { + dev_err(ep->dev, + "Corrupt buffer allocation in IDT. Aborting.\n"); + return -ENODEV; + } - list_for_each_safe(this, next, &mem->to_pagefree) { - struct xilly_page *entry = - list_entry(this, struct xilly_page, node); + if (s->left_of_salami == 0) { + int allocorder, allocsize; - free_pages(entry->addr, entry->order); - kfree(entry); - } - INIT_LIST_HEAD(&mem->to_pagefree); -} -EXPORT_SYMBOL(xillybus_do_cleanup); + allocsize = PAGE_SIZE; + allocorder = 0; + while (bytebufsize > allocsize) { + allocsize *= 2; + allocorder++; + } -static void *xilly_malloc(struct xilly_cleanup *mem, size_t size) -{ - void *ptr; + s->salami = (void *) devm_get_free_pages( + dev, + GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO, + allocorder); - ptr = kzalloc(sizeof(struct list_head) + size, GFP_KERNEL); + if (!s->salami) + return -ENOMEM; + s->left_of_salami = allocsize; + } - if (!ptr) - return ptr; + rc = ep->ephw->map_single(ep, s->salami, + bytebufsize, s->direction, + &dma_addr); - list_add_tail((struct list_head *) ptr, &mem->to_kfree); + if (rc) + return rc; - return ptr + sizeof(struct list_head); -} + iowrite32((u32) (dma_addr & 0xffffffff), + ep->registers + fpga_dma_bufaddr_lowaddr_reg); + iowrite32(((u32) ((((u64) dma_addr) >> 32) & 0xffffffff)), + ep->registers + fpga_dma_bufaddr_highaddr_reg); + mmiowb(); -static unsigned long xilly_pagealloc(struct xilly_cleanup *mem, - unsigned long order) -{ - unsigned long addr; - struct xilly_page *this; + if (buffers) { /* Not the message buffer */ + this_buffer->addr = s->salami; + this_buffer->dma_addr = dma_addr; + buffers[i] = this_buffer++; - this = kmalloc(sizeof(struct xilly_page), GFP_KERNEL); - if (!this) - return 0; + iowrite32(s->regdirection | s->nbuffer++, + ep->registers + fpga_dma_bufno_reg); + } else { + ep->msgbuf_addr = s->salami; + ep->msgbuf_dma_addr = dma_addr; + ep->msg_buf_size = bytebufsize; - addr = __get_free_pages(GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO, order); + iowrite32(s->regdirection, + ep->registers + fpga_dma_bufno_reg); + } - if (!addr) { - kfree(this); - return 0; + s->left_of_salami -= bytebufsize; + s->salami += bytebufsize; } - - this->addr = addr; - this->order = order; - - list_add_tail(&this->node, &mem->to_pagefree); - - return addr; + return 0; /* Success */ } - -static void xillybus_autoflush(struct work_struct *work); - static int xilly_setupchannels(struct xilly_endpoint *ep, - struct xilly_cleanup *mem, unsigned char *chandesc, int entries ) { - int i, entry, wr_nbuffer, rd_nbuffer; + struct device *dev = ep->dev; + int i, entry, rc; struct xilly_channel *channel; int channelnum, bufnum, bufsize, format, is_writebuf; int bytebufsize; int synchronous, allowpartial, exclusive_open, seekable; int supports_nonempty; - void *wr_salami = NULL; - void *rd_salami = NULL; - int left_of_wr_salami = 0; - int left_of_rd_salami = 0; - dma_addr_t dma_addr; int msg_buf_done = 0; - struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */ - - channel = xilly_malloc(mem, ep->num_channels * - sizeof(struct xilly_channel)); + struct xilly_alloc_state rd_alloc = { + .salami = NULL, + .left_of_salami = 0, + .nbuffer = 1, + .direction = DMA_TO_DEVICE, + .regdirection = 0, + }; + + struct xilly_alloc_state wr_alloc = { + .salami = NULL, + .left_of_salami = 0, + .nbuffer = 1, + .direction = DMA_FROM_DEVICE, + .regdirection = 0x80000000, + }; + + channel = devm_kzalloc(dev, ep->num_channels * + sizeof(struct xilly_channel), GFP_KERNEL); if (!channel) goto memfail; - ep->channels = xilly_malloc(mem, (ep->num_channels + 1) * - sizeof(struct xilly_channel *)); + ep->channels = devm_kzalloc(dev, (ep->num_channels + 1) * + sizeof(struct xilly_channel *), + GFP_KERNEL); if (!ep->channels) goto memfail; @@ -457,17 +496,9 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, ep->channels[i] = channel++; } - /* - * The DMA buffer address update is atomic on the FPGA, so even if - * it was in the middle of sending messages to some buffer, changing - * the address is safe, since the data will go to either of the - * buffers. Not that this situation should occur at all anyhow. - */ - - wr_nbuffer = 1; - rd_nbuffer = 1; /* Buffer zero isn't used at all */ - for (entry = 0; entry < entries; entry++, chandesc += 4) { + struct xilly_buffer **buffers = NULL; + is_writebuf = chandesc[0] & 0x01; channelnum = (chandesc[0] >> 1) | ((chandesc[1] & 0x0f) << 7); format = (chandesc[1] >> 4) & 0x03; @@ -488,40 +519,35 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, channel = ep->channels[channelnum]; /* NULL for msg channel */ - bytebufsize = bufsize << 2; /* Overwritten just below */ - - if (!is_writebuf) { - channel->num_rd_buffers = bufnum; + if (!is_writebuf || channelnum > 0) { channel->log2_element_size = ((format > 2) ? 2 : format); + bytebufsize = channel->rd_buf_size = bufsize * (1 << channel->log2_element_size); - channel->rd_allow_partial = allowpartial; - channel->rd_synchronous = synchronous; - channel->rd_exclusive_open = exclusive_open; - channel->seekable = seekable; - - channel->rd_buffers = xilly_malloc( - mem, - bufnum * sizeof(struct xilly_buffer *)); - if (!channel->rd_buffers) - goto memfail; - - this_buffer = xilly_malloc( - mem, - bufnum * sizeof(struct xilly_buffer)); + buffers = devm_kzalloc(dev, + bufnum * sizeof(struct xilly_buffer *), + GFP_KERNEL); - if (!this_buffer) + if (!buffers) goto memfail; + } else { + bytebufsize = bufsize << 2; } - else if (channelnum > 0) { + if (!is_writebuf) { + channel->num_rd_buffers = bufnum; + channel->rd_allow_partial = allowpartial; + channel->rd_synchronous = synchronous; + channel->rd_exclusive_open = exclusive_open; + channel->seekable = seekable; + + channel->rd_buffers = buffers; + rc = xilly_get_dma_buffers(ep, &rd_alloc, buffers, + bufnum, bytebufsize); + } else if (channelnum > 0) { channel->num_wr_buffers = bufnum; - channel->log2_element_size = ((format > 2) ? - 2 : format); - bytebufsize = channel->wr_buf_size = bufsize * - (1 << channel->log2_element_size); channel->seekable = seekable; channel->wr_supports_nonempty = supports_nonempty; @@ -530,172 +556,17 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, channel->wr_synchronous = synchronous; channel->wr_exclusive_open = exclusive_open; - channel->wr_buffers = xilly_malloc( - mem, - bufnum * sizeof(struct xilly_buffer *)); - - if (!channel->wr_buffers) - goto memfail; - - this_buffer = xilly_malloc( - mem, - bufnum * sizeof(struct xilly_buffer)); - - if (!this_buffer) - goto memfail; + channel->wr_buffers = buffers; + rc = xilly_get_dma_buffers(ep, &wr_alloc, buffers, + bufnum, bytebufsize); + } else { + rc = xilly_get_dma_buffers(ep, &wr_alloc, NULL, + bufnum, bytebufsize); + msg_buf_done++; } - /* - * Although daunting, we cut the chunks for read buffers - * from a different salami than the write buffers', - * possibly improving performance. - */ - - if (is_writebuf) - for (i = 0; i < bufnum; i++) { - /* - * Buffers are expected in descending - * byte-size order, so there is either - * enough for this buffer or none at all. - */ - if ((left_of_wr_salami < bytebufsize) && - (left_of_wr_salami > 0)) { - dev_err(ep->dev, - "Corrupt buffer allocation in IDT. Aborting.\n"); - return -ENODEV; - } - - if (left_of_wr_salami == 0) { - int allocorder, allocsize; - - allocsize = PAGE_SIZE; - allocorder = 0; - while (bytebufsize > allocsize) { - allocsize *= 2; - allocorder++; - } - - wr_salami = (void *) - xilly_pagealloc(mem, - allocorder); - if (!wr_salami) - goto memfail; - left_of_wr_salami = allocsize; - } - - dma_addr = ep->ephw->map_single( - mem, - ep, - wr_salami, - bytebufsize, - DMA_FROM_DEVICE); - - if (!dma_addr) - goto dmafail; - - iowrite32( - (u32) (dma_addr & 0xffffffff), - &ep->registers[ - fpga_dma_bufaddr_lowaddr_reg] - ); - iowrite32( - ((u32) ((((u64) dma_addr) >> 32) - & 0xffffffff)), - &ep->registers[ - fpga_dma_bufaddr_highaddr_reg] - ); - mmiowb(); - - if (channelnum > 0) { - this_buffer->addr = wr_salami; - this_buffer->dma_addr = dma_addr; - channel->wr_buffers[i] = this_buffer++; - - iowrite32( - 0x80000000 | wr_nbuffer++, - &ep->registers[ - fpga_dma_bufno_reg]); - } else { - ep->msgbuf_addr = wr_salami; - ep->msgbuf_dma_addr = dma_addr; - ep->msg_buf_size = bytebufsize; - msg_buf_done++; - - iowrite32( - 0x80000000, &ep->registers[ - fpga_dma_bufno_reg]); - } - - left_of_wr_salami -= bytebufsize; - wr_salami += bytebufsize; - } - else /* Read buffers */ - for (i = 0; i < bufnum; i++) { - /* - * Buffers are expected in descending - * byte-size order, so there is either - * enough for this buffer or none at all. - */ - if ((left_of_rd_salami < bytebufsize) && - (left_of_rd_salami > 0)) { - dev_err(ep->dev, - "Corrupt buffer allocation in IDT. Aborting.\n"); - return -ENODEV; - } - - if (left_of_rd_salami == 0) { - int allocorder, allocsize; - - allocsize = PAGE_SIZE; - allocorder = 0; - while (bytebufsize > allocsize) { - allocsize *= 2; - allocorder++; - } - - rd_salami = (void *) - xilly_pagealloc( - mem, - allocorder); - - if (!rd_salami) - goto memfail; - left_of_rd_salami = allocsize; - } - - dma_addr = ep->ephw->map_single( - mem, - ep, - rd_salami, - bytebufsize, - DMA_TO_DEVICE); - - if (!dma_addr) - goto dmafail; - - iowrite32( - (u32) (dma_addr & 0xffffffff), - &ep->registers[ - fpga_dma_bufaddr_lowaddr_reg] - ); - iowrite32( - ((u32) ((((u64) dma_addr) >> 32) - & 0xffffffff)), - &ep->registers[ - fpga_dma_bufaddr_highaddr_reg] - ); - mmiowb(); - - this_buffer->addr = rd_salami; - this_buffer->dma_addr = dma_addr; - channel->rd_buffers[i] = this_buffer++; - - iowrite32(rd_nbuffer++, - &ep->registers[fpga_dma_bufno_reg]); - - left_of_rd_salami -= bytebufsize; - rd_salami += bytebufsize; - } + if (rc) + goto memfail; } if (!msg_buf_done) { @@ -703,15 +574,11 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, "Corrupt IDT: No message buffer. Aborting.\n"); return -ENODEV; } - return 0; memfail: dev_err(ep->dev, - "Failed to allocate write buffer memory. Aborting.\n"); - return -ENOMEM; -dmafail: - dev_err(ep->dev, "Failed to map DMA memory!. Aborting.\n"); + "Failed to assign DMA buffer memory. Aborting.\n"); return -ENOMEM; } @@ -742,8 +609,8 @@ static void xilly_scan_idt(struct xilly_endpoint *endpoint, "IDT device name list overflow. Aborting.\n"); idt_handle->chandesc = NULL; return; - } else - idt_handle->chandesc = scan; + } + idt_handle->chandesc = scan; len = endpoint->idtlen - (3 + ((int) (scan - idt))); @@ -772,7 +639,7 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint) iowrite32(1 | (3 << 24), /* Opcode 3 for channel 0 = Send IDT */ - &endpoint->registers[fpga_buf_ctrl_reg]); + endpoint->registers + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ wait_event_interruptible_timeout(channel->wr_wait, @@ -854,6 +721,7 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf, while (1) { /* Note that we may drop mutex within this loop */ int bytes_to_do = count - bytes_done; + spin_lock_irqsave(&channel->wr_spinlock, flags); empty = channel->wr_empty; @@ -944,8 +812,8 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf, iowrite32(1 | (channel->chan_num << 1) | (bufidx << 12), - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ } @@ -1031,15 +899,15 @@ static ssize_t xillybus_read(struct file *filp, char __user *userbuf, mutex_lock(&channel->endpoint->register_mutex); iowrite32(offsetlimit, - &channel->endpoint->registers[ - fpga_buf_offset_reg]); + channel->endpoint->registers + + fpga_buf_offset_reg); mmiowb(); iowrite32(1 | (channel->chan_num << 1) | (2 << 24) | /* 2 = offset limit */ (waiting_bufidx << 12), - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ @@ -1131,8 +999,8 @@ desperate: iowrite32(1 | (channel->chan_num << 1) | (3 << 24) | /* Opcode 3, flush it all! */ (waiting_bufidx << 12), - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ } @@ -1244,13 +1112,13 @@ static int xillybus_myflush(struct xilly_channel *channel, long timeout) mutex_lock(&channel->endpoint->register_mutex); iowrite32(end_offset_plus1 - 1, - &channel->endpoint->registers[fpga_buf_offset_reg]); + channel->endpoint->registers + fpga_buf_offset_reg); mmiowb(); iowrite32((channel->chan_num << 1) | /* Channel ID */ (2 << 24) | /* Opcode 2, submit buffer */ (bufidx << 12), - &channel->endpoint->registers[fpga_buf_ctrl_reg]); + channel->endpoint->registers + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ mutex_unlock(&channel->endpoint->register_mutex); @@ -1494,14 +1362,14 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf, mutex_lock(&channel->endpoint->register_mutex); iowrite32(end_offset_plus1 - 1, - &channel->endpoint->registers[ - fpga_buf_offset_reg]); + channel->endpoint->registers + + fpga_buf_offset_reg); mmiowb(); iowrite32((channel->chan_num << 1) | (2 << 24) | /* 2 = submit buffer */ (bufidx << 12), - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ mutex_unlock(&channel->endpoint-> @@ -1696,8 +1564,8 @@ static int xillybus_open(struct inode *inode, struct file *filp) iowrite32(1 | (channel->chan_num << 1) | (4 << 24) | /* Opcode 4, open channel */ ((channel->wr_synchronous & 1) << 23), - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ } @@ -1718,8 +1586,8 @@ static int xillybus_open(struct inode *inode, struct file *filp) iowrite32((channel->chan_num << 1) | (4 << 24), /* Opcode 4, open channel */ - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ } @@ -1771,8 +1639,8 @@ static int xillybus_release(struct inode *inode, struct file *filp) iowrite32((channel->chan_num << 1) | /* Channel ID */ (5 << 24), /* Opcode 5, close channel */ - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ } mutex_unlock(&channel->rd_mutex); @@ -1792,8 +1660,8 @@ static int xillybus_release(struct inode *inode, struct file *filp) iowrite32(1 | (channel->chan_num << 1) | (5 << 24), /* Opcode 5, close channel */ - &channel->endpoint->registers[ - fpga_buf_ctrl_reg]); + channel->endpoint->registers + + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ /* @@ -1898,11 +1766,11 @@ static loff_t xillybus_llseek(struct file *filp, loff_t offset, int whence) mutex_lock(&channel->endpoint->register_mutex); iowrite32(pos >> channel->log2_element_size, - &channel->endpoint->registers[fpga_buf_offset_reg]); + channel->endpoint->registers + fpga_buf_offset_reg); mmiowb(); iowrite32((channel->chan_num << 1) | (6 << 24), /* Opcode 6, set address */ - &channel->endpoint->registers[fpga_buf_ctrl_reg]); + channel->endpoint->registers + fpga_buf_ctrl_reg); mmiowb(); /* Just to appear safe */ mutex_unlock(&channel->endpoint->register_mutex); @@ -2095,17 +1963,12 @@ struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev, struct xilly_endpoint *endpoint; endpoint = devm_kzalloc(dev, sizeof(*endpoint), GFP_KERNEL); - if (!endpoint) { - dev_err(dev, "Failed to allocate memory. Aborting.\n"); + if (!endpoint) return NULL; - } endpoint->pdev = pdev; endpoint->dev = dev; endpoint->ephw = ephw; - INIT_LIST_HEAD(&endpoint->cleanup.to_kfree); - INIT_LIST_HEAD(&endpoint->cleanup.to_pagefree); - INIT_LIST_HEAD(&endpoint->cleanup.to_unmap); endpoint->msg_counter = 0x0b; endpoint->failed_messages = 0; endpoint->fatal_error = 0; @@ -2122,7 +1985,7 @@ static int xilly_quiesce(struct xilly_endpoint *endpoint) endpoint->idtlen = -1; wmb(); /* Make sure idtlen is set before sending command */ iowrite32((u32) (endpoint->dma_using_dac & 0x0001), - &endpoint->registers[fpga_dma_control_reg]); + endpoint->registers + fpga_dma_control_reg); mmiowb(); wait_event_interruptible_timeout(endpoint->ep_wait, @@ -2131,7 +1994,7 @@ static int xilly_quiesce(struct xilly_endpoint *endpoint) if (endpoint->idtlen < 0) { dev_err(endpoint->dev, - "Failed to quiesce the device on exit. Quitting while leaving a mess.\n"); + "Failed to quiesce the device on exit.\n"); return -ENODEV; } return 0; /* Success */ @@ -2141,8 +2004,9 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) { int rc = 0; - struct xilly_cleanup tmpmem; + void *bootstrap_resources; int idtbuffersize = (1 << PAGE_SHIFT); + struct device *dev = endpoint->dev; /* * The bogus IDT is used during bootstrap for allocating the initial @@ -2155,30 +2019,30 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) 3, 192, PAGE_SHIFT, 0 }; struct xilly_idt_handle idt_handle; - INIT_LIST_HEAD(&tmpmem.to_kfree); - INIT_LIST_HEAD(&tmpmem.to_pagefree); - INIT_LIST_HEAD(&tmpmem.to_unmap); - /* * Writing the value 0x00000001 to Endianness register signals which * endianness this processor is using, so the FPGA can swap words as * necessary. */ - iowrite32(1, &endpoint->registers[fpga_endian_reg]); + iowrite32(1, endpoint->registers + fpga_endian_reg); mmiowb(); /* Writes below are affected by the one above. */ /* Bootstrap phase I: Allocate temporary message buffer */ + bootstrap_resources = devres_open_group(dev, NULL, GFP_KERNEL); + if (!bootstrap_resources) + return -ENOMEM; + endpoint->num_channels = 0; - rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 1); + rc = xilly_setupchannels(endpoint, bogus_idt, 1); if (rc) - goto failed_buffers; + return rc; /* Clear the message subsystem (and counter in particular) */ - iowrite32(0x04, &endpoint->registers[fpga_msg_ctrl_reg]); + iowrite32(0x04, endpoint->registers + fpga_msg_ctrl_reg); mmiowb(); endpoint->idtlen = -1; @@ -2190,7 +2054,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) * buffer size. */ iowrite32((u32) (endpoint->dma_using_dac & 0x0001), - &endpoint->registers[fpga_dma_control_reg]); + endpoint->registers + fpga_dma_control_reg); mmiowb(); wait_event_interruptible_timeout(endpoint->ep_wait, @@ -2199,13 +2063,12 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) if (endpoint->idtlen < 0) { dev_err(endpoint->dev, "No response from FPGA. Aborting.\n"); - rc = -ENODEV; - goto failed_quiesce; + return -ENODEV; } /* Enable DMA */ iowrite32((u32) (0x0002 | (endpoint->dma_using_dac & 0x0001)), - &endpoint->registers[fpga_dma_control_reg]); + endpoint->registers + fpga_dma_control_reg); mmiowb(); /* Bootstrap phase II: Allocate buffer for IDT and obtain it */ @@ -2216,7 +2079,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) endpoint->num_channels = 1; - rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 2); + rc = xilly_setupchannels(endpoint, bogus_idt, 2); if (rc) goto failed_idt; @@ -2234,10 +2097,12 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) rc = -ENODEV; goto failed_idt; } + + devres_close_group(dev, bootstrap_resources); + /* Bootstrap phase III: Allocate buffers according to IDT */ rc = xilly_setupchannels(endpoint, - &endpoint->cleanup, idt_handle.chandesc, idt_handle.entries); @@ -2260,7 +2125,7 @@ int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) if (rc) goto failed_chrdevs; - xillybus_do_cleanup(&tmpmem, endpoint); + devres_release_group(dev, bootstrap_resources); return 0; @@ -2270,16 +2135,8 @@ failed_chrdevs: mutex_unlock(&ep_list_lock); failed_idt: - /* Quiesce the device. Now it's serious to do it */ - rc = xilly_quiesce(endpoint); - - if (rc) - return rc; /* FPGA may still DMA, so no release */ - + xilly_quiesce(endpoint); flush_workqueue(xillybus_wq); -failed_quiesce: -failed_buffers: - xillybus_do_cleanup(&tmpmem, endpoint); return rc; } |