summaryrefslogtreecommitdiff
path: root/drivers/staging/xillybus
diff options
context:
space:
mode:
authorEli Billauer <eli.billauer@gmail.com>2014-07-05 12:45:08 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-09 12:20:37 -0700
commit049c1fb4fc2a45a51b51bf9abb24cd5fd1b3fcf3 (patch)
treec845fe5b55a06794f0764be3ae5bea459413a619 /drivers/staging/xillybus
parentcc6289fa1469831b806f2a857a19169d15759c31 (diff)
staging: xillybus: Reorganizing xilly_setupchannels()
Duplicate code in this function was moved into a new function, xilly_get_dma_buffers(). There is no change in functionality. Signed-off-by: Eli Billauer <eli.billauer@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/xillybus')
-rw-r--r--drivers/staging/xillybus/xillybus_core.c345
1 files changed, 138 insertions, 207 deletions
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c
index fa799795f714..134800de13eb 100644
--- a/drivers/staging/xillybus/xillybus_core.c
+++ b/drivers/staging/xillybus/xillybus_core.c
@@ -319,28 +319,130 @@ EXPORT_SYMBOL(xillybus_isr);
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)
+{
+ int i, rc;
+ dma_addr_t dma_addr;
+ struct device *dev = ep->dev;
+ struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */
+
+ if (buffers) { /* Not the message buffer */
+ this_buffer = devm_kzalloc(
+ dev, bufnum * sizeof(struct xilly_buffer),
+ GFP_KERNEL);
+
+ if (!this_buffer)
+ return -ENOMEM;
+ }
+
+ 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.
+ */
+
+ if ((s->left_of_salami < bytebufsize) &&
+ (s->left_of_salami > 0)) {
+ dev_err(ep->dev,
+ "Corrupt buffer allocation in IDT. Aborting.\n");
+ return -ENODEV;
+ }
+
+ if (s->left_of_salami == 0) {
+ int allocorder, allocsize;
+
+ allocsize = PAGE_SIZE;
+ allocorder = 0;
+ while (bytebufsize > allocsize) {
+ allocsize *= 2;
+ allocorder++;
+ }
+
+ s->salami = (void *) devm_get_free_pages(
+ dev,
+ GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO,
+ allocorder);
+
+ if (!s->salami)
+ return -ENOMEM;
+ s->left_of_salami = allocsize;
+ }
+
+ rc = ep->ephw->map_single(ep, s->salami,
+ bytebufsize, s->direction,
+ &dma_addr);
+
+ if (rc)
+ return rc;
+
+ 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 (buffers) { /* Not the message buffer */
+ this_buffer->addr = s->salami;
+ this_buffer->dma_addr = dma_addr;
+ buffers[i] = this_buffer++;
+
+ 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;
+
+ iowrite32(s->regdirection,
+ &ep->registers[fpga_dma_bufno_reg]);
+ }
+
+ s->left_of_salami -= bytebufsize;
+ s->salami += bytebufsize;
+ }
+ return 0; /* Success */
+}
+
static int xilly_setupchannels(struct xilly_endpoint *ep,
unsigned char *chandesc,
int entries
)
{
struct device *dev = ep->dev;
- int i, entry, wr_nbuffer, rd_nbuffer;
+ 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;
- const gfp_t gfp_mask = GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO;
- struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */
- int rc = 0;
+ 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);
@@ -395,17 +497,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;
@@ -426,40 +520,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 = devm_kzalloc(dev,
+ buffers = devm_kzalloc(dev,
bufnum * sizeof(struct xilly_buffer *),
GFP_KERNEL);
- if (!channel->rd_buffers)
+ if (!buffers)
goto memfail;
+ } else
+ bytebufsize = bufsize << 2;
- this_buffer = devm_kzalloc(dev,
- bufnum * sizeof(struct xilly_buffer),
- GFP_KERNEL);
+ 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;
- if (!this_buffer)
- goto memfail;
+ 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;
@@ -468,171 +557,17 @@ static int xilly_setupchannels(struct xilly_endpoint *ep,
channel->wr_synchronous = synchronous;
channel->wr_exclusive_open = exclusive_open;
- channel->wr_buffers = devm_kzalloc(dev,
- bufnum * sizeof(struct xilly_buffer *),
- GFP_KERNEL);
-
- if (!channel->wr_buffers)
- goto memfail;
-
- this_buffer = devm_kzalloc(dev,
- bufnum * sizeof(struct xilly_buffer),
- GFP_KERNEL);
-
- 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 *)
- devm_get_free_pages(
- dev, gfp_mask,
- allocorder);
-
- if (!wr_salami)
- goto memfail;
- left_of_wr_salami = allocsize;
- }
-
- rc = ep->ephw->map_single(ep, wr_salami,
- bytebufsize,
- DMA_FROM_DEVICE,
- &dma_addr);
-
- if (rc)
- 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 *)
- devm_get_free_pages(
- dev, gfp_mask,
- allocorder);
-
- if (!rd_salami)
- goto memfail;
- left_of_rd_salami = allocsize;
- }
-
-
- rc = ep->ephw->map_single(ep, rd_salami,
- bytebufsize,
- DMA_TO_DEVICE,
- &dma_addr);
-
- if (rc)
- 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) {
@@ -640,16 +575,12 @@ 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");
+ "Failed to assign DMA buffer memory. Aborting.\n");
return -ENOMEM;
-dmafail:
- dev_err(ep->dev, "Failed to map DMA memory!. Aborting.\n");
- return rc;
}
static void xilly_scan_idt(struct xilly_endpoint *endpoint,