diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-06-04 13:09:01 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-06-04 13:09:01 +0200 |
commit | af5666e0f76023d9c296016024297903a4c83108 (patch) | |
tree | 9397e7a41dd3eb0c0e14a6407a8e8f12abed4fc5 /drivers/rapidio | |
parent | 1b15d2e5b8077670b1e6a33250a0d9577efff4a5 (diff) | |
parent | 368c96640d10a145da5f258f2d2833668d4f3629 (diff) |
Merge branches 'for-3.15/upstream-fixes' and 'for-3.16/upstream' into for-linus
Conflicts:
drivers/hid/hid-sensor-hub.c
Diffstat (limited to 'drivers/rapidio')
-rw-r--r-- | drivers/rapidio/devices/tsi721.c | 1 | ||||
-rw-r--r-- | drivers/rapidio/devices/tsi721.h | 4 | ||||
-rw-r--r-- | drivers/rapidio/devices/tsi721_dma.c | 111 | ||||
-rw-r--r-- | drivers/rapidio/rio-driver.c | 22 | ||||
-rw-r--r-- | drivers/rapidio/rio-scan.c | 1 | ||||
-rw-r--r-- | drivers/rapidio/rio-sysfs.c | 40 | ||||
-rw-r--r-- | drivers/rapidio/rio.c | 11 | ||||
-rw-r--r-- | drivers/rapidio/rio.h | 1 |
8 files changed, 151 insertions, 40 deletions
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index ff7cbf2d28e3..1753dc693c15 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2256,6 +2256,7 @@ static int tsi721_setup_mport(struct tsi721_device *priv) mport->phy_type = RIO_PHY_SERIAL; mport->priv = (void *)priv; mport->phys_efptr = 0x100; + mport->dev.parent = &pdev->dev; priv->mport = mport; INIT_LIST_HEAD(&mport->dbells); diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 7061ac0ad428..0305675270ee 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -644,6 +644,9 @@ enum tsi721_smsg_int_flag { #ifdef CONFIG_RAPIDIO_DMA_ENGINE +#define TSI721_BDMA_BD_RING_SZ 128 +#define TSI721_BDMA_MAX_BCOUNT (TSI721_DMAD_BCOUNT1 + 1) + struct tsi721_tx_desc { struct dma_async_tx_descriptor txd; struct tsi721_dma_desc *hw_desc; @@ -652,6 +655,7 @@ struct tsi721_tx_desc { u64 rio_addr; /* upper 2-bits of 66-bit RIO address */ u8 rio_addr_u; + u32 bcount; bool interrupt; struct list_head desc_node; struct list_head tx_list; diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index 91245f5dbe81..9b60b1f3261c 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c @@ -304,35 +304,17 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) } static int -tsi721_fill_desc(struct tsi721_bdma_chan *bdma_chan, - struct tsi721_tx_desc *desc, struct scatterlist *sg, +tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg, enum dma_rtype rtype, u32 sys_size) { struct tsi721_dma_desc *bd_ptr = desc->hw_desc; u64 rio_addr; - if (sg_dma_len(sg) > TSI721_DMAD_BCOUNT1 + 1) { - dev_err(bdma_chan->dchan.device->dev, - "SG element is too large\n"); - return -EINVAL; - } - - dev_dbg(bdma_chan->dchan.device->dev, - "desc: 0x%llx, addr: 0x%llx len: 0x%x\n", - (u64)desc->txd.phys, (unsigned long long)sg_dma_address(sg), - sg_dma_len(sg)); - - dev_dbg(bdma_chan->dchan.device->dev, - "bd_ptr = %p did=%d raddr=0x%llx\n", - bd_ptr, desc->destid, desc->rio_addr); - /* Initialize DMA descriptor */ bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) | (rtype << 19) | desc->destid); - if (desc->interrupt) - bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF); bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) | - (sys_size << 26) | sg_dma_len(sg)); + (sys_size << 26)); rio_addr = (desc->rio_addr >> 2) | ((u64)(desc->rio_addr_u & 0x3) << 62); bd_ptr->raddr_lo = cpu_to_le32(rio_addr & 0xffffffff); @@ -346,6 +328,20 @@ tsi721_fill_desc(struct tsi721_bdma_chan *bdma_chan, return 0; } +static int +tsi721_desc_fill_end(struct tsi721_tx_desc *desc) +{ + struct tsi721_dma_desc *bd_ptr = desc->hw_desc; + + /* Update DMA descriptor */ + if (desc->interrupt) + bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF); + bd_ptr->bcount |= cpu_to_le32(desc->bcount & TSI721_DMAD_BCOUNT1); + + return 0; +} + + static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan, struct tsi721_tx_desc *desc) { @@ -674,6 +670,7 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, unsigned int i; u32 sys_size = dma_to_mport(dchan->device)->sys_size; enum dma_rtype rtype; + dma_addr_t next_addr = -1; if (!sgl || !sg_len) { dev_err(dchan->device->dev, "%s: No SG list\n", __func__); @@ -704,36 +701,84 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, for_each_sg(sgl, sg, sg_len, i) { int err; - dev_dbg(dchan->device->dev, "%s: sg #%d\n", __func__, i); + if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) { + dev_err(dchan->device->dev, + "%s: SG entry %d is too large\n", __func__, i); + goto err_desc_put; + } + + /* + * If this sg entry forms contiguous block with previous one, + * try to merge it into existing DMA descriptor + */ + if (desc) { + if (next_addr == sg_dma_address(sg) && + desc->bcount + sg_dma_len(sg) <= + TSI721_BDMA_MAX_BCOUNT) { + /* Adjust byte count of the descriptor */ + desc->bcount += sg_dma_len(sg); + goto entry_done; + } + + /* + * Finalize this descriptor using total + * byte count value. + */ + tsi721_desc_fill_end(desc); + dev_dbg(dchan->device->dev, "%s: desc final len: %d\n", + __func__, desc->bcount); + } + + /* + * Obtain and initialize a new descriptor + */ desc = tsi721_desc_get(bdma_chan); if (!desc) { dev_err(dchan->device->dev, - "Not enough descriptors available\n"); - goto err_desc_get; + "%s: Failed to get new descriptor for SG %d\n", + __func__, i); + goto err_desc_put; } - if (sg_is_last(sg)) - desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0; - else - desc->interrupt = false; - desc->destid = rext->destid; desc->rio_addr = rio_addr; desc->rio_addr_u = 0; + desc->bcount = sg_dma_len(sg); + + dev_dbg(dchan->device->dev, + "sg%d desc: 0x%llx, addr: 0x%llx len: %d\n", + i, (u64)desc->txd.phys, + (unsigned long long)sg_dma_address(sg), + sg_dma_len(sg)); + + dev_dbg(dchan->device->dev, + "bd_ptr = %p did=%d raddr=0x%llx\n", + desc->hw_desc, desc->destid, desc->rio_addr); - err = tsi721_fill_desc(bdma_chan, desc, sg, rtype, sys_size); + err = tsi721_desc_fill_init(desc, sg, rtype, sys_size); if (err) { dev_err(dchan->device->dev, "Failed to build desc: %d\n", err); - goto err_desc_get; + goto err_desc_put; } - rio_addr += sg_dma_len(sg); + next_addr = sg_dma_address(sg); if (!first) first = desc; else list_add_tail(&desc->desc_node, &first->tx_list); + +entry_done: + if (sg_is_last(sg)) { + desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0; + tsi721_desc_fill_end(desc); + dev_dbg(dchan->device->dev, "%s: desc final len: %d\n", + __func__, desc->bcount); + } else { + rio_addr += sg_dma_len(sg); + next_addr += sg_dma_len(sg); + } } first->txd.cookie = -EBUSY; @@ -741,7 +786,7 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, return &first->txd; -err_desc_get: +err_desc_put: tsi721_desc_put(bdma_chan, first); return NULL; } @@ -792,7 +837,7 @@ int tsi721_register_dma(struct tsi721_device *priv) if (i == TSI721_DMACH_MAINT) continue; - bdma_chan->bd_num = 64; + bdma_chan->bd_num = TSI721_BDMA_BD_RING_SZ; bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i); bdma_chan->dchan.device = &mport->dma; diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index c9ae692d3451..f301f059bb85 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -167,7 +167,6 @@ void rio_unregister_driver(struct rio_driver *rdrv) void rio_attach_device(struct rio_dev *rdev) { rdev->dev.bus = &rio_bus_type; - rdev->dev.parent = &rio_bus; } EXPORT_SYMBOL_GPL(rio_attach_device); @@ -216,9 +215,12 @@ static int rio_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -struct device rio_bus = { - .init_name = "rapidio", +struct class rio_mport_class = { + .name = "rapidio_port", + .owner = THIS_MODULE, + .dev_groups = rio_mport_groups, }; +EXPORT_SYMBOL_GPL(rio_mport_class); struct bus_type rio_bus_type = { .name = "rapidio", @@ -233,14 +235,20 @@ struct bus_type rio_bus_type = { /** * rio_bus_init - Register the RapidIO bus with the device model * - * Registers the RIO bus device and RIO bus type with the Linux + * Registers the RIO mport device class and RIO bus type with the Linux * device model. */ static int __init rio_bus_init(void) { - if (device_register(&rio_bus) < 0) - printk("RIO: failed to register RIO bus device\n"); - return bus_register(&rio_bus_type); + int ret; + + ret = class_register(&rio_mport_class); + if (!ret) { + ret = bus_register(&rio_bus_type); + if (ret) + class_unregister(&rio_mport_class); + } + return ret; } postcore_initcall(rio_bus_init); diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index d3a6539a77cc..47a1b2ea76c4 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -461,6 +461,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rdev->comp_tag & RIO_CTAG_UDEVID); } + rdev->dev.parent = &port->dev; rio_attach_device(rdev); device_initialize(&rdev->dev); diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index e0221c6d0cc2..cdb005c0094d 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -341,3 +341,43 @@ const struct attribute_group *rio_bus_groups[] = { &rio_bus_group, NULL, }; + +static ssize_t +port_destid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct rio_mport *mport = to_rio_mport(dev); + + if (mport) + return sprintf(buf, "0x%04x\n", mport->host_deviceid); + else + return -ENODEV; +} +static DEVICE_ATTR_RO(port_destid); + +static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct rio_mport *mport = to_rio_mport(dev); + + if (mport) + return sprintf(buf, "%u\n", mport->sys_size); + else + return -ENODEV; +} +static DEVICE_ATTR_RO(sys_size); + +static struct attribute *rio_mport_attrs[] = { + &dev_attr_port_destid.attr, + &dev_attr_sys_size.attr, + NULL, +}; + +static const struct attribute_group rio_mport_group = { + .attrs = rio_mport_attrs, +}; + +const struct attribute_group *rio_mport_groups[] = { + &rio_mport_group, + NULL, +}; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 2e8a20cac588..a54ba0494dd3 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1884,6 +1884,7 @@ static int rio_get_hdid(int index) int rio_register_mport(struct rio_mport *port) { struct rio_scan_node *scan = NULL; + int res = 0; if (next_portid >= RIO_MAX_MPORTS) { pr_err("RIO: reached specified max number of mports\n"); @@ -1894,6 +1895,16 @@ int rio_register_mport(struct rio_mport *port) port->host_deviceid = rio_get_hdid(port->id); port->nscan = NULL; + dev_set_name(&port->dev, "rapidio%d", port->id); + port->dev.class = &rio_mport_class; + + res = device_register(&port->dev); + if (res) + dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n", + port->id, res); + else + dev_dbg(&port->dev, "RIO: mport%d registered\n", port->id); + mutex_lock(&rio_mport_list_lock); list_add_tail(&port->node, &rio_mports); diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index 5f99d22ad0b0..2d0550e08ea2 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h @@ -50,6 +50,7 @@ extern int rio_mport_scan(int mport_id); /* Structures internal to the RIO core code */ extern const struct attribute_group *rio_dev_groups[]; extern const struct attribute_group *rio_bus_groups[]; +extern const struct attribute_group *rio_mport_groups[]; #define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) #define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) |