Commit 049c1fb4 authored by Eli Billauer's avatar Eli Billauer Committed by Greg Kroah-Hartman

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: default avatarEli Billauer <eli.billauer@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cc6289fa
......@@ -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;
}
/*
* 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]);
channel->wr_buffers = buffers;
rc = xilly_get_dma_buffers(ep, &wr_alloc, buffers,
bufnum, bytebufsize);
} else {
ep->msgbuf_addr = wr_salami;
ep->msgbuf_dma_addr = dma_addr;
ep->msg_buf_size = bytebufsize;
rc = xilly_get_dma_buffers(ep, &wr_alloc, NULL,
bufnum, 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;
}
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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment