[PATCH 12/13] powerpc/fsl_rio: apply changes for RIO spec rev 3
- Remove check for parallel PHY - Set LP-Serial Register Map type Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Benjamin Herrenschmidt Cc: Michael Ellerman Cc: Andre van Herk Cc: Barry Wood Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/fsl_rio.c | 12 ++-- 1 files changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 1958838..ee5b9f1 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -643,19 +643,11 @@ int fsl_rio_setup(struct platform_device *dev) port->ops = ops; port->priv = priv; port->phys_efptr = 0x100; + port->phys_rmap = 1; priv->regs_win = rio_regs_win; - /* Probe the master port phy type */ ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20); - port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL; - if (port->phy_type == RIO_PHY_PARALLEL) { - dev_err(&dev->dev, "RIO: Parallel PHY type, unsupported port type!\n"); - release_resource(&port->iores); - kfree(priv); - kfree(port); - continue; - } - dev_info(&dev->dev, "RapidIO PHY type: Serial\n"); + /* Checking the port training status */ if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) { dev_err(&dev->dev, "Port %d is not ready. " -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 10/13] rapidio: change inbound window size type to u64
Current definition of map_inb() mport operations callback uses u32 type to specify required inbound window (IBW) size. This is limiting factor because existing hardware - tsi721 and fsl_rio, both support IBW size up to 16GB. Changing type of size parameter to u64 to allow IBW size configurations larger than 4GB. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Benjamin Herrenschmidt Cc: Michael Ellerman Cc: Andre van Herk Cc: Barry Wood Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/fsl_rio.c|4 ++-- drivers/rapidio/devices/tsi721.c | 14 +- include/linux/rio.h |2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index f5bf38b9..1958838 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -289,7 +289,7 @@ static void fsl_rio_inbound_mem_init(struct rio_priv *priv) } int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, - u64 rstart, u32 size, u32 flags) + u64 rstart, u64 size, u32 flags) { struct rio_priv *priv = mport->priv; u32 base_size; @@ -298,7 +298,7 @@ int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, u32 riwar; int i; - if ((size & (size - 1)) != 0) + if ((size & (size - 1)) != 0 || size > 0x4UL) return -EINVAL; base_size_log = ilog2(size); diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 8e07cd5..53daf63 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -1090,7 +1090,7 @@ static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv) * from rstart to lstart. */ static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, - u64 rstart, u32 size, u32 flags) + u64 rstart, u64 size, u32 flags) { struct tsi721_device *priv = mport->priv; int i, avail = -1; @@ -1103,6 +1103,10 @@ static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, struct tsi721_ib_win_mapping *map = NULL; int ret = -EBUSY; + /* Max IBW size supported by HW is 16GB */ + if (size > 0x4UL) + return -EINVAL; + if (direct) { /* Calculate minimal acceptable window size and base address */ @@ -1110,15 +1114,15 @@ static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, ibw_start = lstart & ~(ibw_size - 1); tsi_debug(IBW, &priv->pdev->dev, - "Direct (RIO_0x%llx -> PCIe_%pad), size=0x%x, ibw_start = 0x%llx", + "Direct (RIO_0x%llx -> PCIe_%pad), size=0x%llx, ibw_start = 0x%llx", rstart, &lstart, size, ibw_start); while ((lstart + size) > (ibw_start + ibw_size)) { ibw_size *= 2; ibw_start = lstart & ~(ibw_size - 1); - if (ibw_size > 0x8000) { /* Limit max size to 2GB */ + /* Check for crossing IBW max size 16GB */ + if (ibw_size > 0x4UL) return -EBUSY; - } } loc_start = ibw_start; @@ -1129,7 +1133,7 @@ static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, } else { tsi_debug(IBW, &priv->pdev->dev, - "Translated (RIO_0x%llx -> PCIe_%pad), size=0x%x", + "Translated (RIO_0x%llx -> PCIe_%pad), size=0x%llx", rstart, &lstart, size); if (!is_power_of_2(size) || size < 0x1000 || diff --git a/include/linux/rio.h b/include/linux/rio.h index aa23238..f7ec35b 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -425,7 +425,7 @@ struct rio_ops { int (*add_inb_buffer)(struct rio_mport *mport, int mbox, void *buf); void *(*get_inb_message)(struct rio_mport *mport, int mbox); int (*map_inb)(struct rio_mport *mport, dma_addr_t lstart, - u64 rstart, u32 size, u32 flags); + u64 rstart, u64 size, u32 flags); void (*unmap_inb)(struct rio_mport *mport, dma_addr_t lstart); int (*query_mport)(struct rio_mport *mport, struct rio_mport_attr *attr); -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc/fsl_rio: update for port-write interface change
Platform-specific update following changes in port-write handler interface. This is a follow-up patch for [PATCH 22/30] rapidio: add global inbound port write interfaces Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Benjamin Herrenschmidt Cc: Aurelien Jacquiot Cc: Andre van Herk Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/fsl_rio.c |1 + arch/powerpc/sysdev/fsl_rio.h |1 + arch/powerpc/sysdev/fsl_rmu.c | 16 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 385371a..f5bf38b9 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -726,6 +726,7 @@ int fsl_rio_setup(struct platform_device *dev) fsl_rio_inbound_mem_init(priv); dbell->mport[i] = port; + pw->mport[i] = port; if (rio_register_mport(port)) { release_resource(&port->iores); diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h index d53407a..12dd18f 100644 --- a/arch/powerpc/sysdev/fsl_rio.h +++ b/arch/powerpc/sysdev/fsl_rio.h @@ -97,6 +97,7 @@ struct fsl_rio_dbell { }; struct fsl_rio_pw { + struct rio_mport *mport[MAX_PORT_NUM]; struct device *dev; struct rio_pw_regs __iomem *pw_regs; struct rio_port_write_msg port_write_msg; diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c index b48197a..176acfc 100644 --- a/arch/powerpc/sysdev/fsl_rmu.c +++ b/arch/powerpc/sysdev/fsl_rmu.c @@ -481,14 +481,14 @@ pw_done: static void fsl_pw_dpc(struct work_struct *work) { struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work); - u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; + union rio_pw_msg msg_buffer; + int i; /* * Process port-write messages */ - while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)msg_buffer, + while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)&msg_buffer, RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) { - /* Process one message */ #ifdef DEBUG_PW { u32 i; @@ -496,15 +496,19 @@ static void fsl_pw_dpc(struct work_struct *work) for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); i++) { if ((i%4) == 0) pr_debug("\n0x%02x: 0x%08x", i*4, -msg_buffer[i]); +msg_buffer.raw[i]); else - pr_debug(" 0x%08x", msg_buffer[i]); + pr_debug(" 0x%08x", msg_buffer.raw[i]); } pr_debug("\n"); } #endif /* Pass the port-write message to RIO core for processing */ - rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); + for (i = 0; i < MAX_PORT_NUM; i++) { + if (pw->mport[i]) + rio_inb_pwrite_handler(pw->mport[i], + &msg_buffer); + } } } -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 16/30] powerpc/fsl_rio: changes to mport registration
Change mport object initialization/registration sequence to match reworked version of rio_register_mport() in the core code. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Benjamin Herrenschmidt Cc: Aurelien Jacquiot Cc: Andre van Herk Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/sysdev/fsl_rio.c | 18 -- 1 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index c1cd369..385371a 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -606,6 +606,12 @@ int fsl_rio_setup(struct platform_device *dev) if (!port) continue; + rc = rio_mport_initialize(port); + if (rc) { + kfree(port); + continue; + } + i = *port_index - 1; port->index = (unsigned char)i; @@ -682,12 +688,6 @@ int fsl_rio_setup(struct platform_device *dev) dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", port->sys_size ? 65536 : 256); - if (rio_register_mport(port)) { - release_resource(&port->iores); - kfree(priv); - kfree(port); - continue; - } if (port->host_deviceid >= 0) out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); @@ -727,6 +727,12 @@ int fsl_rio_setup(struct platform_device *dev) dbell->mport[i] = port; + if (rio_register_mport(port)) { + release_resource(&port->iores); + kfree(priv); + kfree(port); + continue; + } active_ports++; } -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RESEND PATCH] rapidio: add new RapidIO DMA interface routines
Resending because the original email was rejected by some gateways. Add RapidIO DMA interface routines that directly use reference to the mport device object and/or target device destination ID as parameters. This allows to perform RapidIO DMA transfer requests by modules that do not have an access to the RapidIO device list. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Andre van Herk Cc: Stef van Os Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- drivers/rapidio/rio.c | 66 +++-- include/linux/rio_drv.h | 5 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index a54ba04..d7b87c6 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1509,30 +1509,39 @@ EXPORT_SYMBOL_GPL(rio_route_clr_table); static bool rio_chan_filter(struct dma_chan *chan, void *arg) { - struct rio_dev *rdev = arg; + struct rio_mport *mport = arg; /* Check that DMA device belongs to the right MPORT */ - return (rdev->net->hport == - container_of(chan->device, struct rio_mport, dma)); + return mport == container_of(chan->device, struct rio_mport, dma); } /** - * rio_request_dma - request RapidIO capable DMA channel that supports - * specified target RapidIO device. - * @rdev: RIO device control structure + * rio_request_mport_dma - request RapidIO capable DMA channel associated + * with specified local RapidIO mport device. + * @mport: RIO mport to perform DMA data transfers * * Returns pointer to allocated DMA channel or NULL if failed. */ -struct dma_chan *rio_request_dma(struct rio_dev *rdev) +struct dma_chan *rio_request_mport_dma(struct rio_mport *mport) { dma_cap_mask_t mask; - struct dma_chan *dchan; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - dchan = dma_request_channel(mask, rio_chan_filter, rdev); + return dma_request_channel(mask, rio_chan_filter, mport); +} +EXPORT_SYMBOL_GPL(rio_request_mport_dma); - return dchan; +/** + * rio_request_dma - request RapidIO capable DMA channel that supports + * specified target RapidIO device. + * @rdev: RIO device associated with DMA transfer + * + * Returns pointer to allocated DMA channel or NULL if failed. + */ +struct dma_chan *rio_request_dma(struct rio_dev *rdev) +{ + return rio_request_mport_dma(rdev->net->hport); } EXPORT_SYMBOL_GPL(rio_request_dma); @@ -1547,10 +1556,10 @@ void rio_release_dma(struct dma_chan *dchan) EXPORT_SYMBOL_GPL(rio_release_dma); /** - * rio_dma_prep_slave_sg - RapidIO specific wrapper + * rio_dma_prep_xfer - RapidIO specific wrapper * for device_prep_slave_sg callback defined by DMAENGINE. - * @rdev: RIO device control structure * @dchan: DMA channel to configure + * @destid: target RapidIO device destination ID * @data: RIO specific data descriptor * @direction: DMA data transfer direction (TO or FROM the device) * @flags: dmaengine defined flags @@ -1560,11 +1569,10 @@ EXPORT_SYMBOL_GPL(rio_release_dma); * target RIO device. * Returns pointer to DMA transaction descriptor or NULL if failed. */ -struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, - struct dma_chan *dchan, struct rio_dma_data *data, +struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan, + u16 destid, struct rio_dma_data *data, enum dma_transfer_direction direction, unsigned long flags) { - struct dma_async_tx_descriptor *txd = NULL; struct rio_dma_ext rio_ext; if (dchan->device->device_prep_slave_sg == NULL) { @@ -1572,15 +1580,35 @@ struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, return NULL; } - rio_ext.destid = rdev->destid; + rio_ext.destid = destid; rio_ext.rio_addr_u = data->rio_addr_u; rio_ext.rio_addr = data->rio_addr; rio_ext.wr_type = data->wr_type; - txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, - direction, flags, &rio_ext); + return dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, +direction, flags, &rio_ext); +} +EXPORT_SYMBOL_GPL(rio_dma_prep_xfer); - return txd; +/** + * rio_dma_prep_slave_sg - RapidIO specific wrapper + * for device_prep_slave_sg callback defined by DMAENGINE. + * @rdev: RIO device control structure + * @dchan: DMA channel to configure + * @data: RIO specific data descriptor + * @direction: DMA data transfer direction (TO or FROM the device) + * @flags: dmaengine defined flags + * + * Initializes RapidIO capable DMA channel for the specified data transfer. + * Uses DMA channel private extension to pass information related to remote + * target RIO device. + * Returns pointer to DM
[PATCH] rapidio: rework device hierarchy and introduce mport class of devices
This patch removes an artificial RapidIO bus root device and establishes actual device hierarchy by providing reference to real parent devices. It also introduces device class for RapidIO controller devices (on-chip or an eternal bridge, known as "mport"). Existing implementation was sufficient for SoC-based platforms that have a single RapidIO controller. With introduction of devices using multiple RapidIO controllers and PCIe-to-RapidIO bridges the old scheme is very limiting or does not work at all. The implemented changes allow to properly reference platform's local RapidIO mport devices and provide device details needed for upper layers. This change to RapidIO device hierarchy does not break any known existing kernel or user space interfaces. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Stef van Os Cc: Jerry Jacobs Cc: Arno Tiemersma Cc: Rob Landley Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- Documentation/rapidio/sysfs.txt | 66 + arch/powerpc/sysdev/fsl_rio.c|1 + drivers/net/rionet.c |1 + drivers/rapidio/devices/tsi721.c |1 + drivers/rapidio/rio-driver.c | 22 drivers/rapidio/rio-scan.c |1 + drivers/rapidio/rio-sysfs.c | 40 +++ drivers/rapidio/rio.c| 11 ++ drivers/rapidio/rio.h|1 + include/linux/rio.h |5 ++- 10 files changed, 133 insertions(+), 16 deletions(-) diff --git a/Documentation/rapidio/sysfs.txt b/Documentation/rapidio/sysfs.txt index 271438c..47ce9a5 100644 --- a/Documentation/rapidio/sysfs.txt +++ b/Documentation/rapidio/sysfs.txt @@ -2,8 +2,8 @@ -1. Device Subdirectories - +1. RapidIO Device Subdirectories + For each RapidIO device, the RapidIO subsystem creates files in an individual subdirectory with the following name, /sys/bus/rapidio/devices/. @@ -25,8 +25,8 @@ seen by the enumerating host (destID = 1): NOTE: An enumerating or discovering endpoint does not create a sysfs entry for itself, this is why an endpoint with destID=1 is not shown in the list. -2. Attributes Common for All Devices - +2. Attributes Common for All RapidIO Devices + Each device subdirectory contains the following informational read-only files: @@ -52,16 +52,16 @@ This attribute is similar in behavior to the "config" attribute of PCI devices and provides an access to the RapidIO device registers using standard file read and write operations. -3. Endpoint Device Attributes -- +3. RapidIO Endpoint Device Attributes +- Currently Linux RapidIO subsystem does not create any endpoint specific sysfs attributes. It is possible that RapidIO master port drivers and endpoint device drivers will add their device-specific sysfs attributes but such attributes are outside the scope of this document. -4. Switch Device Attributes +4. RapidIO Switch Device Attributes +--- RapidIO switches have additional attributes in sysfs. RapidIO subsystem supports common and device-specific sysfs attributes for switches. Because switches are @@ -106,3 +106,53 @@ attribute: for that controller always will be 0. To initiate RapidIO enumeration/discovery on all available mports a user must write '-1' (or RIO_MPORT_ANY) into this attribute file. + + +6. RapidIO Bus Controllers/Ports + + +On-chip RapidIO controllers and PCIe-to-RapidIO bridges (referenced as +"Master Port" or "mport") are presented in sysfs as the special class of +devices: "rapidio_port". + +The /sys/class/rapidio_port subdirectory contains individual subdirectories +named as "rapidioN" where N = mport ID registered with RapidIO subsystem. + +NOTE: An mport ID is not a RapidIO destination ID assigned to a given local +mport device. + +Each mport device subdirectory in addition to standard entries contains the +following device-specific attributes: + + port_destid - reports RapidIO destination ID assigned to the given RapidIO + mport device. If value 0x is returned this means that + no valid destination ID have been assigned to the mport (yet). + Normally, before enumeration/discovery have been executed only + fabric enumerating mports have a valid destination ID assigned + to them using "hdid=..." rapidio module parameter. + sys_size - reports RapidIO common transport system size: +
[PATCH] rapidio/tsi721: fix tasklet termination in dma channel release
This patch is a modification of the patch originally proposed by Xiaotian Feng : https://lkml.org/lkml/2012/11/5/413 This new version disables DMA channel interrupts and ensures that the tasklet wil not be scheduled again before calling tasklet_kill(). Unfortunately the updated patch was not released at that time due to planned rework of Tsi721 mport driver to use threaded interrupts (which has yet to happen). Recently the issue was reported again: https://lkml.org/lkml/2014/2/19/762. Description from the original Xiaotian's patch: "Some drivers use tasklet_disable in device remove/release process, tasklet_disable will inc tasklet->count and return. If the tasklet is not handled yet under some softirq pressure, the tasklet will be placed on the tasklet_vec, never have a chance to be excuted. This might lead to a heavy loaded ksoftirqd, wakeup with pending_softirq, but tasklet is disabled. tasklet_kill should be used in this case." This patch is applicable to kernel versions starting from v3.5. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Xiaotian Feng Cc: Thomas Gleixner Cc: Mike Galbraith Cc: --- drivers/rapidio/devices/tsi721.h |1 + drivers/rapidio/devices/tsi721_dma.c | 25 ++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index b4b0d83..7061ac0 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -678,6 +678,7 @@ struct tsi721_bdma_chan { struct list_headfree_list; dma_cookie_tcompleted_cookie; struct tasklet_struct tasklet; + boolactive; }; #endif /* CONFIG_RAPIDIO_DMA_ENGINE */ diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index 502663f..b57f650 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c @@ -206,8 +206,8 @@ void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan) { /* Disable BDMA channel interrupts */ iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE); - - tasklet_schedule(&bdma_chan->tasklet); + if (bdma_chan->active) + tasklet_schedule(&bdma_chan->tasklet); } #ifdef CONFIG_PCI_MSI @@ -562,7 +562,7 @@ static int tsi721_alloc_chan_resources(struct dma_chan *dchan) } #endif /* CONFIG_PCI_MSI */ - tasklet_enable(&bdma_chan->tasklet); + bdma_chan->active = true; tsi721_bdma_interrupt_enable(bdma_chan, 1); return bdma_chan->bd_num - 1; @@ -589,14 +589,25 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan) BUG_ON(!list_empty(&bdma_chan->active_list)); BUG_ON(!list_empty(&bdma_chan->queue)); - tasklet_disable(&bdma_chan->tasklet); + tsi721_bdma_interrupt_enable(bdma_chan, 0); + bdma_chan->active = false; + +#ifdef CONFIG_PCI_MSI + if (priv->flags & TSI721_USING_MSIX) { + synchronize_irq(priv->msix[TSI721_VECT_DMA0_DONE + + bdma_chan->id].vector); + synchronize_irq(priv->msix[TSI721_VECT_DMA0_INT + + bdma_chan->id].vector); + } else +#endif + synchronize_irq(priv->pdev->irq); + + tasklet_kill(&bdma_chan->tasklet); spin_lock_bh(&bdma_chan->lock); list_splice_init(&bdma_chan->free_list, &list); spin_unlock_bh(&bdma_chan->lock); - tsi721_bdma_interrupt_enable(bdma_chan, 0); - #ifdef CONFIG_PCI_MSI if (priv->flags & TSI721_USING_MSIX) { free_irq(priv->msix[TSI721_VECT_DMA0_DONE + @@ -790,6 +801,7 @@ int tsi721_register_dma(struct tsi721_device *priv) bdma_chan->dchan.cookie = 1; bdma_chan->dchan.chan_id = i; bdma_chan->id = i; + bdma_chan->active = false; spin_lock_init(&bdma_chan->lock); @@ -799,7 +811,6 @@ int tsi721_register_dma(struct tsi721_device *priv) tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet, (unsigned long)bdma_chan); - tasklet_disable(&bdma_chan->tasklet); list_add_tail(&bdma_chan->dchan.device_node, &mport->dma.channels); } -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio: add modular rapidio core build into powerpc and mips branches
Allow modular build option for RapidIO subsystem core in MIPS and PowerPC architectural branches. At this moment modular RapidIO subsystem build is enabled only for platforms that use PCI/PCIe based RapidIO controllers (e.g. Tsi721). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Jean Delvare Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: Li Yang Cc: linux-m...@linux-mips.org --- arch/mips/Kconfig|2 +- arch/powerpc/Kconfig |4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 650de39..e6a8a7a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2442,7 +2442,7 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" config RAPIDIO - bool "RapidIO support" + tristate "RapidIO support" depends on PCI default n help diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b44b52c..992531f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -790,7 +790,7 @@ config HAS_RAPIDIO default n config RAPIDIO - bool "RapidIO support" + tristate "RapidIO support" depends on HAS_RAPIDIO || PCI help If you say Y here, the kernel will include drivers and @@ -798,7 +798,7 @@ config RAPIDIO config FSL_RIO bool "Freescale Embedded SRIO Controller support" - depends on RAPIDIO && HAS_RAPIDIO + depends on RAPIDIO = y && HAS_RAPIDIO default "n" ---help--- Include support for RapidIO controller on Freescale embedded -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio: change endpoint device name format
Change endpoint device name format to use a component tag value instead of device destination ID. RapidIO specification defines a component tag to be a unique identifier for devices in a network. RapidIO switches already use component tag as part of their device name and also use it for device identification when processing error management event notifications. Forming an endpoint's device name using its component tag instead of destination ID allows to keep sysfs device directories unchanged in case if a routing process dynamically changes endpoint's destination ID as a result of route optimization. This change should not affect any existing users because a valid device destination ID always should be obtained by reading "destid" attribute and not by parsing device name. This patch also removes switchid member from struct rio_switch because it simply duplicates the component tag and does not have other use than in device name generation. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os --- drivers/rapidio/rio-scan.c |5 ++--- include/linux/rio.h|2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 0e86569..c744800 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -433,7 +433,6 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { rswitch = rdev->rswitch; - rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; rswitch->port_ok = 0; spin_lock_init(&rswitch->lock); rswitch->route_table = kzalloc(sizeof(u8)* @@ -446,7 +445,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rdid++) rswitch->route_table[rdid] = RIO_INVALID_ROUTE; dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, -rswitch->switchid); +rdev->comp_tag & RIO_CTAG_UDEVID); if (do_enum) rio_route_clr_table(rdev, RIO_GLOBAL_TABLE, 0); @@ -459,7 +458,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rio_enable_rx_tx_port(port, 0, destid, hopcount, 0); dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, -rdev->destid); +rdev->comp_tag & RIO_CTAG_UDEVID); } rio_attach_device(rdev); diff --git a/include/linux/rio.h b/include/linux/rio.h index e2faf7b..b71d573 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -92,7 +92,6 @@ union rio_pw_msg; /** * struct rio_switch - RIO switch info * @node: Node in global list of switches - * @switchid: Switch ID that is unique across a network * @route_table: Copy of switch routing table * @port_ok: Status of each port (one bit per port) - OK=1 or UNINIT=0 * @ops: pointer to switch-specific operations @@ -101,7 +100,6 @@ union rio_pw_msg; */ struct rio_switch { struct list_head node; - u16 switchid; u8 *route_table; u32 port_ok; struct rio_switch_ops *ops; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/7] rapidio: convert switch drivers to modules
Rework RapidIO switch drivers to add an option to build them as loadable kernel modules. This patch removes RapidIO-specific vmlinux section and converts switch drivers to be compatible with LDM driver registration method. To simplify registration of device-specific callback routines this patch introduces rio_switch_ops data structure. The sw_sysfs() callback is removed from the list of device-specific operations because under the new structure its functions can be handled by switch driver's probe() and remove() routines. If a specific switch device driver is not loaded the RapidIO subsystem core will use default standard-based operations to configure a switch. Because the current implementation of RapidIO enumeration/discovery method relies on availability of device-specific operations for error management, switch device drivers must be loaded before the RapidIO enumeration/discovery starts. This patch also moves several common routines from enumeration/discovery module into the RapidIO core code to make switch-specific operations accessible to all components of RapidIO subsystem. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- drivers/rapidio/Kconfig |5 + drivers/rapidio/rio-scan.c | 171 + drivers/rapidio/rio-sysfs.c |4 - drivers/rapidio/rio.c | 286 +-- drivers/rapidio/rio.h | 41 + drivers/rapidio/switches/Kconfig| 12 +- drivers/rapidio/switches/idt_gen2.c | 98 ++--- drivers/rapidio/switches/idtcps.c | 86 +-- drivers/rapidio/switches/tsi568.c | 71 - drivers/rapidio/switches/tsi57x.c | 81 -- include/asm-generic/vmlinux.lds.h |7 - include/linux/rio.h | 51 +++ 12 files changed, 568 insertions(+), 345 deletions(-) diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index 5ab0564..3e3be57 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -67,4 +67,9 @@ config RAPIDIO_ENUM_BASIC endchoice +menu "RapidIO Switch drivers" + depends on RAPIDIO + source "drivers/rapidio/switches/Kconfig" + +endmenu diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 4c15dbf..61c913f 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -406,6 +406,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rio_mport_write_config_32(port, destid, hopcount, RIO_COMPONENT_TAG_CSR, next_comptag); rdev->comp_tag = next_comptag++; + rdev->do_enum = true; } else { rio_mport_read_config_32(port, destid, hopcount, RIO_COMPONENT_TAG_CSR, @@ -434,6 +435,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rswitch = rdev->rswitch; rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; rswitch->port_ok = 0; + spin_lock_init(&rswitch->lock); rswitch->route_table = kzalloc(sizeof(u8)* RIO_MAX_ROUTE_ENTRIES(port->sys_size), GFP_KERNEL); @@ -445,11 +447,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rswitch->route_table[rdid] = RIO_INVALID_ROUTE; dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, rswitch->switchid); - rio_switch_init(rdev, do_enum); - if (do_enum && rswitch->clr_table) - rswitch->clr_table(port, destid, hopcount, - RIO_GLOBAL_TABLE); + if (do_enum) + rio_route_clr_table(rdev, RIO_GLOBAL_TABLE, 0); list_add_tail(&rswitch->node, &net->switches); @@ -533,156 +533,6 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) } /** - * rio_lock_device - Acquires host device lock for specified device - * @port: Master port to send transaction - * @destid: Destination ID for device/switch - * @hopcount: Hopcount to reach switch - * @wait_ms: Max wait time in msec (0 = no timeout) - * - * Attepts to acquire host device lock for specified device - * Returns 0 if device lock acquired or EINVAL if timeout expires. - */ -static int -rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms) -{ - u32 result; - int tcnt = 0; - - /* Attempt to acquire device lock */ - rio_mport_write_config_32(port, destid, hopcount, -
[PATCH 2/7] rapidio/rionet: rework driver initialization and removal
Rework probe/remove routines to prevent rionet driver from monopolizing target RapidIO devices. Fix conflict with modular RapidIO switch drivers. Using one of RapidIO messaging channels rionet driver provides a service layer common to all endpoint devices in a system's RapidIO network. These devices may also require their own specific device driver which will be blocked from attaching to the target device by rionet (or block rionet if loaded earlier). To avoid conflict with device-specific drivers, the rionet driver is reworked to be registered as a subsystem interface on the RapidIO bus. The reworked rio_remove_dev() and rionet_exit() routines also include handling of individual rionet peer device removal which was not supported before. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: "David S. Miller" Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- drivers/net/rionet.c | 103 + 1 files changed, 78 insertions(+), 25 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index f433b59..6d1f6ed 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -208,6 +208,17 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (nets[rnet->mport->id].active[destid]) rionet_queue_tx_msg(skb, ndev, nets[rnet->mport->id].active[destid]); + else { + /* +* If the target device was removed from the list of +* active peers but we still have TX packets targeting +* it just report sending a packet to the target +* (without actual packet transfer). +*/ + dev_kfree_skb_any(skb); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + } } spin_unlock_irqrestore(&rnet->tx_lock, flags); @@ -385,24 +396,28 @@ static int rionet_close(struct net_device *ndev) return 0; } -static void rionet_remove(struct rio_dev *rdev) +static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif) { - struct net_device *ndev = rio_get_drvdata(rdev); + struct rio_dev *rdev = to_rio_dev(dev); unsigned char netid = rdev->net->hport->id; struct rionet_peer *peer, *tmp; - unregister_netdev(ndev); - - free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) * - RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); - nets[netid].active = NULL; + if (dev_rionet_capable(rdev)) { + list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { + if (peer->rdev == rdev) { + if (nets[netid].active[rdev->destid]) { + nets[netid].active[rdev->destid] = NULL; + nets[netid].nact--; + } - list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { - list_del(&peer->node); - kfree(peer); + list_del(&peer->node); + kfree(peer); + break; + } + } } - free_netdev(ndev); + return 0; } static void rionet_get_drvinfo(struct net_device *ndev, @@ -503,12 +518,13 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; -static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) +static int rionet_add_dev(struct device *dev, struct subsys_interface *sif) { int rc = -ENODEV; u32 lsrc_ops, ldst_ops; struct rionet_peer *peer; struct net_device *ndev = NULL; + struct rio_dev *rdev = to_rio_dev(dev); unsigned char netid = rdev->net->hport->id; int oldnet; @@ -518,8 +534,9 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) oldnet = test_and_set_bit(netid, net_table); /* -* First time through, make sure local device is rionet -* capable, setup netdev (will be skipped on later probes) +* If first time through this net, make sure local device is rionet +* capable and setup netdev (this step will be skipped in later probes +* on the same net). */ if (!oldnet) { rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, @@ -541,6 +558,12 @@ static int rionet_probe(struct rio_dev *rdev, con
[PATCH 7/7] rapidio: documentation update
Update RapidIO documentation files to reflect modularization changes. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- Documentation/rapidio/rapidio.txt | 98 - Documentation/rapidio/sysfs.txt |1 + 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt index a9c16c9..717f5aa 100644 --- a/Documentation/rapidio/rapidio.txt +++ b/Documentation/rapidio/rapidio.txt @@ -73,28 +73,44 @@ data structure. This structure includes lists of all devices and local master ports that form the same network. It also contains a pointer to the default master port that is used to communicate with devices within the network. +2.5 Device Drivers + +RapidIO device-specific drivers follow Linux Kernel Driver Model and are +intended to support specific RapidIO devices attached to the RapidIO network. + +2.6 Subsystem Interfaces + +RapidIO interconnect specification defines features that may be used to provide +one or more common service layers for all participating RapidIO devices. These +common services may act separately from device-specific drivers or be used by +device-specific drivers. Example of such service provider is the RIONET driver +which implements Ethernet-over-RapidIO interface. Because only one driver can be +registered for a device, all common RapidIO services have to be registered as +subsystem interfaces. This allows to have multiple common services attached to +the same device without blocking attachment of a device-specific driver. + 3. Subsystem Initialization --- In order to initialize the RapidIO subsystem, a platform must initialize and register at least one master port within the RapidIO network. To register mport -within the subsystem controller driver initialization code calls function +within the subsystem controller driver's initialization code calls function rio_register_mport() for each available master port. -RapidIO subsystem uses subsys_initcall() or device_initcall() to perform -controller initialization (depending on controller device type). - After all active master ports are registered with a RapidIO subsystem, an enumeration and/or discovery routine may be called automatically or by user-space command. +RapidIO subsystem can be configured to be built as a statically linked or +modular component of the kernel (see details below). + 4. Enumeration and Discovery 4.1 Overview -RapidIO subsystem configuration options allow users to specify enumeration and +RapidIO subsystem configuration options allow users to build enumeration and discovery methods as statically linked components or loadable modules. An enumeration/discovery method implementation and available input parameters define how any given method can be attached to available RapidIO mports: @@ -115,8 +131,8 @@ several methods to initiate an enumeration and/or discovery process: endpoint waits for enumeration to be completed. If the specified timeout expires the discovery process is terminated without obtaining RapidIO network information. NOTE: a timed out discovery process may be restarted later using - a user-space command as it is described later if the given endpoint was - enumerated successfully. + a user-space command as it is described below (if the given endpoint was + enumerated successfully). (b) Statically linked enumeration and discovery process can be started by a command from user space. This initiation method provides more flexibility @@ -138,15 +154,42 @@ When a network scan process is started it calls an enumeration or discovery routine depending on the configured role of a master port: host or agent. Enumeration is performed by a master port if it is configured as a host port by -assigning a host device ID greater than or equal to zero. A host device ID is -assigned to a master port through the kernel command line parameter "riohdid=", -or can be configured in a platform-specific manner. If the host device ID for -a specific master port is set to -1, the discovery process will be performed -for it. +assigning a host destination ID greater than or equal to zero. The host +destination ID can be assigned to a master port using various methods depending +on RapidIO subsystem build configuration: + + (a) For a statically linked RapidIO subsystem core use command line parameter + "rapidio.hdid=" with a list of destination ID assignments in order of mport + device registration. For example, in a system with two RapidIO controllers + the command line parameter "rapidio.hdid=-1,7" will result in assignment of + the host destination ID=7 to the second RapidIO controller, while the first + one will be assigned destination ID=-1. + + (
[PATCH 3/7] rapidio: update enumerator registration mechanism
Update enumeration/discovery method registration mechanism to allow loading enumeration/discovery methods before all mports are registered. Existing statically linked RapidIO subsystem expects that all available RapidIO mport devices are initialized and registered before the enumeration/discovery method is registered. Switching to loadable mport device drivers creates situation when mport device driver can be loaded after enumeration/discovery method is attached (e.g., loadable mport driver in a system with statically linked RapidIO core and enumerator). This also will happen in a system with hot-pluggable RapidIO controllers. To remove the dependency on the initialization/registration order this patch introduces enumeration/discovery registration mechanism that supports arbitrary registration order of mports and enumerator/discovery methods. The following registration rules are implemented: - only one enumeration/discovery method can be registered for given mport ID (including RIO_MPORT_ANY); - when new enumeration/discovery methods tries to attach to the registered mport device, method with matching mport ID will replace a default method previously registered for given mport (if any); - enumeration/discovery method with target ID=RIO_MPORT_ANY will be attached only to mports that do not have another enumerator attached to them; - when new mport device is registered with RapidIO subsystem, registration routine searches for the enumeration/discovery method with the best matching mport ID; Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- drivers/rapidio/rio-scan.c |1 + drivers/rapidio/rio-sysfs.c | 17 + drivers/rapidio/rio.c | 176 +++ drivers/rapidio/rio.h |3 +- include/linux/rio.h | 15 5 files changed, 164 insertions(+), 48 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 61c913f..0e86569 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -1162,6 +1162,7 @@ bail: } static struct rio_scan rio_scan_ops = { + .owner = THIS_MODULE, .enumerate = rio_enum_mport, .discover = rio_disc_mport, }; diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 864e52f..0c4473e 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -286,7 +286,6 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf, size_t count) { long val; - struct rio_mport *port = NULL; int rc; if (kstrtol(buf, 0, &val) < 0) @@ -300,21 +299,7 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf, if (val < 0 || val >= RIO_MAX_MPORTS) return -EINVAL; - port = rio_find_mport((int)val); - - if (!port) { - pr_debug("RIO: %s: mport_%d not available\n", -__func__, (int)val); - return -EINVAL; - } - - if (!port->nscan) - return -EINVAL; - - if (port->host_deviceid >= 0) - rc = port->nscan->enumerate(port, 0); - else - rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT); + rc = rio_mport_scan((int)val); exit: if (!rc) rc = count; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index b17d521..5eb727c 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -34,6 +34,7 @@ static LIST_HEAD(rio_devices); static DEFINE_SPINLOCK(rio_global_list_lock); static LIST_HEAD(rio_mports); +static LIST_HEAD(rio_scans); static DEFINE_MUTEX(rio_mport_list_lock); static unsigned char next_portid; static DEFINE_SPINLOCK(rio_mmap_lock); @@ -1602,34 +1603,73 @@ found: * rio_register_scan - enumeration/discovery method registration interface * @mport_id: mport device ID for which fabric scan routine has to be set *(RIO_MPORT_ANY = set for all available mports) - * @scan_ops: enumeration/discovery control structure + * @scan_ops: enumeration/discovery operations structure + * + * Registers enumeration/discovery operations with RapidIO subsystem and + * attaches it to the specified mport device (or all available mports + * if RIO_MPORT_ANY is specified). * - * Assigns enumeration or discovery method to the specified mport device (or all - * available mports if RIO_MPORT_ANY is specified). * Returns error if the mport already has an enumerator attached to it. - * In case of RIO_MPORT_ANY ignores ports with valid scan routines and returns - * an error if was unable to find at least one available mport. + * In case of RIO_MPORT_ANY skips mports with valid scan routines (no error). */ int rio_register_scan(int mport_id, struct rio_scan *scan_ops) { str
[PATCH 5/7] rapidio: add modular build option for the subsystem core
Add a configuration option to build RapidIO subsystem core code as a loadable kernel module. Currently this option is available only for x86-based platforms, with the additional patch for PowerPC planned to be provided later. This patch replaces kernel command line parameter "riohdid=" with its module-specific analog "rapidio.hdid=". Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- arch/x86/Kconfig |4 ++-- drivers/rapidio/Makefile |4 +++- drivers/rapidio/rio.c| 27 ++- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fe120da..583ac42 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2246,11 +2246,11 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" config RAPIDIO - bool "RapidIO support" + tristate "RapidIO support" depends on PCI default n help - If you say Y here, the kernel will include drivers and + If enabled this option will include drivers and the core infrastructure code to support RapidIO interconnect devices. source "drivers/rapidio/Kconfig" diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index 3036702..6271ada 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile @@ -1,7 +1,9 @@ # # Makefile for RapidIO interconnect services # -obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o +obj-$(CONFIG_RAPIDIO) += rapidio.o +rapidio-y := rio.o rio-access.o rio-driver.o rio-sysfs.o + obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o obj-$(CONFIG_RAPIDIO) += switches/ diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 2054b62..f4f30af 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -5,7 +5,7 @@ * Copyright 2005 MontaVista Software, Inc. * Matt Porter * - * Copyright 2009 Integrated Device Technology, Inc. + * Copyright 2009 - 2013 Integrated Device Technology, Inc. * Alex Bounine * * This program is free software; you can redistribute it and/or modify it @@ -30,6 +30,17 @@ #include "rio.h" +MODULE_DESCRIPTION("RapidIO Subsystem Core"); +MODULE_AUTHOR("Matt Porter "); +MODULE_AUTHOR("Alexandre Bounine "); +MODULE_LICENSE("GPL"); + +static int hdid[RIO_MAX_MPORTS]; +static int ids_num; +module_param_array(hdid, int, &ids_num, 0); +MODULE_PARM_DESC(hdid, + "Destination ID assignment to local RapidIO controllers"); + static LIST_HEAD(rio_devices); static DEFINE_SPINLOCK(rio_global_list_lock); @@ -1860,24 +1871,14 @@ no_disc: return 0; } -static int hdids[RIO_MAX_MPORTS + 1]; - static int rio_get_hdid(int index) { - if (!hdids[0] || hdids[0] <= index || index >= RIO_MAX_MPORTS) + if (ids_num == 0 || ids_num <= index || index >= RIO_MAX_MPORTS) return -1; - return hdids[index + 1]; + return hdid[index]; } -static int rio_hdid_setup(char *str) -{ - (void)get_options(str, ARRAY_SIZE(hdids), hdids); - return 1; -} - -__setup("riohdid=", rio_hdid_setup); - int rio_register_mport(struct rio_mport *port) { struct rio_scan_node *scan = NULL; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 6/7] rapidio: add udev notification
Add RapidIO-specific modalias generation to enable udev notifications about RapidIO-specific events. The RapidIO modalias string format is shown below: "rapidio:vdavad" Where: v - Device Vendor ID (16 bit), d - Device ID (16 bit), av - Assembly Vendor ID (16 bit), ad - Assembly ID (16 bit), as they are reported in corresponding Capability Registers (CARs) of each RapidIO device. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- drivers/rapidio/rio-driver.c | 18 ++ drivers/rapidio/rio-sysfs.c | 10 ++ include/linux/mod_devicetable.h | 19 +++ include/linux/rio.h | 16 +--- include/linux/rio_ids.h |2 -- scripts/mod/devicetable-offsets.c |6 ++ scripts/mod/file2alias.c | 20 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index a0c8755..3e9b6a7 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -199,6 +199,23 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) out:return 0; } +static int rio_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct rio_dev *rdev; + + if (!dev) + return -ENODEV; + + rdev = to_rio_dev(dev); + if (!rdev) + return -ENODEV; + + if (add_uevent_var(env, "MODALIAS=rapidio:v%04Xd%04Xav%04Xad%04X", + rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did)) + return -ENOMEM; + return 0; +} + struct device rio_bus = { .init_name = "rapidio", }; @@ -210,6 +227,7 @@ struct bus_type rio_bus_type = { .bus_attrs = rio_bus_attrs, .probe = rio_device_probe, .remove = rio_device_remove, + .uevent = rio_uevent, }; /** diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 0c4473e..9331be6 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -84,6 +84,15 @@ static ssize_t lnext_show(struct device *dev, return str - buf; } +static ssize_t modalias_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + + return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n", + rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did); +} + struct device_attribute rio_dev_attrs[] = { __ATTR_RO(did), __ATTR_RO(vid), @@ -93,6 +102,7 @@ struct device_attribute rio_dev_attrs[] = { __ATTR_RO(asm_rev), __ATTR_RO(lprev), __ATTR_RO(destid), + __ATTR_RO(modalias), __ATTR_NULL, }; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b508016..4b0ac9c 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -577,4 +577,23 @@ struct mei_cl_device_id { kernel_ulong_t driver_info; }; +/* RapidIO */ + +#define RIO_ANY_ID 0x + +/** + * struct rio_device_id - RIO device identifier + * @did: RapidIO device ID + * @vid: RapidIO vendor ID + * @asm_did: RapidIO assembly device ID + * @asm_vid: RapidIO assembly vendor ID + * + * Identifies a RapidIO device based on both the device/vendor IDs and + * the assembly device/vendor IDs. + */ +struct rio_device_id { + __u16 did, vid; + __u16 asm_did, asm_vid; +}; + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/rio.h b/include/linux/rio.h index 8d3db1b..e2faf7b 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef CONFIG_RAPIDIO_DMA_ENGINE #include #endif @@ -396,21 +397,6 @@ struct rio_driver { #defineto_rio_driver(drv) container_of(drv,struct rio_driver, driver) -/** - * struct rio_device_id - RIO device identifier - * @did: RIO device ID - * @vid: RIO vendor ID - * @asm_did: RIO assembly device ID - * @asm_vid: RIO assembly vendor ID - * - * Identifies a RIO device based on both the device/vendor IDs and - * the assembly device/vendor IDs. - */ -struct rio_device_id { - u16 did, vid; - u16 asm_did, asm_vid; -}; - union rio_pw_msg { struct { u32 comptag;/* Component Tag CSR */ diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h index b66d13d..2543bc1 100644 --- a/include/linux/rio_ids.h +++ b/include/linux/rio_ids.h @@ -13,8 +13,6 @@ #ifndef LINUX_RIO_IDS_H #define LINUX_RIO_IDS_H -#define RIO_ANY_ID 0x - #define RIO_VID_FREESCALE 0x0002 #define RIO_DID_MPC85600x0003 diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/d
[PATCH 4/7] rapidio/tsi721: convert to modular mport driver
This patch adds an option to build device driver for Tsi721 PCIe-to-SRIO bridge device as a kernel module. Currently this module cannot be unloaded because the existing RapidIO subsystem code does not support dynamic removal of local RapidIO controllers (TODO). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare --- drivers/rapidio/devices/Kconfig |2 +- drivers/rapidio/devices/Makefile |7 +++ drivers/rapidio/devices/tsi721.c |9 - drivers/rapidio/rio.c|1 + 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/rapidio/devices/Kconfig b/drivers/rapidio/devices/Kconfig index 12a9d7f..c4cb087 100644 --- a/drivers/rapidio/devices/Kconfig +++ b/drivers/rapidio/devices/Kconfig @@ -3,7 +3,7 @@ # config RAPIDIO_TSI721 - bool "IDT Tsi721 PCI Express SRIO Controller support" + tristate "IDT Tsi721 PCI Express SRIO Controller support" depends on RAPIDIO && PCIEPORTBUS default "n" ---help--- diff --git a/drivers/rapidio/devices/Makefile b/drivers/rapidio/devices/Makefile index 7b62860..9432c49 100644 --- a/drivers/rapidio/devices/Makefile +++ b/drivers/rapidio/devices/Makefile @@ -2,7 +2,6 @@ # Makefile for RapidIO devices # -obj-$(CONFIG_RAPIDIO_TSI721) += tsi721.o -ifeq ($(CONFIG_RAPIDIO_DMA_ENGINE),y) -obj-$(CONFIG_RAPIDIO_TSI721) += tsi721_dma.o -endif +obj-$(CONFIG_RAPIDIO_TSI721) += tsi721_mport.o +tsi721_mport-y := tsi721.o +tsi721_mport-$(CONFIG_RAPIDIO_DMA_ENGINE) += tsi721_dma.o diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index a8b2c23..ff7cbf2 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2515,9 +2515,8 @@ static int __init tsi721_init(void) return pci_register_driver(&tsi721_driver); } -static void __exit tsi721_exit(void) -{ - pci_unregister_driver(&tsi721_driver); -} - device_initcall(tsi721_init); + +MODULE_DESCRIPTION("IDT Tsi721 PCIExpress-to-SRIO bridge driver"); +MODULE_AUTHOR("Integrated Device Technology, Inc."); +MODULE_LICENSE("GPL"); diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 5eb727c..2054b62 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1911,6 +1911,7 @@ int rio_register_mport(struct rio_mport *port) pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id); return 0; } +EXPORT_SYMBOL_GPL(rio_register_mport); EXPORT_SYMBOL_GPL(rio_local_get_device_id); EXPORT_SYMBOL_GPL(rio_get_device); -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 0/7] rapidio: modularize rapidio subsystem
The following set of patches modifies kernel RapidIO subsystem to enable build and use of its components as loadable kernel modules. Combinations of statically linked and modular components are also supported. For this release full RapidIO subsystem modularization is implemented for x86-based platforms. For PowerPC platforms (mostly MPC85xx) RapidIO core and the mport driver (fsl_rio.c) still have only statically linked build option while other components (enumerator and switch drivers) can be built as kernel modules. This is not a significant limitation for embedded PowerPC platforms because they use on-chip RapidIO controllers. For PowerPC platforms that may use an external PCIe RapidIO controller (e.g. Tsi721) an additional patch will be provided later. This set of patches is based on the current linux-next code tree that contains previously submitted patches for modularized enumeration/discovery method. Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Cc: Stef van Os Cc: Jean Delvare Alexandre Bounine (7): rapidio: convert switch drivers to modules rapidio/rionet: rework driver initialization and removal rapidio: update enumerator registration mechanism rapidio/tsi721: convert to modular mport driver rapidio: add modular build option for the subsystem core rapidio: add udev notification rapidio: documentation update Documentation/rapidio/rapidio.txt | 98 ++- Documentation/rapidio/sysfs.txt |1 + arch/x86/Kconfig|4 +- drivers/net/rionet.c| 103 ++-- drivers/rapidio/Kconfig |5 + drivers/rapidio/Makefile|4 +- drivers/rapidio/devices/Kconfig |2 +- drivers/rapidio/devices/Makefile|7 +- drivers/rapidio/devices/tsi721.c|9 +- drivers/rapidio/rio-driver.c| 18 ++ drivers/rapidio/rio-scan.c | 172 + drivers/rapidio/rio-sysfs.c | 31 +-- drivers/rapidio/rio.c | 490 --- drivers/rapidio/rio.h | 44 +--- drivers/rapidio/switches/Kconfig| 12 +- drivers/rapidio/switches/idt_gen2.c | 98 ++-- drivers/rapidio/switches/idtcps.c | 86 +-- drivers/rapidio/switches/tsi568.c | 71 +- drivers/rapidio/switches/tsi57x.c | 81 +- include/asm-generic/vmlinux.lds.h |7 - include/linux/mod_devicetable.h | 19 ++ include/linux/rio.h | 82 +++--- include/linux/rio_ids.h |2 - scripts/mod/devicetable-offsets.c |6 + scripts/mod/file2alias.c| 20 ++ 25 files changed, 998 insertions(+), 474 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/switches: remove tsi500 driver
Remove the driver for Tsi500 Parallel RapidIO switch because this device is not available for several years. Since the first introduction of Tsi500, the parallel RapidIO interface was replaced by the serial RapidIO (sRIO) and therefore there is no value in keeping this driver. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala --- drivers/rapidio/switches/Kconfig |7 --- drivers/rapidio/switches/Makefile |1 - drivers/rapidio/switches/tsi500.c | 78 - 3 files changed, 0 insertions(+), 86 deletions(-) delete mode 100644 drivers/rapidio/switches/tsi500.c diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig index f47fee5..62d4a06 100644 --- a/drivers/rapidio/switches/Kconfig +++ b/drivers/rapidio/switches/Kconfig @@ -26,10 +26,3 @@ config RAPIDIO_CPS_GEN2 default n ---help--- Includes support for ITD CPS Gen.2 serial RapidIO switches. - -config RAPIDIO_TSI500 - bool "Tsi500 Parallel RapidIO switch support" - depends on RAPIDIO - default n - ---help--- - Includes support for IDT Tsi500 parallel RapidIO switch. diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index c4d3acc..051cc6b 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile @@ -5,5 +5,4 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o -obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c deleted file mode 100644 index 914eddd..000 --- a/drivers/rapidio/switches/tsi500.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * RapidIO Tsi500 switch support - * - * Copyright 2009-2010 Integrated Device Technology, Inc. - * Alexandre Bounine - * - Modified switch operations initialization. - * - * Copyright 2005 MontaVista Software, Inc. - * Matt Porter - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include "../rio.h" - -static int -tsi500_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 route_port) -{ - int i; - u32 offset = 0x1 + 0xa00 + ((route_destid / 2)&~0x3); - u32 result; - - if (table == 0xff) { - rio_mport_read_config_32(mport, destid, hopcount, offset, &result); - result &= ~(0xf << (4*(route_destid & 0x7))); - for (i=0;i<4;i++) - rio_mport_write_config_32(mport, destid, hopcount, offset + (0x2*i), result | (route_port << (4*(route_destid & 0x7; - } - else { - rio_mport_read_config_32(mport, destid, hopcount, offset + (0x2*table), &result); - result &= ~(0xf << (4*(route_destid & 0x7))); - rio_mport_write_config_32(mport, destid, hopcount, offset + (0x2*table), result | (route_port << (4*(route_destid & 0x7; - } - - return 0; -} - -static int -tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 *route_port) -{ - int ret = 0; - u32 offset = 0x1 + 0xa00 + ((route_destid / 2)&~0x3); - u32 result; - - if (table == 0xff) - rio_mport_read_config_32(mport, destid, hopcount, offset, &result); - else - rio_mport_read_config_32(mport, destid, hopcount, offset + (0x2*table), &result); - - result &= 0xf << (4*(route_destid & 0x7)); - *route_port = result >> (4*(route_destid & 0x7)); - if (*route_port > 3) - ret = -1; - - return ret; -} - -static int tsi500_switch_init(struct rio_dev *rdev, int do_enum) -{ - pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); - rdev->rswitch->add_entry = tsi500_route_add_entry; - rdev->rswitch->get_entry = tsi500_route_get_entry; - rdev->rswitch->clr_table = NULL; - rdev->rswitch->set_domain = NULL; - rdev->rswitch->get_domain = NULL; - rdev->rswitch->em_init = NULL; - rdev->rswitch->em_handle = NULL; - - return 0; -} - -DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_switch_init); -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: fix bug in MSI interrupt handling
Fix bug in MSI interrupt handling which causes loss of event notifications. Typical indication of lost MSI interrupts are stalled message and doorbell transfers between RapidIO endpoints. To avoid loss of MSI interrupts all interrupts from the device must be disabled on entering the interrupt handler routine and re-enabled when exiting it. Re-enabling device interrupts will trigger new MSI message(s) if Tsi721 registered new events since entering interrupt handler routine. This patch is applicable to kernel versions starting from v3.2. Signed-off-by: Alexandre Bounine Cc: Matt Porter --- drivers/rapidio/devices/tsi721.c | 12 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 6faba40..a8b2c23 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -471,6 +471,10 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) u32 intval; u32 ch_inte; + /* For MSI mode disable all device-level interrupts */ + if (priv->flags & TSI721_USING_MSI) + iowrite32(0, priv->regs + TSI721_DEV_INTE); + dev_int = ioread32(priv->regs + TSI721_DEV_INT); if (!dev_int) return IRQ_NONE; @@ -560,6 +564,14 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) } } #endif + + /* For MSI mode re-enable device-level interrupts */ + if (priv->flags & TSI721_USING_MSI) { + dev_int = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO | + TSI721_DEV_INT_SMSG_CH | TSI721_DEV_INT_BDMA_CH; + iowrite32(dev_int, priv->regs + TSI721_DEV_INTE); + } + return IRQ_HANDLED; } -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 1/3] rapidio: make enumeration/discovery configurable
Rework to implement RapidIO enumeration/discovery method selection combined with ability to use enumeration/discovery as a kernel module. This patch adds ability to introduce new RapidIO enumeration/discovery methods using kernel configuration options. Configuration option mechanism allows to select statically linked or modular enumeration/discovery method from the list of existing methods or use external modules. If a modular enumeration/discovery is selected each RapidIO mport device can have its own method attached to it. The existing enumeration/discovery code was updated to be used as statically linked or modular method. This configuration option is named "Basic enumeration/discovery" method. Several common routines have been moved from rio-scan.c to make them available to other enumeration methods and reduce number of exported symbols. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- drivers/rapidio/Kconfig | 20 drivers/rapidio/Makefile |3 +- drivers/rapidio/rio-driver.c |7 ++ drivers/rapidio/rio-scan.c | 166 drivers/rapidio/rio.c| 222 -- drivers/rapidio/rio.h| 11 ++- include/linux/rio.h | 13 +++- include/linux/rio_drv.h |1 + 8 files changed, 304 insertions(+), 139 deletions(-) diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index 6194d35..5ab0564 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -47,4 +47,24 @@ config RAPIDIO_DEBUG If you are unsure about this, say N here. +choice + prompt "Enumeration method" + depends on RAPIDIO + default RAPIDIO_ENUM_BASIC + help + There are different enumeration and discovery mechanisms offered + for RapidIO subsystem. You may select single built-in method or + or any number of methods to be built as modules. + Selecting a built-in method disables use of loadable methods. + + If unsure, select Basic built-in. + +config RAPIDIO_ENUM_BASIC + tristate "Basic" + help + This option includes basic RapidIO fabric enumeration and discovery + mechanism similar to one described in RapidIO specification Annex 1. + +endchoice + source "drivers/rapidio/switches/Kconfig" diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index ec3fb81..3036702 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile @@ -1,7 +1,8 @@ # # Makefile for RapidIO interconnect services # -obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o +obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o +obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o obj-$(CONFIG_RAPIDIO) += switches/ obj-$(CONFIG_RAPIDIO) += devices/ diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 0f4a53b..55850bb 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -164,6 +164,13 @@ void rio_unregister_driver(struct rio_driver *rdrv) driver_unregister(&rdrv->driver); } +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); + /** * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure * @dev: the standard device structure to match against diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index a965acd..7bdc674 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -37,12 +37,8 @@ #include "rio.h" -LIST_HEAD(rio_devices); - static void rio_init_em(struct rio_dev *rdev); -DEFINE_SPINLOCK(rio_global_list_lock); - static int next_destid = 0; static int next_comptag = 1; @@ -327,127 +323,6 @@ static int rio_is_switch(struct rio_dev *rdev) } /** - * rio_switch_init - Sets switch operations for a particular vendor switch - * @rdev: RIO device - * @do_enum: Enumeration/Discovery mode flag - * - * Searches the RIO switch ops table for known switch types. If the vid - * and did match a switch table entry, then call switch initialization - * routine to setup switch-specific routines. - */ -static void rio_switch_init(struct rio_dev *rdev, int do_enum) -{ - struct rio_switch_ops *cur = __start_rio_switch_ops; - struct rio_switch_ops *end = __end_rio_switch_ops; - - while (cur < end) { - if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { - pr_debug("RIO: calling init routine for %s\n", -rio_name(rdev)); - cur->init_hook(rdev, do_enum); - break; - } - cur++; - } - - if ((
[PATCH v2 2/3] rapidio: add enumeration/discovery start from user space
Add RapidIO enumeration/discovery start from user space. User space start allows to defer RapidIO fabric scan until the moment when all participating endpoints are initialized avoiding mandatory synchronized start of all endpoints (which may be challenging in systems with large number of RapidIO endpoints). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- drivers/rapidio/rio-driver.c |1 + drivers/rapidio/rio-scan.c | 24 +++-- drivers/rapidio/rio-sysfs.c | 45 ++ drivers/rapidio/rio.c| 28 - drivers/rapidio/rio.h|2 + include/linux/rio.h |9 ++- 6 files changed, 102 insertions(+), 7 deletions(-) diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 55850bb..a0c8755 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -207,6 +207,7 @@ struct bus_type rio_bus_type = { .name = "rapidio", .match = rio_match_bus, .dev_attrs = rio_dev_attrs, + .bus_attrs = rio_bus_attrs, .probe = rio_device_probe, .remove = rio_device_remove, }; diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 7bdc674..4c15dbf 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -1134,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable) /** * rio_enum_mport- Start enumeration through a master port * @mport: Master port to send transactions + * @flags: Enumeration control flags * * Starts the enumeration process. If somebody has enumerated our * master port device, then give up. If not and we have an active * link, then start recursive peer enumeration. Returns %0 if * enumeration succeeds or %-EBUSY if enumeration fails. */ -int rio_enum_mport(struct rio_mport *mport) +int rio_enum_mport(struct rio_mport *mport, u32 flags) { struct rio_net *net = NULL; int rc = 0; printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, mport->name); + + /* +* To avoid multiple start requests (repeat enumeration is not supported +* by this method) check if enumeration/discovery was performed for this +* mport: if mport was added into the list of mports for a net exit +* with error. +*/ + if (mport->nnode.next || mport->nnode.prev) + return -EBUSY; + /* If somebody else enumerated our master port device, bail. */ if (rio_enum_host(mport) < 0) { printk(KERN_INFO @@ -1236,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net) /** * rio_disc_mport- Start discovery through a master port * @mport: Master port to send transactions + * @flags: discovery control flags * * Starts the discovery process. If we have an active link, - * then wait for the signal that enumeration is complete. + * then wait for the signal that enumeration is complete (if wait + * is allowed). * When enumeration completion is signaled, start recursive * peer discovery. Returns %0 if discovery succeeds or %-EBUSY * on failure. */ -int rio_disc_mport(struct rio_mport *mport) +int rio_disc_mport(struct rio_mport *mport, u32 flags) { struct rio_net *net = NULL; unsigned long to_end; @@ -1253,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport) /* If master port has an active link, allocate net and discover peers */ if (rio_mport_is_active(mport)) { + if (rio_enum_complete(mport)) + goto enum_done; + else if (flags & RIO_SCAN_ENUM_NO_WAIT) + return -EAGAIN; + pr_debug("RIO: wait for enumeration to complete...\n"); to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 4dbe360..66d4acd 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -285,3 +285,48 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev) rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); } } + +static ssize_t bus_scan_store(struct bus_type *bus, const char *buf, + size_t count) +{ + long val; + struct rio_mport *port = NULL; + int rc; + + if (kstrtol(buf, 0, &val) < 0) + return -EINVAL; + + if (val == RIO_MPORT_ANY) { + rc = rio_init_mports(); + goto exit; + } + + if (val < 0 || val >= RIO_MAX_MPORTS) + return -EINVAL; + + port = rio_find_mport((int)val); + + if (!port) { + pr_debug("RIO: %s: mport_%d not available\n", +__func__, (
[PATCH v2 3/3] rapidio: documentation update for enumeration changes
Update RapidIO documentation to reflect changes made to enumeration/discovery build configuration and user space triggering mechanism. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- Documentation/rapidio/rapidio.txt | 128 +--- Documentation/rapidio/sysfs.txt | 17 + 2 files changed, 134 insertions(+), 11 deletions(-) diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt index c75694b..a9c16c9 100644 --- a/Documentation/rapidio/rapidio.txt +++ b/Documentation/rapidio/rapidio.txt @@ -79,20 +79,63 @@ master port that is used to communicate with devices within the network. In order to initialize the RapidIO subsystem, a platform must initialize and register at least one master port within the RapidIO network. To register mport within the subsystem controller driver initialization code calls function -rio_register_mport() for each available master port. After all active master -ports are registered with a RapidIO subsystem, the rio_init_mports() routine -is called to perform enumeration and discovery. +rio_register_mport() for each available master port. -In the current PowerPC-based implementation a subsys_initcall() is specified to -perform controller initialization and mport registration. At the end it directly -calls rio_init_mports() to execute RapidIO enumeration and discovery. +RapidIO subsystem uses subsys_initcall() or device_initcall() to perform +controller initialization (depending on controller device type). + +After all active master ports are registered with a RapidIO subsystem, +an enumeration and/or discovery routine may be called automatically or +by user-space command. 4. Enumeration and Discovery -When rio_init_mports() is called it scans a list of registered master ports and -calls an enumeration or discovery routine depending on the configured role of a -master port: host or agent. +4.1 Overview + + +RapidIO subsystem configuration options allow users to specify enumeration and +discovery methods as statically linked components or loadable modules. +An enumeration/discovery method implementation and available input parameters +define how any given method can be attached to available RapidIO mports: +simply to all available mports OR individually to the specified mport device. + +Depending on selected enumeration/discovery build configuration, there are +several methods to initiate an enumeration and/or discovery process: + + (a) Statically linked enumeration and discovery process can be started + automatically during kernel initialization time using corresponding module + parameters. This was the original method used since introduction of RapidIO + subsystem. Now this method relies on enumerator module parameter which is + 'rio-scan.scan' for existing basic enumeration/discovery method. + When automatic start of enumeration/discovery is used a user has to ensure + that all discovering endpoints are started before the enumerating endpoint + and are waiting for enumeration to be completed. + Configuration option CONFIG_RAPIDIO_DISC_TIMEOUT defines time that discovering + endpoint waits for enumeration to be completed. If the specified timeout + expires the discovery process is terminated without obtaining RapidIO network + information. NOTE: a timed out discovery process may be restarted later using + a user-space command as it is described later if the given endpoint was + enumerated successfully. + + (b) Statically linked enumeration and discovery process can be started by + a command from user space. This initiation method provides more flexibility + for a system startup compared to the option (a) above. After all participating + endpoints have been successfully booted, an enumeration process shall be + started first by issuing a user-space command, after an enumeration is + completed a discovery process can be started on all remaining endpoints. + + (c) Modular enumeration and discovery process can be started by a command from + user space. After an enumeration/discovery module is loaded, a network scan + process can be started by issuing a user-space command. + Similar to the option (b) above, an enumerator has to be started first. + + (d) Modular enumeration and discovery process can be started by a module + initialization routine. In this case an enumerating module shall be loaded + first. + +When a network scan process is started it calls an enumeration or discovery +routine depending on the configured role of a master port: host or agent. Enumeration is performed by a master port if it is configured as a host port by assigning a host device ID greater than or equal to zero. A host device ID is @@ -104,8 +147,58 @@ for it. The enumeration and discovery routines use RapidIO maintenance transactions to access the configuration space
[PATCH v2 0/3] rapidio: changes to enumeration/discovery
Systems that use RapidIO fabric may need to implement their own enumeration and discovery methods which are better suitable for needs of a target application. The following set of patches is intended to simplify process of introduction of new RapidIO fabric enumeration/discovery methods. The first patch offers ability to add new RapidIO enumeration/discovery methods using kernel configuration options. This new configuration option mechanism allows to select statically linked or modular enumeration/discovery method(s) from the list of existing methods or use external module(s). This patch also updates the currently existing enumeration/discovery code to be used as a statically linked or modular method. The corresponding configuration option is named "Basic enumeration/discovery" method. This is the only one configuration option available today but new methods are expected to be introduced after adoption of provided patches. The second patch address a long time complaint of RapidIO subsystem users regarding fabric enumeration/discovery start sequence. Existing implementation offers only a boot-time enumeration/discovery start which requires synchronized boot of all endpoints in RapidIO network. While it works for small closed configurations with limited number of endpoints, using this approach in systems with large number of endpoints is quite challenging. To eliminate requirement for synchronized start the second patch introduces RapidIO enumeration/discovery start from user space. For compatibility with the existing RapidIO subsystem implementation, automatic boot time enumeration/discovery start can be configured in by specifying "rio-scan.scan=1" command line parameter if statically linked basic enumeration method is selected. Changes since v1: (1) Addressed comments made by Andrew Morton for v1: - reworked enumeration/discovery module initialization - added locking for list of mport devices - made mport list static - removed CONFIG_RAPIDIO_ENUM_AUTO option: not needed with new module initialization - added default value for "Enumeration method" choice in Kconfig Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Alexandre Bounine (3): rapidio: make enumeration/discovery configurable rapidio: add enumeration/discovery start from user space rapidio: documentation update for enumeration changes Documentation/rapidio/rapidio.txt | 128 ++-- Documentation/rapidio/sysfs.txt | 17 +++ drivers/rapidio/Kconfig | 20 +++ drivers/rapidio/Makefile |3 +- drivers/rapidio/rio-driver.c |8 ++ drivers/rapidio/rio-scan.c| 190 +--- drivers/rapidio/rio-sysfs.c | 45 +++ drivers/rapidio/rio.c | 246 +++- drivers/rapidio/rio.h | 13 ++- include/linux/rio.h | 18 +++- include/linux/rio_drv.h |1 + 11 files changed, 536 insertions(+), 153 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/3] rapidio: make enumeration/discovery configurable
Rework to implement RapidIO enumeration/discovery method selection combined with ability to use enumeration/discovery as a kernel module. This patch adds ability to introduce new RapidIO enumeration/discovery methods using kernel configuration options or loadable modules. Configuration option mechanism allows to select built-in or modular enumeration/discovery method from the list of existing methods or use external modules. If a modular enumeration/discovery is selected each RapidIO mport device can have its own method attached to it. The currently existing enumeration/discovery code was updated to be used as built-in or modular method. This configuration option is named "Basic enumeration/discovery" method. Several common routines have been moved from rio-scan.c to make them available to other enumeration methods and reduce number of exported symbols. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- drivers/rapidio/Kconfig | 19 drivers/rapidio/Makefile |3 +- drivers/rapidio/rio-driver.c |7 ++ drivers/rapidio/rio-scan.c | 171 +- drivers/rapidio/rio.c| 212 +- drivers/rapidio/rio.h| 10 ++- include/linux/rio.h | 12 +++ include/linux/rio_drv.h |1 + 8 files changed, 300 insertions(+), 135 deletions(-) diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index 6194d35..e392cab 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -47,4 +47,23 @@ config RAPIDIO_DEBUG If you are unsure about this, say N here. +choice + prompt "Enumeration method" + depends on RAPIDIO + help + There are different enumeration and discovery mechanisms offered + for RapidIO subsystem. You may select single built-in method or + or any number of methods to be built as modules. + Selecting a built-in method disables use of loadable methods. + + If unsure, select Basic built-in. + +config RAPIDIO_ENUM_BASIC + tristate "Basic" + help + This option includes basic RapidIO fabric enumeration and discovery + mechanism similar to one described in RapidIO specification Annex 1. + +endchoice + source "drivers/rapidio/switches/Kconfig" diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index ec3fb81..3036702 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile @@ -1,7 +1,8 @@ # # Makefile for RapidIO interconnect services # -obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o +obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o +obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o obj-$(CONFIG_RAPIDIO) += switches/ obj-$(CONFIG_RAPIDIO) += devices/ diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 0f4a53b..55850bb 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -164,6 +164,13 @@ void rio_unregister_driver(struct rio_driver *rdrv) driver_unregister(&rdrv->driver); } +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); + /** * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure * @dev: the standard device structure to match against diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index a965acd..33fc332 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -37,12 +37,8 @@ #include "rio.h" -LIST_HEAD(rio_devices); - static void rio_init_em(struct rio_dev *rdev); -DEFINE_SPINLOCK(rio_global_list_lock); - static int next_destid = 0; static int next_comptag = 1; @@ -327,127 +323,6 @@ static int rio_is_switch(struct rio_dev *rdev) } /** - * rio_switch_init - Sets switch operations for a particular vendor switch - * @rdev: RIO device - * @do_enum: Enumeration/Discovery mode flag - * - * Searches the RIO switch ops table for known switch types. If the vid - * and did match a switch table entry, then call switch initialization - * routine to setup switch-specific routines. - */ -static void rio_switch_init(struct rio_dev *rdev, int do_enum) -{ - struct rio_switch_ops *cur = __start_rio_switch_ops; - struct rio_switch_ops *end = __end_rio_switch_ops; - - while (cur < end) { - if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { - pr_debug("RIO: calling init routine for %s\n", -rio_name(rdev)); - cur->init_hook(rdev, do_enum); - break; - } - cur++; - } - - if ((cu
[PATCH 3/3] rapidio: documentation update for enumeration changes
Update RapidIO documentation to reflect changes made to enumeration/discovery build configuration and user space triggering mechanism. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- Documentation/rapidio/rapidio.txt | 137 ++--- Documentation/rapidio/sysfs.txt | 17 + 2 files changed, 143 insertions(+), 11 deletions(-) diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt index c75694b..d97576f 100644 --- a/Documentation/rapidio/rapidio.txt +++ b/Documentation/rapidio/rapidio.txt @@ -79,20 +79,64 @@ master port that is used to communicate with devices within the network. In order to initialize the RapidIO subsystem, a platform must initialize and register at least one master port within the RapidIO network. To register mport within the subsystem controller driver initialization code calls function -rio_register_mport() for each available master port. After all active master -ports are registered with a RapidIO subsystem, the rio_init_mports() routine -is called to perform enumeration and discovery. +rio_register_mport() for each available master port. -In the current PowerPC-based implementation a subsys_initcall() is specified to -perform controller initialization and mport registration. At the end it directly -calls rio_init_mports() to execute RapidIO enumeration and discovery. +RapidIO subsystem uses subsys_initcall() or device_initcall() to perform +controller initialization (depending on controller device type). + +After all active master ports are registered with a RapidIO subsystem, +an enumeration and/or discovery routine may be called automatically or +by user-space command. 4. Enumeration and Discovery -When rio_init_mports() is called it scans a list of registered master ports and -calls an enumeration or discovery routine depending on the configured role of a -master port: host or agent. +4.1 Overview + + +RapidIO subsystem configuration options allow users to specify enumeration and +discovery methods as built-in components or loadable modules. +For built-in options only one method can be selected for all mports in a system. +Selecting a modular build option for enumeration/discovery allows to use +different enumerators attached to available mport device individually. + +Depending on selected enumeration/discovery build configuration, there are +several methods to initiate enumeration and/or discovery process: + + (a) Built-in enumeration and discovery process can be started automatically + during kernel initialization time. This is the original method used since + introduction of RapidIO subsystem. This method relieson kernel initcall that + calls rio_init_mports() routine after all available mports have been + registered. When automatic start of enumeration/discovery is used a user has + to ensure that all discovering endpoints are started before the enumerating + endpoint and are waiting for enumeration to be completed. + Configuration option CONFIG_RAPIDIO_DISC_TIMEOUT defines time that discovering + endpoint waits for enumeration to be completed. If the specified timeout + expires the discovery process is terminated without obtaining RapidIO network + information. NOTE: a timed out discovery process may be restarted later using + a user-space command as it is described later if the given endpoint was + enumerated successfully. + + (b) Built-in enumeration and discovery process can be started by a command + from user space. This initiation method provides more freedom for system + startup compared to the option (a) above. After all participating endpoints + have been successfully booted, an enumeration process shall be started first + by issuing a user-space command, as soon as enumeration is completed + a discovery process can be started on all remaining endpoints. + Configuration option CONFIG_RAPIDIO_ENUM_AUTO defines which method will be + used to start a built-in enumeration and discovery process. + + (c) Modular enumeration and discovery process can be started by a command from + user space. After an enumeration/discovery module is loaded, a network scan + process can be started by issuing a user-space command. + Similar to the option (b) above, an enumerator has to be started first. + + (d) Modular enumeration and discovery process can be started by a module + initialization routine. As in the cases above an enumerating module shall be + loaded first. + +When a network scan process is started it calls an enumeration or discovery +routine depending on the configured role of a master port: host or agent. Enumeration is performed by a master port if it is configured as a host port by assigning a host device ID greater than or equal to zero. A host device ID is @@ -104,8 +148,57 @@ for it. The enumeration and discovery routines use RapidIO
[PATCH 2/3] rapidio: add enumeration/discovery start from user space
Add RapidIO enumeration/discovery start from user space. User space start allows to defer RapidIO fabric scan until the moment when all participating endpoints are initialized avoiding mandatory synchronized start of all endpoints (which may be challenging in systems with large number of RapidIO endpoints). For compatibility with the existing RapidIO subsystem implementation, automatic boot time enumeration/discovery start can be configured in by selecting CONFIG_RAPIDIO_ENUM_AUTO option. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen --- drivers/rapidio/Kconfig |9 drivers/rapidio/rio-driver.c |1 + drivers/rapidio/rio-scan.c | 24 +++-- drivers/rapidio/rio-sysfs.c | 45 ++ drivers/rapidio/rio.c| 26 ++- drivers/rapidio/rio.h|2 + include/linux/rio.h |9 ++- 7 files changed, 109 insertions(+), 7 deletions(-) diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index e392cab..8b7f92d 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -66,4 +66,13 @@ config RAPIDIO_ENUM_BASIC endchoice +config RAPIDIO_ENUM_AUTO + bool "Automatic RapidIO enumeration/discovery start" + depends on RAPIDIO && RAPIDIO_ENUM_BASIC = y + help + Say Y if you want RapidIO subsystem to start fabric enumeration and + discovery automatically during kernel initialization time. + If you are unsure, say N here. You will be able to start RapidIO + fabric enumeration or discovery later by a user request. + source "drivers/rapidio/switches/Kconfig" diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 55850bb..a0c8755 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -207,6 +207,7 @@ struct bus_type rio_bus_type = { .name = "rapidio", .match = rio_match_bus, .dev_attrs = rio_dev_attrs, + .bus_attrs = rio_bus_attrs, .probe = rio_device_probe, .remove = rio_device_remove, }; diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 33fc332..3e371b1 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -1134,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable) /** * rio_enum_mport- Start enumeration through a master port * @mport: Master port to send transactions + * @flags: Enumeration control flags * * Starts the enumeration process. If somebody has enumerated our * master port device, then give up. If not and we have an active * link, then start recursive peer enumeration. Returns %0 if * enumeration succeeds or %-EBUSY if enumeration fails. */ -int rio_enum_mport(struct rio_mport *mport) +int rio_enum_mport(struct rio_mport *mport, u32 flags) { struct rio_net *net = NULL; int rc = 0; printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, mport->name); + + /* +* To avoid multiple start requests (repeat enumeration is not supported +* by this method) check if enumeration/discovery was performed for this +* mport: if mport was added into the list of mports for a net exit +* with error. +*/ + if (mport->nnode.next || mport->nnode.prev) + return -EBUSY; + /* If somebody else enumerated our master port device, bail. */ if (rio_enum_host(mport) < 0) { printk(KERN_INFO @@ -1236,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net) /** * rio_disc_mport- Start discovery through a master port * @mport: Master port to send transactions + * @flags: discovery control flags * * Starts the discovery process. If we have an active link, - * then wait for the signal that enumeration is complete. + * then wait for the signal that enumeration is complete (if wait + * is allowed). * When enumeration completion is signaled, start recursive * peer discovery. Returns %0 if discovery succeeds or %-EBUSY * on failure. */ -int rio_disc_mport(struct rio_mport *mport) +int rio_disc_mport(struct rio_mport *mport, u32 flags) { struct rio_net *net = NULL; unsigned long to_end; @@ -1253,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport) /* If master port has an active link, allocate net and discover peers */ if (rio_mport_is_active(mport)) { + if (rio_enum_complete(mport)) + goto enum_done; + else if (flags & RIO_SCAN_ENUM_NO_WAIT) + return -EAGAIN; + pr_debug("RIO: wait for enumeration to complete...\n"); to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; diff --git a/drivers/rapidio/
[PATCH 0/3] rapidio: changes to enumeration/discovery
Systems that use RapidIO fabric may need to implement their own enumeration and discovery methods which are better suitable for needs of a target application. The following set of patches is intended to simplify process of introduction of new RapidIO fabric enumeration/discovery methods. The first patch offers ability to add new RapidIO enumeration/discovery methods using kernel configuration options or loadable modules. The new configuration option mechanism allows to select built-in or modular enumeration/discovery method from the list of existing methods or use external module(s). This patch also updates the currently existing enumeration/discovery code to be used as built-in or modular method. The corresponding configuration option is named "Basic enumeration/discovery" method. This is the only one built-in configuration option available today but new methods are expected to be introduced after adoption of provided patches. The second patch address a long time complaint of RapidIO subsystem users regarding fabric enumeration/discovery start sequence. Existing implementation offers only a boot-time enumeration/discovery start which requires synchronized boot of all endpoints in RapidIO network. While it works for small closed configurations with limited number of endpoints, using this approach in systems with large number of endpoints is quite challenging. To eliminate requirement for synchronized start the second patch introduces RapidIO enumeration/discovery start from user space. For compatibility with the existing RapidIO subsystem implementation, automatic boot time enumeration/discovery start can be configured in by selecting CONFIG_RAPIDIO_ENUM_AUTO option. Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Andre van Herk Cc: Micha Nelissen Alexandre Bounine (3): rapidio: make enumeration/discovery configurable rapidio: add enumeration/discovery start from user space rapidio: documentation update for enumeration changes Documentation/rapidio/rapidio.txt | 137 -- Documentation/rapidio/sysfs.txt | 17 +++ drivers/rapidio/Kconfig | 28 + drivers/rapidio/Makefile |3 +- drivers/rapidio/rio-driver.c |8 ++ drivers/rapidio/rio-scan.c| 195 ++ drivers/rapidio/rio-sysfs.c | 45 +++ drivers/rapidio/rio.c | 234 - drivers/rapidio/rio.h | 12 ++- include/linux/rio.h | 17 +++ include/linux/rio_drv.h |1 + 11 files changed, 548 insertions(+), 149 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/3] rapidio: update asynchronous discovery initialization
Update discovery process initialization based on Andrew Morton's comments: https://lkml.org/lkml/2012/10/3/552. This update processes all enumerating mports first and schedules discovery work after that. If the initialization routine fails to allocate resources needed to execute discovery, it abandons discovery for all ports. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio.c | 75 ++-- 1 files changed, 47 insertions(+), 28 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d4bd690..c17ae22 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work) pr_debug("RIO: discovery work for mport %d %s\n", work->mport->id, work->mport->name); rio_disc_mport(work->mport); - - kfree(work); } int __devinit rio_init_mports(void) { struct rio_mport *port; struct rio_disc_work *work; - int no_disc = 0; + int n = 0; + + if (!next_portid) + return -ENODEV; + /* +* First, run enumerations and check if we need to perform discovery +* on any of the registered mports. +*/ list_for_each_entry(port, &rio_mports, node) { if (port->host_deviceid >= 0) rio_enum_mport(port); - else if (!no_disc) { - if (!rio_wq) { - rio_wq = alloc_workqueue("riodisc", 0, 0); - if (!rio_wq) { - pr_err("RIO: unable allocate rio_wq\n"); - no_disc = 1; - continue; - } - } - - work = kzalloc(sizeof *work, GFP_KERNEL); - if (!work) { - pr_err("RIO: no memory for work struct\n"); - no_disc = 1; - continue; - } - - work->mport = port; - INIT_WORK(&work->work, disc_work_handler); - queue_work(rio_wq, &work->work); - } + else + n++; + } + + if (!n) + goto no_disc; + + /* +* If we have mports that require discovery schedule a discovery work +* for each of them. If the code below fails to allocate needed +* resources, exit without error to keep results of enumeration +* process (if any). +* TODO: Implement restart of dicovery process for all or +* individual discovering mports. +*/ + rio_wq = alloc_workqueue("riodisc", 0, 0); + if (!rio_wq) { + pr_err("RIO: unable allocate rio_wq\n"); + goto no_disc; } - if (rio_wq) { - pr_debug("RIO: flush discovery workqueue\n"); - flush_workqueue(rio_wq); - pr_debug("RIO: flush discovery workqueue finished\n"); + work = kcalloc(n, sizeof *work, GFP_KERNEL); + if (!work) { + pr_err("RIO: no memory for work struct\n"); destroy_workqueue(rio_wq); + goto no_disc; } + n = 0; + list_for_each_entry(port, &rio_mports, node) { + if (port->host_deviceid < 0) { + work[n].mport = port; + INIT_WORK(&work[n].work, disc_work_handler); + queue_work(rio_wq, &work[n].work); + n++; + } + } + + flush_workqueue(rio_wq); + pr_debug("RIO: destroy discovery workqueue\n"); + destroy_workqueue(rio_wq); + kfree(work); + +no_disc: rio_init(); return 0; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/3] rapidio: use msleep in discovery wait
Use msleep() routine for code clarity as suggested by Andrew Morton in his comments for the original patch: https://lkml.org/lkml/2012/10/3/546. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 48e9041..05f0ed9 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -1391,7 +1391,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport) while (time_before(jiffies, to_end)) { if (rio_enum_complete(mport)) goto enum_done; - schedule_timeout_uninterruptible(msecs_to_jiffies(10)); + msleep(10); } pr_debug("RIO: discovery timeout on mport %d %s\n", -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 0/3] rapidio: updates for multiple mport patches
This is a set of updates for patches submitted earlier: https://lkml.org/lkml/2012/10/3/460. Alexandre Bounine (3): rapidio: use msleep in discovery wait rapidio: update asynchronous discovery initialization rapidio: update for destination ID allocation drivers/rapidio/rio-scan.c | 40 ++- drivers/rapidio/rio.c | 75 +++ include/linux/rio.h|1 - 3 files changed, 64 insertions(+), 52 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/3] rapidio: update for destination ID allocation
This patch address comments provided by Andrew Morton: https://lkml.org/lkml/2012/10/3/550 - Keeps consistent kerneldoc compatible comments style for new static functions. - Removes unnecessary complexity from destination ID allocation routine. - Uses kcalloc() for code clarity. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c | 38 -- include/linux/rio.h|1 - 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 05f0ed9..07da58b 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -55,9 +55,9 @@ static int rio_mport_phys_table[] = { }; -/* +/** * rio_destid_alloc - Allocate next available destID for given network - * net: RIO network + * @net: RIO network * * Returns next available device destination ID for the specified RIO network. * Marks allocated ID as one in use. @@ -69,14 +69,9 @@ static u16 rio_destid_alloc(struct rio_net *net) struct rio_id_table *idtab = &net->destid_table; spin_lock(&idtab->lock); - destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next); - if (destid >= idtab->max) - destid = find_first_zero_bit(idtab->table, idtab->max); + destid = find_first_zero_bit(idtab->table, idtab->max); if (destid < idtab->max) { - idtab->next = destid + 1; - if (idtab->next >= idtab->max) - idtab->next = 0; set_bit(destid, idtab->table); destid += idtab->start; } else @@ -86,10 +81,10 @@ static u16 rio_destid_alloc(struct rio_net *net) return (u16)destid; } -/* +/** * rio_destid_reserve - Reserve the specivied destID - * net: RIO network - * destid: destID to reserve + * @net: RIO network + * @destid: destID to reserve * * Tries to reserve the specified destID. * Returns 0 if successfull. @@ -106,10 +101,10 @@ static int rio_destid_reserve(struct rio_net *net, u16 destid) return oldbit; } -/* +/** * rio_destid_free - free a previously allocated destID - * net: RIO network - * destid: destID to free + * @net: RIO network + * @destid: destID to free * * Makes the specified destID available for use. */ @@ -123,9 +118,9 @@ static void rio_destid_free(struct rio_net *net, u16 destid) spin_unlock(&idtab->lock); } -/* +/** * rio_destid_first - return first destID in use - * net: RIO network + * @net: RIO network */ static u16 rio_destid_first(struct rio_net *net) { @@ -142,10 +137,10 @@ static u16 rio_destid_first(struct rio_net *net) return (u16)destid; } -/* +/** * rio_destid_next - return next destID in use - * net: RIO network - * from: destination ID from which search shall continue + * @net: RIO network + * @from: destination ID from which search shall continue */ static u16 rio_destid_next(struct rio_net *net, u16 from) { @@ -1163,8 +1158,8 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port, net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); if (net && do_enum) { - net->destid_table.table = kzalloc( - BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)) * + net->destid_table.table = kcalloc( + BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)), sizeof(long), GFP_KERNEL); @@ -1174,7 +1169,6 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port, net = NULL; } else { net->destid_table.start = start; - net->destid_table.next = 0; net->destid_table.max = RIO_MAX_ROUTE_ENTRIES(port->sys_size); spin_lock_init(&net->destid_table.lock); diff --git a/include/linux/rio.h b/include/linux/rio.h index d2dff22..ac21ac6 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -266,7 +266,6 @@ struct rio_mport { struct rio_id_table { u16 start; /* logical minimal id */ - u16 next; /* hint for find */ u32 max;/* max number of IDs in table */ spinlock_t lock; unsigned long *table; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/5] rapidio/rionet: rework to support multiple RIO master ports
Make RIONET driver multi-net safe/capable by introducing per-net lists of RapidIO network peers. Rework registration of network adapters to support all available RIO master port devices. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: David S. Miller --- drivers/net/rionet.c | 133 ++ 1 files changed, 70 insertions(+), 63 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 1470d3e..d8b9b1e 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -26,7 +26,7 @@ #include #define DRV_NAME"rionet" -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.3" #define DRV_AUTHOR "Matt Porter " #define DRV_DESC"Ethernet over RapidIO" @@ -47,8 +47,7 @@ MODULE_LICENSE("GPL"); #define RIONET_TX_RING_SIZECONFIG_RIONET_TX_SIZE #define RIONET_RX_RING_SIZECONFIG_RIONET_RX_SIZE - -static LIST_HEAD(rionet_peers); +#define RIONET_MAX_NETS8 struct rionet_private { struct rio_mport *mport; @@ -69,17 +68,14 @@ struct rionet_peer { struct resource *res; }; -static int rionet_check = 0; -static int rionet_capable = 1; +struct rionet_net { + struct net_device *ndev; + struct list_head peers; + struct rio_dev **active; + int nact; /* number of active peers */ +}; -/* - * This is a fast lookup table for translating TX - * Ethernet packets into a destination RIO device. It - * could be made into a hash table to save memory depending - * on system trade-offs. - */ -static struct rio_dev **rionet_active; -static int nact; /* total number of active rionet peers */ +static struct rionet_net nets[RIONET_MAX_NETS]; #define is_rionet_capable(src_ops, dst_ops)\ ((src_ops & RIO_SRC_OPS_DATA_MSG) &&\ @@ -185,7 +181,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } if (is_multicast_ether_addr(eth->h_dest)) - add_num = nact; + add_num = nets[rnet->mport->id].nact; if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); @@ -197,19 +193,21 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (is_multicast_ether_addr(eth->h_dest)) { int count = 0; + for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) { + if (nets[rnet->mport->id].active[i]) { rionet_queue_tx_msg(skb, ndev, - rionet_active[i]); + nets[rnet->mport->id].active[i]); if (count) atomic_inc(&skb->users); count++; } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid = RIONET_GET_DESTID(eth->h_dest); - if (rionet_active[destid]) - rionet_queue_tx_msg(skb, ndev, rionet_active[destid]); + if (nets[rnet->mport->id].active[destid]) + rionet_queue_tx_msg(skb, ndev, + nets[rnet->mport->id].active[destid]); } spin_unlock_irqrestore(&rnet->tx_lock, flags); @@ -228,19 +226,21 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x", DRV_NAME, sid, tid, info); if (info == RIONET_DOORBELL_JOIN) { - if (!rionet_active[sid]) { - list_for_each_entry(peer, &rionet_peers, node) { + if (!nets[rnet->mport->id].active[sid]) { + list_for_each_entry(peer, + &nets[rnet->mport->id].peers, node) { if (peer->rdev->destid == sid) { - rionet_active[sid] = peer->rdev; - nact++; + nets[rnet->mport->id].active[sid] = + peer->rdev; + nets[rnet->mport->id].nact++; } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info == RIONET_DOORBELL_LEAVE) { - rionet_active[
[PATCH 5/5] rapidio: add destination ID allocation mechanism
Replace the single global destination ID counter with per-net allocation mechanism to allow independent destID management for each available RapidIO network. Using bitmap based mechanism instead of counters allows destination ID release and reuse in systems that support hot-swap. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c | 205 include/linux/rio.h|9 ++ 2 files changed, 179 insertions(+), 35 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 745670f..48e9041 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -54,6 +54,114 @@ static int rio_mport_phys_table[] = { -1, }; + +/* + * rio_destid_alloc - Allocate next available destID for given network + * net: RIO network + * + * Returns next available device destination ID for the specified RIO network. + * Marks allocated ID as one in use. + * Returns RIO_INVALID_DESTID if new destID is not available. + */ +static u16 rio_destid_alloc(struct rio_net *net) +{ + int destid; + struct rio_id_table *idtab = &net->destid_table; + + spin_lock(&idtab->lock); + destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next); + if (destid >= idtab->max) + destid = find_first_zero_bit(idtab->table, idtab->max); + + if (destid < idtab->max) { + idtab->next = destid + 1; + if (idtab->next >= idtab->max) + idtab->next = 0; + set_bit(destid, idtab->table); + destid += idtab->start; + } else + destid = RIO_INVALID_DESTID; + + spin_unlock(&idtab->lock); + return (u16)destid; +} + +/* + * rio_destid_reserve - Reserve the specivied destID + * net: RIO network + * destid: destID to reserve + * + * Tries to reserve the specified destID. + * Returns 0 if successfull. + */ +static int rio_destid_reserve(struct rio_net *net, u16 destid) +{ + int oldbit; + struct rio_id_table *idtab = &net->destid_table; + + destid -= idtab->start; + spin_lock(&idtab->lock); + oldbit = test_and_set_bit(destid, idtab->table); + spin_unlock(&idtab->lock); + return oldbit; +} + +/* + * rio_destid_free - free a previously allocated destID + * net: RIO network + * destid: destID to free + * + * Makes the specified destID available for use. + */ +static void rio_destid_free(struct rio_net *net, u16 destid) +{ + struct rio_id_table *idtab = &net->destid_table; + + destid -= idtab->start; + spin_lock(&idtab->lock); + clear_bit(destid, idtab->table); + spin_unlock(&idtab->lock); +} + +/* + * rio_destid_first - return first destID in use + * net: RIO network + */ +static u16 rio_destid_first(struct rio_net *net) +{ + int destid; + struct rio_id_table *idtab = &net->destid_table; + + spin_lock(&idtab->lock); + destid = find_first_bit(idtab->table, idtab->max); + if (destid >= idtab->max) + destid = RIO_INVALID_DESTID; + else + destid += idtab->start; + spin_unlock(&idtab->lock); + return (u16)destid; +} + +/* + * rio_destid_next - return next destID in use + * net: RIO network + * from: destination ID from which search shall continue + */ +static u16 rio_destid_next(struct rio_net *net, u16 from) +{ + int destid; + struct rio_id_table *idtab = &net->destid_table; + + spin_lock(&idtab->lock); + destid = find_next_bit(idtab->table, idtab->max, from); + if (destid >= idtab->max) + destid = RIO_INVALID_DESTID; + else + destid += idtab->start; + spin_unlock(&idtab->lock); + return (u16)destid; +} + /** * rio_get_device_id - Get the base/extended device id for a device * @port: RIO master port @@ -171,10 +279,6 @@ static int rio_enum_host(struct rio_mport *port) /* Set master port destid and init destid ctr */ rio_local_set_device_id(port, port->host_deviceid); - - if (next_destid == port->host_deviceid) - next_destid++; - return 0; } @@ -441,9 +545,8 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { if (do_enum) { rio_set_device_id(port, destid, hopcount, next_destid); - rdev->destid = next_destid++; - if (next_destid == port->host_deviceid) - next_destid++; + rdev->destid = next_destid; + next_destid = rio_destid_alloc(net);
[PATCH 2/5] rapidio: use device lists handling on per-net basis
Modify handling of device lists to resolve issues caused by using single global list of RIO devices during enumeration/discovery. The most common sign of existing issue is incorrect contents of switch routing tables in systems with multiple mport controllers while single-port configuration performs as expected. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c | 60 ++- include/linux/rio.h|1 + 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 0a27253..8b7c4bc 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -38,7 +38,6 @@ #include "rio.h" LIST_HEAD(rio_devices); -static LIST_HEAD(rio_switches); static void rio_init_em(struct rio_dev *rdev); @@ -104,14 +103,15 @@ static void rio_local_set_device_id(struct rio_mport *port, u16 did) /** * rio_clear_locks- Release all host locks and signal enumeration complete - * @port: Master port to issue transaction + * @net: RIO network to run on * * Marks the component tag CSR on each device with the enumeration * complete flag. When complete, it then release the host locks on * each device. Returns 0 on success or %-EINVAL on failure. */ -static int rio_clear_locks(struct rio_mport *port) +static int rio_clear_locks(struct rio_net *net) { + struct rio_mport *port = net->hport; struct rio_dev *rdev; u32 result; int ret = 0; @@ -126,7 +126,7 @@ static int rio_clear_locks(struct rio_mport *port) result); ret = -EINVAL; } - list_for_each_entry(rdev, &rio_devices, global_list) { + list_for_each_entry(rdev, &net->devices, net_list) { rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, port->host_deviceid); rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); @@ -479,7 +479,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rswitch->clr_table(port, destid, hopcount, RIO_GLOBAL_TABLE); - list_add_tail(&rswitch->node, &rio_switches); + list_add_tail(&rswitch->node, &net->switches); } else { if (do_enum) @@ -1058,6 +1058,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) if (net) { INIT_LIST_HEAD(&net->node); INIT_LIST_HEAD(&net->devices); + INIT_LIST_HEAD(&net->switches); INIT_LIST_HEAD(&net->mports); list_add_tail(&port->nnode, &net->mports); net->hport = port; @@ -1068,24 +1069,24 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) /** * rio_update_route_tables- Updates route tables in switches - * @port: Master port associated with the RIO network + * @net: RIO network to run update on * * For each enumerated device, ensure that each switch in a system * has correct routing entries. Add routes for devices that where * unknown dirung the first enumeration pass through the switch. */ -static void rio_update_route_tables(struct rio_mport *port) +static void rio_update_route_tables(struct rio_net *net) { struct rio_dev *rdev, *swrdev; struct rio_switch *rswitch; u8 sport; u16 destid; - list_for_each_entry(rdev, &rio_devices, global_list) { + list_for_each_entry(rdev, &net->devices, net_list) { destid = rdev->destid; - list_for_each_entry(rswitch, &rio_switches, node) { + list_for_each_entry(rswitch, &net->switches, node) { if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) continue; @@ -1181,12 +1182,12 @@ int __devinit rio_enum_mport(struct rio_mport *mport) printk(KERN_INFO "RIO: master port %d device has lost enumeration to a remote host\n", mport->id); - rio_clear_locks(mport); + rio_clear_locks(net); rc = -EBUSY; goto out; } - rio_update_route_tables(mport); - rio_clear_locks(mport); + rio_update_route_tables(net); + rio_clear_locks(net); rio_pw_enable(mport, 1); } else { printk(KERN_INFO "RIO: master port %d link inactive\n", @@ -1200,33 +1201,34 @@ int __devinit rio_enum_mport(struct rio_mport *mport) /** * rio_build_route_tables- Generate route tables from switch route ent
[PATCH 0/5] rapidio: patches to support multiple master ports
The following set of patches provides modifications targeting support of multiple RapidIO master port (mport) devices on a CPU-side of RapidIO-capable board. While the RapidIO subsystem code has definitions suitable for multi-controller/multi-net support, the existing implementation cannot be considered ready for multiple mport configurations. === NOTES: = a) The patches below do not address RapidIO side view of multiport processing elements defined in Part 6 of RapidIO spec Rev.2.1 (section 6.4.1). These devices have Base Device ID CSR (0x60) and Component Tag CSR (0x6C) shared by all SRIO ports. For example, Freescale's P4080, P3041 and P5020 have a dual-port SRIO controller implemented according the specification. Enumeration/discovery of such devices from RapidIO side may require device-specific fixups. b) Devices referenced above may also require implementation specific code to setup a host device ID for mport device. These operations are not addressed by patches in this package. = Details about provided patches: 1. Fix blocking wait for discovery ready While it does not happen on PowerPC based platforms, there is possibility of stalled CPU warning dump on x86 based platforms that run RapidIO discovery process if they wait too long for being enumerated. Currently users can avoid it by disabling the soft-lockup detector using "nosoftlockup" kernel parameter OR by ensuring that enumeration is completed before soft-lockup is detected. This patch eliminates blocking wait and keeps a scheduler running. It also is required for patch 3 below which introduces asynchronous discovery process. 2. Use device lists handling on per-net basis This patch allows to correctly support multiple RapidIO nets and resolves possible issues caused by using single global list of devices during RapidIO system enumeration/discovery. The most common sign of existing issue is incorrect contents of switch routing tables in systems with multiple mport controllers while single-port configuration performs as expected. The patch does not eliminate the global RapidIO device list but changes some routines in enumeration/discovery to use per-net device lists instead. This way compatibility with upper layer RIO routines is preserved. 3. Run discovery as an asynchronous process This patch modifies RapidIO initialization routine to asynchronously run the discovery process for each corresponding mport. This allows having an arbitrary order of enumerating and discovering mports without creating a deadlock situation if an enumerator port was registered after a discovering one. On boards with multiple discovering mports it also eliminates order dependency between mports and may reduce total time of RapidIO subsystem initialization. Making netID matching to mportID ensures consistent netID assignment in multiport RapidIO systems with asynchronous discovery process (global counter implementation is affected by race between threads). 4. Rework RIONET to support multiple RIO master ports In the current version of the driver rionet_probe() has comment "XXX Make multi-net safe". Now it is a good time to address this comment. This patch makes RIONET driver multi-net safe/capable by introducing per-net lists of RapidIO network peers. It also enables to register network adapters for all available mport devices. 5. Add destination ID allocation mechanism The patch replaces a single global destination ID counter with per-net allocation mechanism to allow independent destID management for each available RapidIO network. Using bitmap based mechanism instead of counters allows destination ID release and reuse in systems that support hot-swap. Alexandre Bounine (5): rapidio: fix blocking wait for discovery ready rapidio: use device lists handling on per-net basis rapidio: run discovery as an asynchronous process rapidio/rionet: rework to support multiple RIO master ports rapidio: add destination ID allocation mechanism drivers/net/rionet.c | 133 ++- drivers/rapidio/rio-scan.c | 326 +-- drivers/rapidio/rio.c | 51 +++- include/linux/rio.h| 10 ++ 4 files changed, 349 insertions(+), 171 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/5] rapidio: fix blocking wait for discovery ready
Fix blocking wait loop in the RapidIO discovery routine to avoid warning dumps about stalled CPU on x86 platforms. Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c | 62 ++- 1 files changed, 20 insertions(+), 42 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 02e686b..0a27253 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -39,8 +40,6 @@ LIST_HEAD(rio_devices); static LIST_HEAD(rio_switches); -static void rio_enum_timeout(unsigned long); - static void rio_init_em(struct rio_dev *rdev); DEFINE_SPINLOCK(rio_global_list_lock); @@ -49,9 +48,6 @@ static int next_destid = 0; static int next_net = 0; static int next_comptag = 1; -static struct timer_list rio_enum_timer = -TIMER_INITIALIZER(rio_enum_timeout, 0, 0); - static int rio_mport_phys_table[] = { RIO_EFB_PAR_EP_ID, RIO_EFB_PAR_EP_REC_ID, @@ -1234,20 +1230,6 @@ static void rio_build_route_tables(void) } /** - * rio_enum_timeout- Signal that enumeration timed out - * @data: Address of timeout flag. - * - * When the enumeration complete timer expires, set a flag that - * signals to the discovery process that enumeration did not - * complete in a sane amount of time. - */ -static void rio_enum_timeout(unsigned long data) -{ - /* Enumeration timed out, set flag */ - *(int *)data = 1; -} - -/** * rio_disc_mport- Start discovery through a master port * @mport: Master port to send transactions * @@ -1260,34 +1242,33 @@ static void rio_enum_timeout(unsigned long data) int __devinit rio_disc_mport(struct rio_mport *mport) { struct rio_net *net = NULL; - int enum_timeout_flag = 0; + unsigned long to_end; printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, mport->name); /* If master port has an active link, allocate net and discover peers */ if (rio_mport_is_active(mport)) { - if (!(net = rio_alloc_net(mport))) { - printk(KERN_ERR "RIO: Failed to allocate new net\n"); - goto bail; - } + pr_debug("RIO: wait for enumeration to complete...\n"); - pr_debug("RIO: wait for enumeration complete..."); - - rio_enum_timer.expires = - jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; - rio_enum_timer.data = (unsigned long)&enum_timeout_flag; - add_timer(&rio_enum_timer); - while (!rio_enum_complete(mport)) { - mdelay(1); - if (enum_timeout_flag) { - del_timer_sync(&rio_enum_timer); - goto timeout; - } + to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; + while (time_before(jiffies, to_end)) { + if (rio_enum_complete(mport)) + goto enum_done; + schedule_timeout_uninterruptible(msecs_to_jiffies(10)); } - del_timer_sync(&rio_enum_timer); - pr_debug("done\n"); + pr_debug("RIO: discovery timeout on mport %d %s\n", +mport->id, mport->name); + goto bail; +enum_done: + pr_debug("RIO: ... enumeration done\n"); + + net = rio_alloc_net(mport); + if (!net) { + printk(KERN_ERR "RIO: Failed to allocate new net\n"); + goto bail; + } /* Read DestID assigned by enumerator */ rio_local_read_config_32(mport, RIO_DID_CSR, @@ -1307,9 +1288,6 @@ int __devinit rio_disc_mport(struct rio_mport *mport) } return 0; - - timeout: - pr_debug("timeout\n"); - bail: +bail: return -EBUSY; } -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/5] rapidio: run discovery as an asynchronous process
Modify mport initialization routine to run the RapidIO discovery process asynchronously. This allows to have an arbitrary order of enumerating and discovering ports in systems with multiple RapidIO controllers without creating a deadlock situation if enumerator port is registered after a discovering one. Making netID matching to mportID ensures consistent net ID assignment in multiport RapidIO systems with asynchronous discovery process (global counter implementation is affected by race between threads). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/rio-scan.c |3 +- drivers/rapidio/rio.c | 51 ++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 8b7c4bc..745670f 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -44,7 +44,6 @@ static void rio_init_em(struct rio_dev *rdev); DEFINE_SPINLOCK(rio_global_list_lock); static int next_destid = 0; -static int next_net = 0; static int next_comptag = 1; static int rio_mport_phys_table[] = { @@ -1062,7 +1061,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) INIT_LIST_HEAD(&net->mports); list_add_tail(&port->nnode, &net->mports); net->hport = port; - net->id = next_net++; + net->id = port->id; } return net; } diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d7b68cc..7cdc3e6d 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1260,15 +1260,62 @@ static int __devinit rio_init(void) return 0; } +static struct workqueue_struct *rio_wq; + +struct rio_disc_work { + struct work_struct work; + struct rio_mport*mport; +}; + +static void __devinit disc_work_handler(struct work_struct *_work) +{ + struct rio_disc_work *work = container_of(_work, + struct rio_disc_work, work); + + pr_debug("RIO: discovery work for mport %d %s\n", +work->mport->id, work->mport->name); + rio_disc_mport(work->mport); + + kfree(work); +} + int __devinit rio_init_mports(void) { struct rio_mport *port; + struct rio_disc_work *work; + int no_disc = 0; list_for_each_entry(port, &rio_mports, node) { if (port->host_deviceid >= 0) rio_enum_mport(port); - else - rio_disc_mport(port); + else if (!no_disc) { + if (!rio_wq) { + rio_wq = alloc_workqueue("riodisc", 0, 0); + if (!rio_wq) { + pr_err("RIO: unable allocate rio_wq\n"); + no_disc = 1; + continue; + } + } + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) { + pr_err("RIO: no memory for work struct\n"); + no_disc = 1; + continue; + } + + work->mport = port; + INIT_WORK(&work->work, disc_work_handler); + queue_work(rio_wq, &work->work); + } + } + + if (rio_wq) { + pr_debug("RIO: flush discovery workqueue\n"); + flush_workqueue(rio_wq); + pr_debug("RIO: flush discovery workqueue finished\n"); + destroy_workqueue(rio_wq); } rio_init(); -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/rionet: fix multicast packet transmit logic
Fix multicast packet transmit logic to account for repetitive transmission of single skb: - correct check for available buffers (this bug may produce NULL pointer crash dump in case of heavy traffic); - update skb user count (incorrect user counter causes a warning dump from net_tx_action routine during multicast transfers in systems with three or more rionet participants). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: David S. Miller Cc: net...@vger.kernel.org --- drivers/net/rionet.c | 20 +--- 1 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 91d2588..1470d3e 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -79,6 +79,7 @@ static int rionet_capable = 1; * on system trade-offs. */ static struct rio_dev **rionet_active; +static int nact; /* total number of active rionet peers */ #define is_rionet_capable(src_ops, dst_ops)\ ((src_ops & RIO_SRC_OPS_DATA_MSG) &&\ @@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct ethhdr *eth = (struct ethhdr *)skb->data; u16 destid; unsigned long flags; + int add_num = 1; local_irq_save(flags); if (!spin_trylock(&rnet->tx_lock)) { @@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_LOCKED; } - if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { + if (is_multicast_ether_addr(eth->h_dest)) + add_num = nact; + + if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); spin_unlock_irqrestore(&rnet->tx_lock, flags); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", @@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } if (is_multicast_ether_addr(eth->h_dest)) { + int count = 0; for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) + if (rionet_active[i]) { rionet_queue_tx_msg(skb, ndev, rionet_active[i]); + if (count) + atomic_inc(&skb->users); + count++; + } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid = RIONET_GET_DESTID(eth->h_dest); if (rionet_active[destid]) @@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u if (info == RIONET_DOORBELL_JOIN) { if (!rionet_active[sid]) { list_for_each_entry(peer, &rionet_peers, node) { - if (peer->rdev->destid == sid) + if (peer->rdev->destid == sid) { rionet_active[sid] = peer->rdev; + nact++; + } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info == RIONET_DOORBELL_LEAVE) { rionet_active[sid] = NULL; + nact--; } else { if (netif_msg_intr(rnet)) printk(KERN_WARNING "%s: unhandled doorbell\n", @@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) rc = rionet_setup_netdev(rdev->net->hport, ndev); rionet_check = 1; + nact = 0; } /* -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH RESEND] rapidio: apply RX/TX enable to active switch ports only
Apply port RX/TX enable operations only to active switch ports. RapidIO specification (Part 6: LP-Serial Physical Layer) recommends to keep Output Port Enable (TX) and Input Port Enable (RX) control bits in disabled state (0b0) after device reset. It also allows to have implementation specific reset state for these bits. This patch ensures that TX/RX enable action is applied only to active switch's ports while preserving an initial state of inactive ones. Signed-off-by: Alexandre Bounine Cc: Matt Porter --- RESEND: Initial submission of this patch was dropped due to feedback comment which raised concern about some RapidIO switch implementations that may be affected by the change. After specification and device details review this patch declared to be safe because it preserves any combination of initial states of RX/TX enable for inactive port. drivers/rapidio/rio-scan.c |9 + 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 2bebd79..02e686b 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -839,12 +839,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, for (port_num = 0; port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); port_num++) { - /*Enable Input Output Port (transmitter reviever)*/ - rio_enable_rx_tx_port(port, 0, + if (sw_inport == port_num) { + rio_enable_rx_tx_port(port, 0, RIO_ANY_DESTID(port->sys_size), hopcount, port_num); - - if (sw_inport == port_num) { rdev->rswitch->port_ok |= (1 << port_num); continue; } @@ -857,6 +855,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, pr_debug( "RIO: scanning device on port %d\n", port_num); + rio_enable_rx_tx_port(port, 0, + RIO_ANY_DESTID(port->sys_size), + hopcount, port_num); rdev->rswitch->port_ok |= (1 << port_num); rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, RIO_ANY_DESTID(port->sys_size), -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/2] rapidio/tsi721: add inbound memory mapping callbacks
Add Tsi721 routines to support RapidIO subsystem's inbound memory mapping interface (RapidIO to system's local memory). Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala --- drivers/rapidio/devices/tsi721.c | 88 +- drivers/rapidio/devices/tsi721.h | 15 +- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 1974359..961dc7a 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -862,6 +862,90 @@ static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv) } /** + * tsi721_rio_map_inb_mem -- Mapping inbound memory region. + * @mport: RapidIO master port + * @lstart: Local memory space start address. + * @rstart: RapidIO space start address. + * @size: The mapping region size. + * @flags: Flags for mapping. 0 for using default flags. + * + * Return: 0 -- Success. + * + * This function will create the inbound mapping + * from rstart to lstart. + */ +static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, + u64 rstart, u32 size, u32 flags) +{ + struct tsi721_device *priv = mport->priv; + int i; + u32 regval; + + if (!is_power_of_2(size) || size < 0x1000 || + ((u64)lstart & (size - 1)) || (rstart & (size - 1))) + return -EINVAL; + + /* Search for free inbound translation window */ + for (i = 0; i < TSI721_IBWIN_NUM; i++) { + regval = ioread32(priv->regs + TSI721_IBWIN_LB(i)); + if (!(regval & TSI721_IBWIN_LB_WEN)) + break; + } + + if (i >= TSI721_IBWIN_NUM) { + dev_err(&priv->pdev->dev, + "Unable to find free inbound window\n"); + return -EBUSY; + } + + iowrite32(TSI721_IBWIN_SIZE(size) << 8, + priv->regs + TSI721_IBWIN_SZ(i)); + + iowrite32(((u64)lstart >> 32), priv->regs + TSI721_IBWIN_TUA(i)); + iowrite32(((u64)lstart & TSI721_IBWIN_TLA_ADD), + priv->regs + TSI721_IBWIN_TLA(i)); + + iowrite32(rstart >> 32, priv->regs + TSI721_IBWIN_UB(i)); + iowrite32((rstart & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN, + priv->regs + TSI721_IBWIN_LB(i)); + dev_dbg(&priv->pdev->dev, + "Configured IBWIN%d mapping (RIO_0x%llx -> PCIe_0x%llx)\n", + i, rstart, (unsigned long long)lstart); + + return 0; +} + +/** + * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region. + * @mport: RapidIO master port + * @lstart: Local memory space start address. + */ +static void tsi721_rio_unmap_inb_mem(struct rio_mport *mport, + dma_addr_t lstart) +{ + struct tsi721_device *priv = mport->priv; + int i; + u64 addr; + u32 regval; + + /* Search for matching active inbound translation window */ + for (i = 0; i < TSI721_IBWIN_NUM; i++) { + regval = ioread32(priv->regs + TSI721_IBWIN_LB(i)); + if (regval & TSI721_IBWIN_LB_WEN) { + regval = ioread32(priv->regs + TSI721_IBWIN_TUA(i)); + addr = (u64)regval << 32; + regval = ioread32(priv->regs + TSI721_IBWIN_TLA(i)); + addr |= regval & TSI721_IBWIN_TLA_ADD; + + if (addr == (u64)lstart) { + iowrite32(0, priv->regs + TSI721_IBWIN_LB(i)); + break; + } + } + } +} + +/** * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe) * translation regions. * @priv: pointer to tsi721 private data @@ -874,7 +958,7 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv) /* Disable all SR2PC inbound windows */ for (i = 0; i < TSI721_IBWIN_NUM; i++) - iowrite32(0, priv->regs + TSI721_IBWINLB(i)); + iowrite32(0, priv->regs + TSI721_IBWIN_LB(i)); } /** @@ -2144,6 +2228,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) ops->add_outb_message = tsi721_add_outb_message; ops->add_inb_buffer = tsi721_add_inb_buffer; ops->get_inb_message = tsi721_get_inb_message; + ops->map_inb = tsi721_rio_map_inb_mem; + ops->unmap_inb = tsi721_rio_unmap_inb_mem; mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); if (!mport) { diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 59de9d7..7d5b13b 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -156,9 +156,18 @@ #define TSI721_IBWIN_NUM 8 -
[PATCH 0/2] rapidio: add inbound memory mapping API
Add RapidIO subsystem interface to support mapping of RapidIO memory space into system's local memory. RapidIO specification defines memory mapped read (NREAD) and write (NWRITE, NWRITE_R and SWRITE) requests that allow to access memory space on remote target device. Existing RapidIO controllers/bridges provide hardware mechanism to map addresses on RapidIO side into system's local memory. Patches provided in this package define common interface that has to be supported by RIO master port devices and hardware dependent implementation for IDT Tsi721 PCIe-to-SRIO bridge. These patches are based on the work submitted by Li Yang (https://lists.ozlabs.org/pipermail/linuxppc-dev/2009-April/071210.html) but implement only the inbound mapping portion of it. Combined with RapidIO DMA engine interface support these patches allow to perform memory mapped data transfers between devices connected to a RapidIO network. Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala --- Alexandre Bounine (2): rapidio: add inbound memory mapping interface rapidio/tsi721: add inbound memory mapping callbacks drivers/rapidio/devices/tsi721.c | 88 +- drivers/rapidio/devices/tsi721.h | 15 +- drivers/rapidio/rio.c| 44 +++ include/linux/rio.h |5 ++ include/linux/rio_drv.h |5 ++ 5 files changed, 153 insertions(+), 4 deletions(-) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/2] rapidio: add inbound memory mapping interface
Add common inbound memory mapping/unmapping interface. This allows to make local memory space accessible from the RapidIO side using hardware mapping capabilities of RapidIO bridging devices. The new interface is intended to enable data transfers between RapidIO devices in combination with DMA engine support. This patch is based on patch submitted by Li Yang (https://lists.ozlabs.org/pipermail/linuxppc-dev/2009-April/071210.html) Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala --- drivers/rapidio/rio.c | 44 include/linux/rio.h |5 + include/linux/rio_drv.h |5 + 3 files changed, 54 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c40665a..d7b68cc 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -33,6 +33,7 @@ static LIST_HEAD(rio_mports); static unsigned char next_portid; +static DEFINE_SPINLOCK(rio_mmap_lock); /** * rio_local_get_device_id - Get the base/extended device id for a port @@ -398,6 +399,49 @@ int rio_release_inb_pwrite(struct rio_dev *rdev) EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); /** + * rio_map_inb_region -- Map inbound memory region. + * @mport: Master port. + * @lstart: physical address of memory region to be mapped + * @rbase: RIO base address assigned to this window + * @size: Size of the memory region + * @rflags: Flags for mapping. + * + * Return: 0 -- Success. + * + * This function will create the mapping from RIO space to local memory. + */ +int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, + u64 rbase, u32 size, u32 rflags) +{ + int rc = 0; + unsigned long flags; + + if (!mport->ops->map_inb) + return -1; + spin_lock_irqsave(&rio_mmap_lock, flags); + rc = mport->ops->map_inb(mport, local, rbase, size, rflags); + spin_unlock_irqrestore(&rio_mmap_lock, flags); + return rc; +} +EXPORT_SYMBOL_GPL(rio_map_inb_region); + +/** + * rio_unmap_inb_region -- Unmap the inbound memory region + * @mport: Master port + * @lstart: physical address of memory region to be unmapped + */ +void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart) +{ + unsigned long flags; + if (!mport->ops->unmap_inb) + return; + spin_lock_irqsave(&rio_mmap_lock, flags); + mport->ops->unmap_inb(mport, lstart); + spin_unlock_irqrestore(&rio_mmap_lock, flags); +} +EXPORT_SYMBOL_GPL(rio_unmap_inb_region); + +/** * rio_mport_get_physefb - Helper function that returns register offset * for Physical Layer Extended Features Block. * @port: Master port to issue transaction diff --git a/include/linux/rio.h b/include/linux/rio.h index ba382f2..4d1a104 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -301,6 +301,8 @@ struct rio_net { * @add_outb_message: Callback to add a message to an outbound mailbox queue. * @add_inb_buffer: Callback toadd a buffer to an inbound mailbox queue. * @get_inb_message: Callback to get a message from an inbound mailbox queue. + * @map_inb: Callback to map RapidIO address region into local memory space. + * @unmap_inb: Callback to unmap RapidIO address region mapped with map_inb(). */ struct rio_ops { int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len, @@ -323,6 +325,9 @@ struct rio_ops { int mbox, void *buffer, size_t len); int (*add_inb_buffer)(struct rio_mport *mport, int mbox, void *buf); void *(*get_inb_message)(struct rio_mport *mport, int mbox); + int (*map_inb)(struct rio_mport *mport, dma_addr_t lstart, + u64 rstart, u32 size, u32 flags); + void (*unmap_inb)(struct rio_mport *mport, dma_addr_t lstart); }; #define RIO_RESOURCE_MEM 0x0100 diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 31ad146..b75c059 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h @@ -365,6 +365,11 @@ void rio_release_regions(struct rio_dev *); int rio_request_region(struct rio_dev *, int, char *); void rio_release_region(struct rio_dev *, int); +/* Memory mapping functions */ +extern int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, + u64 rbase, u32 size, u32 rflags); +extern void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart); + /* Port-Write management */ extern int rio_request_inb_pwrite(struct rio_dev *, int (*)(struct rio_dev *, union rio_pw_msg*, int)); -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio: fix kerneldoc warnings after DMA support was added
Signed-off-by: Alexandre Bounine Reported-by: Robert P. J. Day Cc: Robert P. J. Day --- include/linux/rio.h |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/include/linux/rio.h b/include/linux/rio.h index 1a7b6c7..ba382f2 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -236,6 +236,7 @@ enum rio_phy_type { * @phys_efptr: RIO port extended features pointer * @name: Port name string * @priv: Master port private data + * @dma: DMA device associated with mport */ struct rio_mport { struct list_head dbells;/* list of doorbell events */ @@ -404,7 +405,7 @@ union rio_pw_msg { #ifdef CONFIG_RAPIDIO_DMA_ENGINE -/** +/* * enum rio_write_type - RIO write transaction types used in DMA transfers * * Note: RapidIO specification defines write (NWRITE) and -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: modify mport name assignment
Modify mport device name assignment to provide clear reference to devices in systems with multiple Tsi721 bridges. This patch is applicable to kernel versions starting from v3.2. Signed-off-by: Alexandre Bounine Cc: Matt Porter --- drivers/rapidio/devices/tsi721.c |3 ++- include/linux/rio.h |3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 5d44252..8533f36 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2165,7 +2165,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0x); rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); - strcpy(mport->name, "Tsi721 mport"); + snprintf(mport->name, RIO_MAX_MPORT_NAME, "%s(%s)", +dev_driver_string(&pdev->dev), dev_name(&pdev->dev)); /* Hook up interrupt handler */ diff --git a/include/linux/rio.h b/include/linux/rio.h index a90ebad..1a7b6c7 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -30,6 +30,7 @@ #define RIO_MAX_MPORTS 8 #define RIO_MAX_MPORT_RESOURCES16 #define RIO_MAX_DEV_RESOURCES 16 +#define RIO_MAX_MPORT_NAME 40 #define RIO_GLOBAL_TABLE 0xff/* Indicates access of a switch's global routing table if it @@ -255,7 +256,7 @@ struct rio_mport { */ enum rio_phy_type phy_type; /* RapidIO phy type */ u32 phys_efptr; - unsigned char name[40]; + unsigned char name[RIO_MAX_MPORT_NAME]; void *priv; /* Master port private data */ #ifdef CONFIG_RAPIDIO_DMA_ENGINE struct dma_device dma; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio: apply RX/TX enable to active switch ports only
Modify RIO enumeration to apply RX/TX enable operations only to active switch ports. This will leave inactive ports in condition consistent with their state. This patch is applicable to kernel versions starting from v2.6.35. Signed-off-by: Alexandre Bounine Cc: Matt Porter --- drivers/rapidio/rio-scan.c |9 + 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 2bebd79..02e686b 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -839,12 +839,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, for (port_num = 0; port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); port_num++) { - /*Enable Input Output Port (transmitter reviever)*/ - rio_enable_rx_tx_port(port, 0, + if (sw_inport == port_num) { + rio_enable_rx_tx_port(port, 0, RIO_ANY_DESTID(port->sys_size), hopcount, port_num); - - if (sw_inport == port_num) { rdev->rswitch->port_ok |= (1 << port_num); continue; } @@ -857,6 +855,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, pr_debug( "RIO: scanning device on port %d\n", port_num); + rio_enable_rx_tx_port(port, 0, + RIO_ANY_DESTID(port->sys_size), + hopcount, port_num); rdev->rswitch->port_ok |= (1 << port_num); rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, RIO_ANY_DESTID(port->sys_size), -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: fix unused variable compiler warning
Fix unused variable compiler warning when built with CONFIG_RAPIDIO_DEBUG option off. This patch is applicable to kernel versions starting from v3.2 Signed-off-by: Alexandre Bounine Cc: Matt Porter --- drivers/rapidio/devices/tsi721.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index c0d6a04..5d44252 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2219,7 +2219,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i, cap; + int cap; int err; u32 regval; @@ -2239,12 +2239,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG + { + int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } + } #endif /* * Verify BAR configuration -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: fix inbound doorbell interrupt handling
Make sure that there is no doorbell messages left behind due to disabled interrupts during inbound doorbell processing. The most common case for this bug is loss of rionet JOIN messages in systems with three or more rionet participants and MSI or MSI-X enabled. As result, requests for packet transfers may finish with "destination unreachable" error message. This patch is applicable to kernel versions starting from v3.2. Signed-off-by: Alexandre Bounine Cc: Matt Porter --- drivers/rapidio/devices/tsi721.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 722246c..c0d6a04 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -435,6 +435,9 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } + + wr_ptr = ioread32(priv->regs + + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -445,6 +448,10 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + if (wr_ptr != rd_ptr) + schedule_work(&priv->idb_work); } /** -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH V2 2/2] rapidio/tsi721: add DMA engine support
Adds support for DMA Engine API into Tsi721 mport driver. Includes following changes for Tsi721 driver: - Modifies BDMA register offset definitions to support per-channel handling - Separates BDMA channel reserved for RIO Maintenance requests - Adds DMA Engine callback routines Signed-off-by: Alexandre Bounine --- This patch is applicable to linux-next-20120326 and after. v2: Address review comments, Switched to use dma_zalloc_coherent, Switched to use dma_transfer_direction enumerator, Uses updated prep_slave_sg() interface. drivers/rapidio/devices/Makefile |3 + drivers/rapidio/devices/tsi721.c | 211 ++ drivers/rapidio/devices/tsi721.h | 105 - drivers/rapidio/devices/tsi721_dma.c | 823 ++ 4 files changed, 1050 insertions(+), 92 deletions(-) create mode 100644 drivers/rapidio/devices/tsi721_dma.c diff --git a/drivers/rapidio/devices/Makefile b/drivers/rapidio/devices/Makefile index 3b7b4e2..7b62860 100644 --- a/drivers/rapidio/devices/Makefile +++ b/drivers/rapidio/devices/Makefile @@ -3,3 +3,6 @@ # obj-$(CONFIG_RAPIDIO_TSI721) += tsi721.o +ifeq ($(CONFIG_RAPIDIO_DMA_ENGINE),y) +obj-$(CONFIG_RAPIDIO_TSI721) += tsi721_dma.o +endif diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 30d2072..722246c 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -108,6 +108,7 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, u16 destid, u8 hopcount, u32 offset, int len, u32 *data, int do_wr) { + void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); struct tsi721_dma_desc *bd_ptr; u32 rd_count, swr_ptr, ch_stat; int i, err = 0; @@ -116,10 +117,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) return -EINVAL; - bd_ptr = priv->bdma[TSI721_DMACH_MAINT].bd_base; + bd_ptr = priv->mdma.bd_base; - rd_count = ioread32( - priv->regs + TSI721_DMAC_DRDCNT(TSI721_DMACH_MAINT)); + rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); /* Initialize DMA descriptor */ bd_ptr[0].type_id = cpu_to_le32((DTYPE2 << 29) | (op << 19) | destid); @@ -134,19 +134,18 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, mb(); /* Start DMA operation */ - iowrite32(rd_count + 2, - priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); - ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + iowrite32(rd_count + 2, regs + TSI721_DMAC_DWRCNT); + ioread32(regs + TSI721_DMAC_DWRCNT); i = 0; /* Wait until DMA transfer is finished */ - while ((ch_stat = ioread32(priv->regs + - TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) { + while ((ch_stat = ioread32(regs + TSI721_DMAC_STS)) + & TSI721_DMAC_STS_RUN) { udelay(1); if (++i >= 500) { dev_dbg(&priv->pdev->dev, "%s : DMA[%d] read timeout ch_status=%x\n", - __func__, TSI721_DMACH_MAINT, ch_stat); + __func__, priv->mdma.ch_id, ch_stat); if (!do_wr) *data = 0x; err = -EIO; @@ -162,13 +161,10 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, __func__, ch_stat); dev_dbg(&priv->pdev->dev, "OP=%d : destid=%x hc=%x off=%x\n", do_wr ? MAINT_WR : MAINT_RD, destid, hopcount, offset); - iowrite32(TSI721_DMAC_INT_ALL, - priv->regs + TSI721_DMAC_INT(TSI721_DMACH_MAINT)); - iowrite32(TSI721_DMAC_CTL_INIT, - priv->regs + TSI721_DMAC_CTL(TSI721_DMACH_MAINT)); + iowrite32(TSI721_DMAC_INT_ALL, regs + TSI721_DMAC_INT); + iowrite32(TSI721_DMAC_CTL_INIT, regs + TSI721_DMAC_CTL); udelay(10); - iowrite32(0, priv->regs + - TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + iowrite32(0, regs + TSI721_DMAC_DWRCNT); udelay(1); if (!do_wr) *data = 0x; @@ -184,8 +180,8 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, * NOTE: Skipping check and clear FIFO entries because we are waiting * for transfer to be completed. */ - swr_ptr = ioread32(priv->regs + TSI721_DMAC_DSWP(TSI721_DMAC
[PATCH V2 1/2] rapidio: add DMA engine support for RIO data transfers
Adds DMA Engine framework support into RapidIO subsystem. Uses DMA Engine DMA_SLAVE interface to generate data transfers to/from remote RapidIO target devices. Introduces RapidIO-specific wrapper for prep_slave_sg() interface with an extra parameter to pass target specific information. Uses scatterlist to describe local data buffer. Address flat data buffer on a remote side. Signed-off-by: Alexandre Bounine --- This patch is applicable to linux-next-20120326 and after. v2: Uses updated DMA engine prep_slave_sg() interface. See https://lkml.org/lkml/2012/3/8/373 for more details. drivers/rapidio/Kconfig | 14 drivers/rapidio/rio.c | 81 + include/linux/dmaengine.h | 12 +++ include/linux/rio.h | 47 ++ include/linux/rio_drv.h |9 + 5 files changed, 163 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index bc87192..6194d35 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -22,6 +22,20 @@ config RAPIDIO_ENABLE_RX_TX_PORTS ports for Input/Output direction to allow other traffic than Maintenance transfers. +config RAPIDIO_DMA_ENGINE + bool "DMA Engine support for RapidIO" + depends on RAPIDIO + select DMADEVICES + select DMA_ENGINE + help + Say Y here if you want to use DMA Engine frameork for RapidIO data + transfers to/from target RIO devices. RapidIO uses NREAD and + NWRITE (NWRITE_R, SWRITE) requests to transfer data between local + memory and memory on remote target device. You need a DMA controller + capable to perform data transfers to/from RapidIO. + + If you are unsure about this, say Y here. + config RAPIDIO_DEBUG bool "RapidIO subsystem debug messages" depends on RAPIDIO diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 86c9a09..c40665a 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1121,6 +1121,87 @@ int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, return 0; } +#ifdef CONFIG_RAPIDIO_DMA_ENGINE + +static bool rio_chan_filter(struct dma_chan *chan, void *arg) +{ + struct rio_dev *rdev = arg; + + /* Check that DMA device belongs to the right MPORT */ + return (rdev->net->hport == + container_of(chan->device, struct rio_mport, dma)); +} + +/** + * rio_request_dma - request RapidIO capable DMA channel that supports + * specified target RapidIO device. + * @rdev: RIO device control structure + * + * Returns pointer to allocated DMA channel or NULL if failed. + */ +struct dma_chan *rio_request_dma(struct rio_dev *rdev) +{ + dma_cap_mask_t mask; + struct dma_chan *dchan; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dchan = dma_request_channel(mask, rio_chan_filter, rdev); + + return dchan; +} +EXPORT_SYMBOL_GPL(rio_request_dma); + +/** + * rio_release_dma - release specified DMA channel + * @dchan: DMA channel to release + */ +void rio_release_dma(struct dma_chan *dchan) +{ + dma_release_channel(dchan); +} +EXPORT_SYMBOL_GPL(rio_release_dma); + +/** + * rio_dma_prep_slave_sg - RapidIO specific wrapper + * for device_prep_slave_sg callback defined by DMAENGINE. + * @rdev: RIO device control structure + * @dchan: DMA channel to configure + * @data: RIO specific data descriptor + * @direction: DMA data transfer direction (TO or FROM the device) + * @flags: dmaengine defined flags + * + * Initializes RapidIO capable DMA channel for the specified data transfer. + * Uses DMA channel private extension to pass information related to remote + * target RIO device. + * Returns pointer to DMA transaction descriptor or NULL if failed. + */ +struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, + struct dma_chan *dchan, struct rio_dma_data *data, + enum dma_transfer_direction direction, unsigned long flags) +{ + struct dma_async_tx_descriptor *txd = NULL; + struct rio_dma_ext rio_ext; + + if (dchan->device->device_prep_slave_sg == NULL) { + pr_err("%s: prep_rio_sg == NULL\n", __func__); + return NULL; + } + + rio_ext.destid = rdev->destid; + rio_ext.rio_addr_u = data->rio_addr_u; + rio_ext.rio_addr = data->rio_addr; + rio_ext.wr_type = data->wr_type; + + txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, + direction, flags, &rio_ext); + + return txd; +} +EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); + +#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ + static void rio_fixup_device(struct rio_dev *dev) { } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 676f967..3596a3a 100644 --- a/include/linux/dmaengine.h +++ b/
[PATCH] rapidio/tsi721: fix bug in inbound doorbell handler
Fixes queue wrapping bug in Inbound Doorbell handling routine. Signed-off-by: Alexandre Bounine Cc: Chul Kim Cc: Matt Porter --- This patch is applicable to kernel version 3.2 and after. drivers/rapidio/devices/tsi721.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index babbede..c746e26 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -406,13 +406,14 @@ static void tsi721_db_dpc(struct work_struct *work) */ mport = priv->mport; - wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)); - rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)); + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE; while (wr_ptr != rd_ptr) { idb_entry = (u64 *)(priv->idb_base + (TSI721_IDB_ENTRY_SIZE * rd_ptr)); rd_ptr++; + rd_ptr %= IDB_QSIZE; idb.msg = *idb_entry; *idb_entry = 0; -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC] dmaengine/dma_slave: add context parameter to prep_slave_sg callback
As we agreed during our discussion about adding DMA Engine support for RapidIO subsystem, RapidIO and similar clients may benefit from adding an extra context parameter to device_prep_slave_sg() callback. See https://lkml.org/lkml/2011/10/24/275 for more details. Adding the context parameter will allow to pass client/target specific information associated with an individual data transfer request. In the case of RapidIO support this additional information consists of target destination ID and its buffer address (which is not mapped into the local CPU memory space). Because a single RapidIO-capable DMA channel may queue data transfer requests to different target devices, the per-request configuration is required. The proposed change eliminates need for new subsystem-specific API. Existing DMA_SLAVE clients will ignore the new parameter. This RFC only demonstrates the API change and does not include corresponding changes to existing DMA_SLAVE clients. Complete set of patches will be provided after (if) this API change is accepted. Signed-off-by: Alexandre Bounine Cc: Jassi Brar Cc: Russell King Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang --- include/linux/dmaengine.h |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 679b349..79d71bb 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -575,7 +575,7 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_transfer_direction direction, - unsigned long flags); + unsigned long flags, void *context); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction); @@ -607,12 +607,13 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, void *buf, size_t len, - enum dma_transfer_direction dir, unsigned long flags) + enum dma_transfer_direction dir, unsigned long flags, void *context) { struct scatterlist sg; sg_init_one(&sg, buf, len); - return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); + return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags, + context); } static inline int dmaengine_terminate_all(struct dma_chan *chan) -- 1.7.8.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH RESEND] rapidio/tsi721: modify PCIe capability settings
Modify initialization of PCIe capability registers in Tsi721 mport driver: - change Completion Timeout value to avoid unexpected data transfer aborts during intensive traffic. - replace hardcoded offset of PCIe capability block by getting it using the common function. This patch is applicable to kernel versions starting from 3.2-rc1. Signed-off-by: Alexandre Bounine --- [Resending this patch with updated commit comment] drivers/rapidio/devices/tsi721.c | 20 +++- drivers/rapidio/devices/tsi721.h |2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 83ac8728..691b1ab 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2154,7 +2154,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i; + int i, cap; int err; u32 regval; @@ -2262,10 +2262,20 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Unable to set consistent DMA mask\n"); } - /* Clear "no snoop" and "relaxed ordering" bits. */ - pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, ®val); - regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN); - pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval); + cap = pci_pcie_cap(pdev); + BUG_ON(cap == 0); + + /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, ®val); + regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN | + PCI_EXP_DEVCTL_NOSNOOP_EN); + regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT; + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval); + + /* Adjust PCIe completion timeout. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, ®val); + regval &= ~(0x0f); + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2); /* * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 58be4de..822e54c 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -72,6 +72,8 @@ #define TSI721_MSIXPBA_OFFSET 0x2a000 #define TSI721_PCIECFG_EPCTL 0x400 +#define MAX_READ_REQUEST_SZ_SHIFT 12 + /* * Event Management Registers */ -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH RESEND] rapidio/tsi721: Fix mailbox resource reporting
Bug fix for Tsi721 RapidIO mport driver: Tsi721 supports four RapidIO mailboxes (MBOX0 - MBOX3) as defined by RapidIO specification. Mailbox resources has to be properly reported to allow use of all available mailboxes (initial version reports only MBOX0). This patch is applicable to kernel versions staring from 3.2-rc1. Signed-off-by: Alexandre Bounine --- [Resending this patch with updated commit comment] drivers/rapidio/devices/tsi721.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 514c28c..83ac8728 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2107,8 +2107,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) INIT_LIST_HEAD(&mport->dbells); rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0x); - rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); - rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); + rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); + rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); strcpy(mport->name, "Tsi721 mport"); /* Hook up interrupt handler */ -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: Fix mailbox resource reporting
Report support of four RapidIO mailboxes (MBOX0 - MBOX3) instead of MBOX0 only. Signed-off-by: Alexandre Bounine --- drivers/rapidio/devices/tsi721.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 514c28c..83ac8728 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2107,8 +2107,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) INIT_LIST_HEAD(&mport->dbells); rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0x); - rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); - rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); + rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); + rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); strcpy(mport->name, "Tsi721 mport"); /* Hook up interrupt handler */ -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: modify PCIe capability settings
Change Completion Timeout Value to avoid data transfer aborts during intensive data transfers. Remove hardcoded offset for PCIe capability registers. Signed-off-by: Alexandre Bounine --- drivers/rapidio/devices/tsi721.c | 20 +++- drivers/rapidio/devices/tsi721.h |2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 83ac8728..691b1ab 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2154,7 +2154,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i; + int i, cap; int err; u32 regval; @@ -2262,10 +2262,20 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "Unable to set consistent DMA mask\n"); } - /* Clear "no snoop" and "relaxed ordering" bits. */ - pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, ®val); - regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN); - pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval); + cap = pci_pcie_cap(pdev); + BUG_ON(cap == 0); + + /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, ®val); + regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN | + PCI_EXP_DEVCTL_NOSNOOP_EN); + regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT; + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval); + + /* Adjust PCIe completion timeout. */ + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, ®val); + regval &= ~(0x0f); + pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2); /* * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 58be4de..822e54c 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h @@ -72,6 +72,8 @@ #define TSI721_MSIXPBA_OFFSET 0x2a000 #define TSI721_PCIECFG_EPCTL 0x400 +#define MAX_READ_REQUEST_SZ_SHIFT 12 + /* * Event Management Registers */ -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] rapidio/tsi721: switch to dma_zalloc_coherent
Replaces pair dma_alloc_coherent()+memset() with new dma_zalloc_coherent() added by Andrew Morton for kernel version 3.2 Signed-off-by: Alexandre Bounine --- drivers/rapidio/devices/tsi721.c | 17 - 1 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 5225930..514c28c 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -851,14 +851,12 @@ static int tsi721_doorbell_init(struct tsi721_device *priv) INIT_WORK(&priv->idb_work, tsi721_db_dpc); /* Allocate buffer for inbound doorbells queue */ - priv->idb_base = dma_alloc_coherent(&priv->pdev->dev, + priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE, &priv->idb_dma, GFP_KERNEL); if (!priv->idb_base) return -ENOMEM; - memset(priv->idb_base, 0, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE); - dev_dbg(&priv->pdev->dev, "Allocated IDB buffer @ %p (phys = %llx)\n", priv->idb_base, (unsigned long long)priv->idb_dma); @@ -904,7 +902,7 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) */ /* Allocate space for DMA descriptors */ - bd_ptr = dma_alloc_coherent(&priv->pdev->dev, + bd_ptr = dma_zalloc_coherent(&priv->pdev->dev, bd_num * sizeof(struct tsi721_dma_desc), &bd_phys, GFP_KERNEL); if (!bd_ptr) @@ -913,8 +911,6 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) priv->bdma[chnum].bd_phys = bd_phys; priv->bdma[chnum].bd_base = bd_ptr; - memset(bd_ptr, 0, bd_num * sizeof(struct tsi721_dma_desc)); - dev_dbg(&priv->pdev->dev, "DMA descriptors @ %p (phys = %llx)\n", bd_ptr, (unsigned long long)bd_phys); @@ -922,7 +918,7 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ? bd_num : TSI721_DMA_MINSTSSZ; sts_size = roundup_pow_of_two(sts_size); - sts_ptr = dma_alloc_coherent(&priv->pdev->dev, + sts_ptr = dma_zalloc_coherent(&priv->pdev->dev, sts_size * sizeof(struct tsi721_dma_sts), &sts_phys, GFP_KERNEL); if (!sts_ptr) { @@ -938,8 +934,6 @@ static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) priv->bdma[chnum].sts_base = sts_ptr; priv->bdma[chnum].sts_size = sts_size; - memset(sts_ptr, 0, sts_size); - dev_dbg(&priv->pdev->dev, "desc status FIFO @ %p (phys = %llx) size=0x%x\n", sts_ptr, (unsigned long long)sts_phys, sts_size); @@ -1400,7 +1394,7 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, /* Outbound message descriptor status FIFO allocation */ priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1); - priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev, + priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev, priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts), &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL); @@ -1412,9 +1406,6 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id, goto out_desc; } - memset(priv->omsg_ring[mbox].sts_base, 0, - entries * sizeof(struct tsi721_dma_sts)); - /* * Configure Outbound Messaging Engine */ -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC PATCH 2/2 -mm] RapidIO: TSI721 Add DMA Engine support
Adds support for DMA Engine API. Includes following changes: - Modifies BDMA register offset definitions to support per-channel handling - Separates BDMA channel reserved for RIO Maintenance requests - Adds DMA Engine callback routines Signed-off-by: Alexandre Bounine Cc: Vinod Koul Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/devices/Kconfig |8 + drivers/rapidio/devices/Makefile |1 + drivers/rapidio/devices/tsi721.c | 201 ++ drivers/rapidio/devices/tsi721.h | 107 - drivers/rapidio/devices/tsi721_dma.c | 802 ++ 5 files changed, 1029 insertions(+), 90 deletions(-) create mode 100644 drivers/rapidio/devices/tsi721_dma.c diff --git a/drivers/rapidio/devices/Kconfig b/drivers/rapidio/devices/Kconfig index 12a9d7f..3a2db3d 100644 --- a/drivers/rapidio/devices/Kconfig +++ b/drivers/rapidio/devices/Kconfig @@ -8,3 +8,11 @@ config RAPIDIO_TSI721 default "n" ---help--- Include support for IDT Tsi721 PCI Express Serial RapidIO controller. + +config TSI721_DMA + bool "IDT Tsi721 RapidIO DMA support" + depends on RAPIDIO_TSI721 + default "n" + select RAPIDIO_DMA_ENGINE + help + Enable DMA support for IDT Tsi721 PCIe-to-SRIO controller. diff --git a/drivers/rapidio/devices/Makefile b/drivers/rapidio/devices/Makefile index 3b7b4e2..8cbce45 100644 --- a/drivers/rapidio/devices/Makefile +++ b/drivers/rapidio/devices/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_RAPIDIO_TSI721) += tsi721.o +obj-$(CONFIG_TSI721_DMA) += tsi721_dma.o diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 5225930..5e893a6 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -108,6 +108,7 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, u16 destid, u8 hopcount, u32 offset, int len, u32 *data, int do_wr) { + void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); struct tsi721_dma_desc *bd_ptr; u32 rd_count, swr_ptr, ch_stat; int i, err = 0; @@ -116,10 +117,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) return -EINVAL; - bd_ptr = priv->bdma[TSI721_DMACH_MAINT].bd_base; + bd_ptr = priv->mdma.bd_base; - rd_count = ioread32( - priv->regs + TSI721_DMAC_DRDCNT(TSI721_DMACH_MAINT)); + rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); /* Initialize DMA descriptor */ bd_ptr[0].type_id = cpu_to_le32((DTYPE2 << 29) | (op << 19) | destid); @@ -134,19 +134,18 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, mb(); /* Start DMA operation */ - iowrite32(rd_count + 2, - priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); - ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + iowrite32(rd_count + 2, regs + TSI721_DMAC_DWRCNT); + ioread32(regs + TSI721_DMAC_DWRCNT); i = 0; /* Wait until DMA transfer is finished */ - while ((ch_stat = ioread32(priv->regs + - TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) { + while ((ch_stat = ioread32(regs + TSI721_DMAC_STS)) + & TSI721_DMAC_STS_RUN) { udelay(1); if (++i >= 500) { dev_dbg(&priv->pdev->dev, "%s : DMA[%d] read timeout ch_status=%x\n", - __func__, TSI721_DMACH_MAINT, ch_stat); + __func__, priv->mdma.ch_id, ch_stat); if (!do_wr) *data = 0x; err = -EIO; @@ -162,13 +161,10 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, __func__, ch_stat); dev_dbg(&priv->pdev->dev, "OP=%d : destid=%x hc=%x off=%x\n", do_wr ? MAINT_WR : MAINT_RD, destid, hopcount, offset); - iowrite32(TSI721_DMAC_INT_ALL, - priv->regs + TSI721_DMAC_INT(TSI721_DMACH_MAINT)); - iowrite32(TSI721_DMAC_CTL_INIT, - priv->regs + TSI721_DMAC_CTL(TSI721_DMACH_MAINT)); + iowrite32(TSI721_DMAC_INT_ALL, regs + TSI721_DMAC_INT); + iowrite32(TSI721_DMAC_CTL_INIT, regs + TSI721_DMAC_CTL); udelay(10); - iowrite32(0, priv->regs + - TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + iowrite32(0, regs + TSI721_DMAC_DWRCNT
[RFC PATCH 1/2] RapidIO: Add DMA Engine support for RIO data transfers
Adds DMA Engine framework support into RapidIO subsystem. Uses DMA Engine DMA_SLAVE interface to generate data transfers to/from remote RapidIO target devices. Uses scatterlist to describe local data buffer and dma_chan.private member to pass target specific information. Supports flat data buffer only for a remote side. Signed-off-by: Alexandre Bounine Cc: Vinod Koul Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang --- drivers/dma/dmaengine.c |4 ++ drivers/rapidio/Kconfig |6 +++ drivers/rapidio/rio.c | 79 + include/linux/dmaengine.h |1 + include/linux/rio.h | 47 ++ include/linux/rio_drv.h |9 + 6 files changed, 146 insertions(+), 0 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index b48967b..11fdc2c 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -699,6 +699,10 @@ int dma_async_device_register(struct dma_device *device) !device->device_prep_dma_cyclic); BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->device_control); + BUG_ON(dma_has_cap(DMA_RAPIDIO, device->cap_mask) && + !device->device_prep_slave_sg); + BUG_ON(dma_has_cap(DMA_RAPIDIO, device->cap_mask) && + !device->device_control); BUG_ON(!device->device_alloc_chan_resources); BUG_ON(!device->device_free_chan_resources); diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index bc87192..c4aa279 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig @@ -34,3 +34,9 @@ config RAPIDIO_DEBUG If you are unsure about this, say N here. source "drivers/rapidio/switches/Kconfig" + +# This option to be turned on by a device selection +config RAPIDIO_DMA_ENGINE + bool + select DMADEVICES + select DMA_ENGINE diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 86c9a09..e5905fc 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1121,6 +1121,85 @@ int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, return 0; } +#ifdef CONFIG_RAPIDIO_DMA_ENGINE + +#include + +static bool rio_chan_filter(struct dma_chan *chan, void *arg) +{ + struct rio_dev *rdev = arg; + + /* Check that DMA device belongs to the right MPORT */ + return (rdev->net->hport == + container_of(chan->device, struct rio_mport, dma)); +} + +/** + * rio_request_dma - request RapidIO capable DMA channel that supports + * specified target RapidIO device. + * @rdev: RIO device control structure + * + * Returns pointer to allocated DMA channel or NULL if failed. + */ +struct dma_chan *rio_request_dma(struct rio_dev *rdev) +{ + dma_cap_mask_t mask; + struct dma_chan *dchan; + + dma_cap_zero(mask); + dma_cap_set(DMA_RAPIDIO, mask); + dchan = dma_request_channel(mask, rio_chan_filter, rdev); + + return dchan; +} +EXPORT_SYMBOL_GPL(rio_request_dma); + +/** + * rio_release_dma - release specified DMA channel + * @dchan: DMA channel to release + */ +void rio_release_dma(struct dma_chan *dchan) +{ + dma_release_channel(dchan); +} +EXPORT_SYMBOL_GPL(rio_release_dma); + +/** + * rio_dma_prep_slave_sg - RapidIO specific wrapper + * for device_prep_slave_sg callback defined by DMAENGINE. + * @rdev: RIO device control structure + * @dchan: DMA channel to configure + * @data: RIO specific data descriptor + * @direction: DMA data transfer direction (TO or FROM the device) + * @flags: dmaengine defined flags + * + * Initializes RapidIO capable DMA channel for the specified data transfer. + * Uses DMA channel private extension to pass information related to remote + * target RIO device. + * Returns pointer to DMA transaction descriptor or NULL if failed. + */ +struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, + struct dma_chan *dchan, struct rio_dma_data *data, + enum dma_data_direction direction, unsigned long flags) +{ + struct dma_async_tx_descriptor *txd = NULL; + struct rio_dma_ext rio_ext; + + rio_ext.destid = rdev->destid; + rio_ext.rio_addr_u = data->rio_addr_u; + rio_ext.rio_addr = data->rio_addr; + rio_ext.wr_type = data->wr_type; + dchan->private = &rio_ext; + + txd = dchan->device->device_prep_slave_sg(dchan, data->sg, data->sg_len, + direction, flags); + + return txd; +} +EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); + +#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ + static void rio_fixup_device(struct rio_dev *dev) { } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 8fbf40e..867b685 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -70,6 +70,7 @@ enum dma
[PATCH] RapidIO: documentation update
Update rapidio.txt to reflect changes from recent patch. See http://marc.info/?l=linux-kernel&m=131285620113589&w=2 for details. Signed-off-by: Alexandre Bounine Cc: Liu Gang --- Documentation/rapidio/rapidio.txt |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt index be70ee1..c75694b 100644 --- a/Documentation/rapidio/rapidio.txt +++ b/Documentation/rapidio/rapidio.txt @@ -144,7 +144,7 @@ and the default device ID in order to access the device on the active port. After the host has completed enumeration of the entire network it releases devices by clearing device ID locks (calls rio_clear_locks()). For each endpoint -in the system, it sets the Master Enable bit in the Port General Control CSR +in the system, it sets the Discovered bit in the Port General Control CSR to indicate that enumeration is completed and agents are allowed to execute passive discovery of the network. -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] RapidIO, rionet: Fix ethernet address macros for LE platforms
Modify Ethernet addess macros to be compatible with BE/LE platforms (applicable to kernel versions starting from 2.6.39). Signed-off-by: Alexandre Bounine Cc: Chul Kim Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang --- drivers/net/rionet.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 3bb1311..7145714 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -88,8 +88,8 @@ static struct rio_dev **rionet_active; #define dev_rionet_capable(dev) \ is_rionet_capable(dev->src_ops, dev->dst_ops) -#define RIONET_MAC_MATCH(x)(*(u32 *)x == 0x00010001) -#define RIONET_GET_DESTID(x) (*(u16 *)(x + 4)) +#define RIONET_MAC_MATCH(x)(!memcmp((x), "\00\01\00\01", 4)) +#define RIONET_GET_DESTID(x) ((*((u8 *)x + 4) << 8) | *((u8 *)x + 5)) static int rionet_rx_clean(struct net_device *ndev) { -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] RapidIO: fix potential null deref in rio_setup_device()
The "goto cleanup" path can deference "rswitch" when it is NULL. Reported-by: Dan Carpenter Signed-off-by: Alexandre Bounine Cc: Dan Carpenter Cc: Kumar Gala Cc: Matt Porter Cc: Chul Kim --- drivers/rapidio/rio-scan.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index ebe77dd..5b2cb53 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -516,7 +516,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, return rdev; cleanup: - if (rio_is_switch(rdev)) + if (rswitch) kfree(rswitch->route_table); kfree(rdev); -- 1.7.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm] RapidIO: Tsi721 driver - fixes for the initial release
- address comments made by Andrew Morton, see http://marc.info/?l=linux-kernel&m=131361256714116&w=2 - add spinlock for IB_MSG handler - rename private BDMA channel structure to avoid conflict with DMA engine - fix endianess bug in outbound message interrupt handler Signed-off-by: Alexandre Bounine Cc: Chul Kim Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang --- drivers/rapidio/devices/Kconfig |2 +- drivers/rapidio/devices/tsi721.c | 273 - drivers/rapidio/devices/tsi721.h | 20 ++- 3 files changed, 161 insertions(+), 134 deletions(-) diff --git a/drivers/rapidio/devices/Kconfig b/drivers/rapidio/devices/Kconfig index df0b0c5..12a9d7f 100644 --- a/drivers/rapidio/devices/Kconfig +++ b/drivers/rapidio/devices/Kconfig @@ -4,7 +4,7 @@ config RAPIDIO_TSI721 bool "IDT Tsi721 PCI Express SRIO Controller support" - depends on RAPIDIO && PCI && PCIEPORTBUS + depends on RAPIDIO && PCIEPORTBUS default "n" ---help--- Include support for IDT Tsi721 PCI Express Serial RapidIO controller. diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index dafedc8..5225930 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -136,21 +136,20 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, /* Start DMA operation */ iowrite32(rd_count + 2, priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); - (void)ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); i = 0; /* Wait until DMA transfer is finished */ while ((ch_stat = ioread32(priv->regs + TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) { - udelay(10); - i++; - if (i >= 500) { + udelay(1); + if (++i >= 500) { dev_dbg(&priv->pdev->dev, "%s : DMA[%d] read timeout ch_status=%x\n", __func__, TSI721_DMACH_MAINT, ch_stat); if (!do_wr) *data = 0x; - err = -EFAULT; + err = -EIO; goto err_out; } } @@ -173,7 +172,7 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, udelay(1); if (!do_wr) *data = 0x; - err = -EFAULT; + err = -EIO; goto err_out; } @@ -288,18 +287,15 @@ static void tsi721_pw_dpc(struct work_struct *work) { struct tsi721_device *priv = container_of(work, struct tsi721_device, pw_work); - unsigned long flags; u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; /* Use full size PW message buffer for RIO layer */ /* * Process port-write messages */ - spin_lock_irqsave(&priv->pw_fifo_lock, flags); - while (kfifo_out(&priv->pw_fifo, (unsigned char *)msg_buffer, -TSI721_RIO_PW_MSG_SIZE)) { + while (kfifo_out_spinlocked(&priv->pw_fifo, (unsigned char *)msg_buffer, +TSI721_RIO_PW_MSG_SIZE, &priv->pw_fifo_lock)) { /* Process one message */ - spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); #ifdef DEBUG_PW { u32 i; @@ -315,9 +311,7 @@ static void tsi721_pw_dpc(struct work_struct *work) #endif /* Pass the port-write message to RIO core for processing */ rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); - spin_lock_irqsave(&priv->pw_fifo_lock, flags); } - spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); } /** @@ -457,87 +451,6 @@ static void tsi721_db_dpc(struct work_struct *work) } /** - * tsi721_srio_msix - Tsi721 MSI-X SRIO MAC interrupt handler - * @irq: Linux interrupt number - * @ptr: Pointer to interrupt-specific data (mport structure) - * - * Handles Tsi721 interrupts from SRIO MAC. - */ -static irqreturn_t tsi721_srio_msix(int irq, void *ptr) -{ - struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv; - u32 srio_int; - - /* Service SRIO MAC interrupts */ - srio_int = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT); - if (srio_int & TSI721_RIO_EM_INT_STAT_PW_RX) - tsi721_pw_handler((struct rio_mport *)ptr); - - return IRQ_HANDLED; -} - -/** - * tsi721_sr2pc_ch_msix - Tsi721 MSI-X SR2PC Channel interrupt han
[PATCH] RapidIO: Fix use of non-compatible registers
Replace/remove use of RIO v.1.2 registers/bits that are not forward-compatible with newer versions of RapidIO specification. RapidIO specification v. 1.3 removed Write Port CSR, Doorbell CSR, Mailbox CSR and Mailbox and Doorbell bits of the PEF CAR. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Chul Kim Cc: --- drivers/net/rionet.c | 23 --- drivers/rapidio/rio-scan.c |3 +-- include/linux/rio_regs.h | 18 +- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 86ac38c..3bb1311 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -80,13 +80,13 @@ static int rionet_capable = 1; */ static struct rio_dev **rionet_active; -#define is_rionet_capable(pef, src_ops, dst_ops) \ - ((pef & RIO_PEF_INB_MBOX) &&\ -(pef & RIO_PEF_INB_DOORBELL) &&\ +#define is_rionet_capable(src_ops, dst_ops)\ + ((src_ops & RIO_SRC_OPS_DATA_MSG) &&\ +(dst_ops & RIO_DST_OPS_DATA_MSG) &&\ (src_ops & RIO_SRC_OPS_DOORBELL) &&\ (dst_ops & RIO_DST_OPS_DOORBELL)) #define dev_rionet_capable(dev) \ - is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops) + is_rionet_capable(dev->src_ops, dev->dst_ops) #define RIONET_MAC_MATCH(x)(*(u32 *)x == 0x00010001) #define RIONET_GET_DESTID(x) (*(u16 *)(x + 4)) @@ -282,7 +282,6 @@ static int rionet_open(struct net_device *ndev) { int i, rc = 0; struct rionet_peer *peer, *tmp; - u32 pwdcsr; struct rionet_private *rnet = netdev_priv(ndev); if (netif_msg_ifup(rnet)) @@ -332,13 +331,8 @@ static int rionet_open(struct net_device *ndev) continue; } - /* -* If device has initialized inbound doorbells, -* send a join message -*/ - rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr); - if (pwdcsr & RIO_DOORBELL_AVAIL) - rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN); + /* Send a join message */ + rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN); } out: @@ -492,7 +486,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) { int rc = -ENODEV; - u32 lpef, lsrc_ops, ldst_ops; + u32 lsrc_ops, ldst_ops; struct rionet_peer *peer; struct net_device *ndev = NULL; @@ -515,12 +509,11 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) * on later probes */ if (!rionet_check) { - rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef); rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, &lsrc_ops); rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, &ldst_ops); - if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) { + if (!is_rionet_capable(lsrc_ops, ldst_ops)) { printk(KERN_ERR "%s: local device is not network capable\n", DRV_NAME); diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index ee89358..ebe77dd 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -505,8 +505,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rdev->dev.dma_mask = &rdev->dma_mask; rdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - if ((rdev->pef & RIO_PEF_INB_DOORBELL) && - (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) + if (rdev->dst_ops & RIO_DST_OPS_DOORBELL) rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], 0, 0x); diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index 9026b30..218168a 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -36,12 +36,12 @@ #define RIO_PEF_PROCESSOR 0x2000 /* [I] Processor */ #define RIO_PEF_SWITCH0x1000 /* [I] Switch */ #define RIO_PEF_MULTIPORT 0x0800 /* [VI, 2.1] Multiport */ -#define RIO_PEF_INB_MBOX 0x00f0 /* [II] Mailboxes */ -#define RIO_PEF_INB_MBOX0 0x0080 /* [II] Mailbox 0
[PATCH] RapidIO: Fix default routing initialization
Fix switch initialization to ensure that all switches have default routing disabled. This guarantees that no unexpected RapidIO packets arrive to the default port set by reset and there is no default routing destination until it is properly configured by software. This update also unifies handling of unmapped destinations by tsi57x, IDT Gen1 and IDT Gen2 switches. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll --- drivers/rapidio/switches/idt_gen2.c |9 + drivers/rapidio/switches/idtcps.c |6 ++ drivers/rapidio/switches/tsi57x.c |6 ++ 3 files changed, 21 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index ac2701b..043ee31 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c @@ -95,6 +95,9 @@ idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, else table++; + if (route_port == RIO_INVALID_ROUTE) + route_port = IDT_DEFAULT_ROUTE; + rio_mport_write_config_32(mport, destid, hopcount, LOCAL_RTE_CONF_DESTID_SEL, table); @@ -411,6 +414,12 @@ static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) rdev->rswitch->em_handle = idtg2_em_handler; rdev->rswitch->sw_sysfs = idtg2_sysfs; + if (do_enum) { + /* Ensure that default routing is disabled on startup */ + rio_write_config_32(rdev, + RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE); + } + return 0; } diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c index 3a97107..d06ee2d 100644 --- a/drivers/rapidio/switches/idtcps.c +++ b/drivers/rapidio/switches/idtcps.c @@ -26,6 +26,9 @@ idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, { u32 result; + if (route_port == RIO_INVALID_ROUTE) + route_port = CPS_DEFAULT_ROUTE; + if (table == RIO_GLOBAL_TABLE) { rio_mport_write_config_32(mport, destid, hopcount, RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); @@ -130,6 +133,9 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) /* set TVAL = ~50us */ rio_write_config_32(rdev, rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); + /* Ensure that default routing is disabled on startup */ + rio_write_config_32(rdev, + RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE); } return 0; diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c index d322fa0..10e7ddc 100644 --- a/drivers/rapidio/switches/tsi57x.c +++ b/drivers/rapidio/switches/tsi57x.c @@ -303,6 +303,12 @@ static int tsi57x_switch_init(struct rio_dev *rdev, int do_enum) rdev->rswitch->em_init = tsi57x_em_init; rdev->rswitch->em_handle = tsi57x_em_handler; + if (do_enum) { + /* Ensure that default routing is disabled on startup */ + rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT, + RIO_INVALID_ROUTE); + } + return 0; } -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] RapidIO/mpc85xx: Fix possible mport registration problems.
Fix possible problem with mport registration left non cleared after fsl_rio_setup() exits on link error. Abort mport initialization if registration failed. This patch is applicable to 2.6.39-rc1 only. The problem does not exists for earlier versions. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll --- arch/powerpc/sysdev/fsl_rio.c |4 +++- drivers/rapidio/rio.c |5 +++-- include/linux/rio.h |2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 14232d5..4979853 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1457,7 +1457,6 @@ int fsl_rio_setup(struct platform_device *dev) port->ops = ops; port->priv = priv; port->phys_efptr = 0x100; - rio_register_mport(port); priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); rio_regs_win = priv->regs_win; @@ -1504,6 +1503,9 @@ int fsl_rio_setup(struct platform_device *dev) dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", port->sys_size ? 65536 : 256); + if (rio_register_mport(port)) + goto err; + if (port->host_deviceid >= 0) out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c29719c..86c9a09 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1171,16 +1171,17 @@ static int rio_hdid_setup(char *str) __setup("riohdid=", rio_hdid_setup); -void rio_register_mport(struct rio_mport *port) +int rio_register_mport(struct rio_mport *port) { if (next_portid >= RIO_MAX_MPORTS) { pr_err("RIO: reached specified max number of mports\n"); - return; + return 1; } port->id = next_portid++; port->host_deviceid = rio_get_hdid(port->id); list_add_tail(&port->node, &rio_mports); + return 0; } EXPORT_SYMBOL_GPL(rio_local_get_device_id); diff --git a/include/linux/rio.h b/include/linux/rio.h index 4e37a7c..4d50611 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -396,7 +396,7 @@ union rio_pw_msg { }; /* Architecture and hardware-specific functions */ -extern void rio_register_mport(struct rio_mport *); +extern int rio_register_mport(struct rio_mport *); extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int); -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/1] RapidIO: Add IDT CPS-1432 switch definitions
Signed-off-by: Alexandre Bounine Cc: Matt Porter Cc: Kumar Gala --- drivers/rapidio/switches/idt_gen2.c |1 + include/linux/rio_ids.h |1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index 095016a..ac2701b 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c @@ -418,3 +418,4 @@ DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init); DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init); +DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1432, idtg2_switch_init); diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h index 7410d33..0cee015 100644 --- a/include/linux/rio_ids.h +++ b/include/linux/rio_ids.h @@ -35,6 +35,7 @@ #define RIO_DID_IDTCPS6Q 0x035f #define RIO_DID_IDTCPS10Q 0x035e #define RIO_DID_IDTCPS1848 0x0374 +#define RIO_DID_IDTCPS1432 0x0375 #define RIO_DID_IDTCPS1616 0x0379 #define RIO_DID_IDTVPS1616 0x0377 #define RIO_DID_IDTSPS1616 0x0378 -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm] RapidIO,powerpc/85xx: Fix configuration option
Follows set of patches in -mm tree. Replaces configuration option missed in previous patches. Signed-off-by: Alexandre Bounine --- arch/powerpc/kernel/cpu_setup_fsl_booke.S |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 5c518ad..9136111 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -64,7 +64,7 @@ _GLOBAL(__setup_cpu_e500v2) bl __e500_icache_setup bl __e500_dcache_setup bl __setup_e500_ivors -#ifdef CONFIG_RAPIDIO +#ifdef CONFIG_FSL_RIO /* Ensure that RFXE is set */ mfspr r3,SPRN_HID1 orisr3,r3,HID1_RFXE@h -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] RapidIO: Update MAINTAINERS
Signed-off-by: Alexandre Bounine Cc: Matt Porter --- MAINTAINERS |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6f99e12..f9630d6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5164,6 +5164,7 @@ F:drivers/char/random.c RAPIDIO SUBSYSTEM M: Matt Porter +M: Alexandre Bounine S: Maintained F: drivers/rapidio/ -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/5] RapidIO: Modify configuration to support PCI-SRIO controller
1. Add an option to include RapidIO support if the PCI is available. 2. Add FSL_RIO configuration option to enable controller selection. 3. Add RapidIO support option into x86 and MIPS architectures. Signed-off-by: Alexandre Bounine --- arch/mips/Kconfig| 10 ++ arch/powerpc/Kconfig | 10 +- arch/powerpc/sysdev/Makefile |2 +- arch/x86/Kconfig | 10 ++ drivers/net/rionet.c |4 ++-- drivers/rapidio/rio-sysfs.c |1 + 6 files changed, 33 insertions(+), 4 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f5ecc05..c451163 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2336,6 +2336,16 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" +config RAPIDIO + bool "RapidIO support" + depends on PCI + default n + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + endmenu menu "Executable file formats" diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7d69e9b..9a7628a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -767,11 +767,19 @@ config HAS_RAPIDIO config RAPIDIO bool "RapidIO support" - depends on HAS_RAPIDIO + depends on HAS_RAPIDIO || PCI help If you say Y here, the kernel will include drivers and infrastructure code to support RapidIO interconnect devices. +config FSL_RIO + bool "Freescale Embedded SRIO Controller support" + depends on RAPIDIO && HAS_RAPIDIO + default "n" + ---help--- + Include support for RapidIO controller on Freescale embedded + processors (MPC8548, MPC8641, etc). + source "drivers/rapidio/Kconfig" endmenu diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 9c29734..1e0c933 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_FSL_GTM) += fsl_gtm.o obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o -obj-$(CONFIG_RAPIDIO) += fsl_rio.o +obj-$(CONFIG_FSL_RIO) += fsl_rio.o obj-$(CONFIG_TSI108_BRIDGE)+= tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d5ed94d..11c1dc5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2104,6 +2104,16 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" +config RAPIDIO + bool "RapidIO support" + depends on PCI + default n + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + endmenu diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 44150f2..678e577 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -382,7 +382,7 @@ static void rionet_remove(struct rio_dev *rdev) struct rionet_peer *peer, *tmp; free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? - __ilog2(sizeof(void *)) + 4 : 0); + __fls(sizeof(void *)) + 4 : 0); unregister_netdev(ndev); free_netdev(ndev); @@ -450,7 +450,7 @@ static int rionet_setup_netdev(struct rio_mport *mport) } rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, - mport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0); + mport->sys_size ? __fls(sizeof(void *)) + 4 : 0); if (!rionet_active) { rc = -ENOMEM; goto out; diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 76b4185..e3ebfec 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "rio.h" -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 5/5] RapidIO: remove mport resource reservation from common RIO code
Removes resource reservation from the common sybsystem initialization code and make it part of mport driver initialization. This resolves conflict with resource reservation by device specific mport drivers. Signed-off-by: Alexandre Bounine --- arch/powerpc/sysdev/fsl_rio.c |9 + drivers/rapidio/rio.c | 14 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 7d35a12..f25ad15 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1432,6 +1432,14 @@ int fsl_rio_setup(struct platform_device *dev) port->iores.flags = IORESOURCE_MEM; port->iores.name = "rio_io_win"; + if (request_resource(&iomem_resource, &port->iores) < 0) { + dev_err(&dev->dev, "RIO: Error requesting master port region" + " 0x%016llx-0x%016llx\n", + (u64)port->iores.start, (u64)port->iores.end); + rc = -ENOMEM; + goto err_res; + } + priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0); priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2); priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3); @@ -1536,6 +1544,7 @@ int fsl_rio_setup(struct platform_device *dev) return 0; err: iounmap(priv->regs_win); +err_res: kfree(priv); err_priv: kfree(port); diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 9a7b216..c29719c 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1137,20 +1137,9 @@ static int __devinit rio_init(void) int __devinit rio_init_mports(void) { - int rc = 0; struct rio_mport *port; list_for_each_entry(port, &rio_mports, node) { - if (!request_mem_region(port->iores.start, - resource_size(&port->iores), - port->name)) { - printk(KERN_ERR - "RIO: Error requesting master port region 0x%016llx-0x%016llx\n", - (u64)port->iores.start, (u64)port->iores.end); - rc = -ENOMEM; - goto out; - } - if (port->host_deviceid >= 0) rio_enum_mport(port); else @@ -1159,8 +1148,7 @@ int __devinit rio_init_mports(void) rio_init(); - out: - return rc; + return 0; } device_initcall_sync(rio_init_mports); -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/5] RapidIO: Modify mport ID assignment
Changes mport ID and host destination ID assignment to implement unified method common to all mport drivers. Makes "riohdid=" kernel command line parameter common for all architectures with support for more that one host destination ID assignment. Signed-off-by: Alexandre Bounine --- arch/powerpc/sysdev/fsl_rio.c | 25 - drivers/rapidio/rio.c | 26 ++ include/linux/rio.h |1 + 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 6995907..7d35a12 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1288,28 +1288,6 @@ err_out: return rc; } -static char *cmdline = NULL; - -static int fsl_rio_get_hdid(int index) -{ - /* XXX Need to parse multiple entries in some format */ - if (!cmdline) - return -1; - - return simple_strtol(cmdline, NULL, 0); -} - -static int fsl_rio_get_cmdline(char *s) -{ - if (!s) - return 0; - - cmdline = s; - return 1; -} - -__setup("riohdid=", fsl_rio_get_cmdline); - static inline void fsl_rio_info(struct device *dev, u32 ccsr) { const char *str; @@ -1439,7 +1417,6 @@ int fsl_rio_setup(struct platform_device *dev) rc = -ENOMEM; goto err_port; } - port->id = 0; port->index = 0; priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); @@ -1470,8 +1447,6 @@ int fsl_rio_setup(struct platform_device *dev) priv->dev = &dev->dev; port->ops = ops; - port->host_deviceid = fsl_rio_get_hdid(port->id); - port->priv = priv; port->phys_efptr = 0x100; rio_register_mport(port); diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index f861b72..9a7b216 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -32,6 +32,7 @@ #include "rio.h" static LIST_HEAD(rio_mports); +static unsigned char next_portid; /** * rio_local_get_device_id - Get the base/extended device id for a port @@ -1164,8 +1165,33 @@ int __devinit rio_init_mports(void) device_initcall_sync(rio_init_mports); +static int hdids[RIO_MAX_MPORTS + 1]; + +static int rio_get_hdid(int index) +{ + if (!hdids[0] || hdids[0] <= index || index >= RIO_MAX_MPORTS) + return -1; + + return hdids[index + 1]; +} + +static int rio_hdid_setup(char *str) +{ + (void)get_options(str, ARRAY_SIZE(hdids), hdids); + return 1; +} + +__setup("riohdid=", rio_hdid_setup); + void rio_register_mport(struct rio_mport *port) { + if (next_portid >= RIO_MAX_MPORTS) { + pr_err("RIO: reached specified max number of mports\n"); + return; + } + + port->id = next_portid++; + port->host_deviceid = rio_get_hdid(port->id); list_add_tail(&port->node, &rio_mports); } diff --git a/include/linux/rio.h b/include/linux/rio.h index b6bcb16..4e37a7c 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -24,6 +24,7 @@ #define RIO_NO_HOPCOUNT-1 #define RIO_INVALID_DESTID 0x +#define RIO_MAX_MPORTS 8 #define RIO_MAX_MPORT_RESOURCES16 #define RIO_MAX_DEV_RESOURCES 16 -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/5] RapidIO: Modify subsystem and driver initialization sequence
Subsystem initialization sequence modified to support presence of multiple RapidIO controllers in the system. The new sequence is compatible with initialization of PCI devices. Signed-off-by: Alexandre Bounine --- arch/powerpc/sysdev/fsl_rio.c | 10 +- drivers/net/rionet.c |2 +- drivers/rapidio/rio.c |6 -- include/linux/rio.h |1 - 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 4c28226..6995907 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1575,18 +1575,10 @@ err_ops: static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev, const struct of_device_id *match) { - int rc; printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", dev->dev.of_node->full_name); - rc = fsl_rio_setup(dev); - if (rc) - goto out; - - /* Enumerate all registered ports */ - rc = rio_init_mports(); -out: - return rc; + return fsl_rio_setup(dev); }; static const struct of_device_id fsl_of_rio_rpn_ids[] = { diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 678e577..26afbaa 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -571,5 +571,5 @@ static void __exit rionet_exit(void) rio_unregister_driver(&rionet_driver); } -module_init(rionet_init); +late_initcall(rionet_init); module_exit(rionet_exit); diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d520dba..f861b72 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -1134,8 +1134,6 @@ static int __devinit rio_init(void) return 0; } -device_initcall(rio_init); - int __devinit rio_init_mports(void) { int rc = 0; @@ -1158,10 +1156,14 @@ int __devinit rio_init_mports(void) rio_disc_mport(port); } + rio_init(); + out: return rc; } +device_initcall_sync(rio_init_mports); + void rio_register_mport(struct rio_mport *port) { list_add_tail(&port->node, &rio_mports); diff --git a/include/linux/rio.h b/include/linux/rio.h index efed116..b6bcb16 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -395,7 +395,6 @@ union rio_pw_msg { }; /* Architecture and hardware-specific functions */ -extern int rio_init_mports(void); extern void rio_register_mport(struct rio_mport *); extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/5] RapidIO: Add architecture specific callbacks
Extend number of mport callback functions to eliminate direct linking of architecture specific mport operations. Signed-off-by: Alexandre Bounine --- arch/powerpc/sysdev/fsl_rio.c | 52 +--- drivers/rapidio/rio.c | 38 - include/linux/rio.h | 23 ++ include/linux/rio_drv.h |7 +++-- 4 files changed, 75 insertions(+), 45 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8c6cab0..4c28226 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -482,7 +482,7 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, } /** - * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue + * fsl_add_outb_message - Add message to the MPC85xx outbound message queue * @mport: Master port with outbound message queue * @rdev: Target of outbound message * @mbox: Outbound mailbox @@ -492,8 +492,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, * Adds the @buffer message to the MPC85xx outbound message queue. Returns * %0 on success or %-EINVAL on failure. */ -int -rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, +static int +fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, void *buffer, size_t len) { struct rio_priv *priv = mport->priv; @@ -502,9 +502,8 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, + priv->msg_tx_ring.tx_slot; int ret = 0; - pr_debug - ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n", -rdev->destid, mbox, (int)buffer, len); + pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ +"%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { ret = -EINVAL; @@ -554,8 +553,6 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, return ret; } -EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); - /** * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler * @irq: Linux interrupt number @@ -600,7 +597,7 @@ fsl_rio_tx_handler(int irq, void *dev_instance) } /** - * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox + * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open @@ -610,7 +607,8 @@ fsl_rio_tx_handler(int irq, void *dev_instance) * and enables the outbound message unit. Returns %0 on success and * %-EINVAL or %-ENOMEM on failure. */ -int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) +static int +fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; struct rio_priv *priv = mport->priv; @@ -706,14 +704,14 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr } /** - * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox + * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit * @mbox: Mailbox to close * * Disables the outbound message unit, free all buffers, and * frees the outbound message interrupt. */ -void rio_close_outb_mbox(struct rio_mport *mport, int mbox) +static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) { struct rio_priv *priv = mport->priv; /* Disable inbound message unit */ @@ -770,7 +768,7 @@ fsl_rio_rx_handler(int irq, void *dev_instance) } /** - * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox + * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open @@ -780,7 +778,8 @@ fsl_rio_rx_handler(int irq, void *dev_instance) * and enables the inbound message unit. Returns %0 on success * and %-EINVAL or %-ENOMEM on failure. */ -int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) +static int +fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; struct rio_priv *priv = mport->priv; @@ -844,14 +843,14 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri } /** - * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox + * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit * @mbox: Mailbox to close * * Disables the inbound message
[PATCH 0/5] RapidIO: configuration and initialization changes
This set of patches eliminates RapidIO dependency on PowerPC architecture and makes it available to other architectures (x86 and MIPS). It also enables support of new platform independent RapidIO controllers such as PCI-to-SRIO and PCI Express-to-SRIO. Alexandre Bounine (5): RapidIO: Add architecture specific callbacks RapidIO: Modify configuration to support PCI-SRIO controller RapidIO: Modify subsystem and driver initialization sequence RapidIO: Modify mport ID assignment RapidIO: remove mport resource reservation from common RIO code arch/mips/Kconfig | 10 arch/powerpc/Kconfig | 10 - arch/powerpc/sysdev/Makefile |2 +- arch/powerpc/sysdev/fsl_rio.c | 96 - arch/x86/Kconfig | 10 drivers/net/rionet.c |6 +- drivers/rapidio/rio-sysfs.c |1 + drivers/rapidio/rio.c | 84 --- include/linux/rio.h | 25 --- include/linux/rio_drv.h |7 ++- 10 files changed, 151 insertions(+), 100 deletions(-) -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm V2] rapidio: Add new sysfs attributes
Add new sysfs attributes. 1. Routing information required to to reach the RIO device: destid - device destination ID (real for for endpoint, route for switch) hopcount - hopcount for maintenance requests (switches only) 2. device linking information: lprev - name of device that precedes the given device in the enumeration or discovery order (displayed along with of the port to which it is attached). lnext - names of devices (with corresponding port numbers) that are attached to the given device as next in the enumeration or discovery order (switches only) Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- Documentation/rapidio/sysfs.txt | 17 +-- drivers/rapidio/rio-sysfs.c | 41 ++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Documentation/rapidio/sysfs.txt b/Documentation/rapidio/sysfs.txt index d6d986e..97f71ce 100755 --- a/Documentation/rapidio/sysfs.txt +++ b/Documentation/rapidio/sysfs.txt @@ -36,6 +36,10 @@ device_rev - returns the device revision level asm_did - returns identifier for the assembly containing the device asm_rev - returns revision level of the assembly containing the device asm_vid - returns vendor identifier of the assembly containing the device + destid - returns device destination ID assigned by the enumeration routine + (see 4.1 for switch specific details) + lprev - returns name of previous device (switch) on the path to the device + that that owns this attribute In addition to the files listed above, each device has a binary attribute file that allows read/write access to the device configuration registers using @@ -66,9 +70,16 @@ set by the switch initialization routine during enumeration or discovery process 4.1 Common Switch Attributes - routes - reports switch routing information in "destID port" format. This - attribute reports only valid routing table entries, one line for - each entry. + routes - reports switch routing information in "destID port" format. This +attribute reports only valid routing table entries, one line for +each entry. + destid - device destination ID that defines a route to the switch + hopcount - number of hops on the path to the switch +lnext - returns names of devices linked to the switch except one of a device +linked to the ingress port (reported as "lprev"). This is an array +names with number of lines equal to number of ports in switch. If +a switch port has no attached device, returns "null" instead of +a device name. 4.2 Device-specific Switch Attributes diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index c04dbc7..4dbe360 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -34,6 +34,8 @@ rio_config_attr(device_rev, "0x%08x\n"); rio_config_attr(asm_did, "0x%04x\n"); rio_config_attr(asm_vid, "0x%04x\n"); rio_config_attr(asm_rev, "0x%04x\n"); +rio_config_attr(destid, "0x%04x\n"); +rio_config_attr(hopcount, "0x%02x\n"); static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -53,6 +55,35 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch return (str - buf); } +static ssize_t lprev_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + + return sprintf(buf, "%s\n", + (rdev->prev) ? rio_name(rdev->prev) : "root"); +} + +static ssize_t lnext_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + char *str = buf; + int i; + + if (rdev->pef & RIO_PEF_SWITCH) { + for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) { + if (rdev->rswitch->nextdev[i]) + str += sprintf(str, "%s\n", + rio_name(rdev->rswitch->nextdev[i])); + else + str += sprintf(str, "null\n"); + } + } + + return str - buf; +} + struct device_attribute rio_dev_attrs[] = { __ATTR_RO(did), __ATTR_RO(vid), @@ -60,10 +91,14 @@ struct device_attribute rio_dev_attrs[] = { __ATTR_RO(asm_did), __ATTR_RO(asm_vid), __ATTR_RO(asm_rev), + __ATTR_RO(lprev), + __ATTR_RO(destid), __ATTR_NULL, }; static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL); +static DEVICE_ATTR(lnext, S_IRUGO, lnext_sh
[PATCH] rapidio: Fix sysfs config attribute to access 16MB of maint space
Fixes sysfs config attribute to allow access to entire 16MB maintenance space of RapidIO devices. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-sysfs.c | 12 ++-- include/linux/rio_regs.h|4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index e3ebfec..c04dbc7 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -78,9 +78,9 @@ rio_read_config(struct file *filp, struct kobject *kobj, /* Several chips lock up trying to read undefined config space */ if (capable(CAP_SYS_ADMIN)) - size = 0x20; + size = RIO_MAINT_SPACE_SZ; - if (off > size) + if (off >= size) return 0; if (off + count > size) { size -= off; @@ -148,10 +148,10 @@ rio_write_config(struct file *filp, struct kobject *kobj, loff_t init_off = off; u8 *data = (u8 *) buf; - if (off > 0x20) + if (off >= RIO_MAINT_SPACE_SZ) return 0; - if (off + count > 0x20) { - size = 0x20 - off; + if (off + count > RIO_MAINT_SPACE_SZ) { + size = RIO_MAINT_SPACE_SZ - off; count = size; } @@ -201,7 +201,7 @@ static struct bin_attribute rio_config_attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, }, - .size = 0x20, + .size = RIO_MAINT_SPACE_SZ, .read = rio_read_config, .write = rio_write_config, }; diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index d63dcba..9026b30 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -14,10 +14,12 @@ #define LINUX_RIO_REGS_H /* - * In RapidIO, each device has a 2MB configuration space that is + * In RapidIO, each device has a 16MB configuration space that is * accessed via maintenance transactions. Portions of configuration * space are standardized and/or reserved. */ +#define RIO_MAINT_SPACE_SZ 0x100 /* 16MB of RapidIO mainenance space */ + #define RIO_DEV_ID_CAR 0x00/* [I] Device Identity CAR */ #define RIO_DEV_INFO_CAR 0x04/* [I] Device Information CAR */ #define RIO_ASM_ID_CAR 0x08/* [I] Assembly Identity CAR */ -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] RapidIO: Add new IDT sRIO switches
Add new sRIO switch device IDs and enable a basic support for them. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/switches/idt_gen2.c |2 ++ include/linux/rio_ids.h |2 ++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index dd4b2b7..095016a 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c @@ -416,3 +416,5 @@ static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); +DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init); +DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init); diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h index ee7b6ad..7410d33 100644 --- a/include/linux/rio_ids.h +++ b/include/linux/rio_ids.h @@ -36,5 +36,7 @@ #define RIO_DID_IDTCPS10Q 0x035e #define RIO_DID_IDTCPS1848 0x0374 #define RIO_DID_IDTCPS1616 0x0379 +#define RIO_DID_IDTVPS1616 0x0377 +#define RIO_DID_IDTSPS1616 0x0378 #endif /* LINUX_RIO_IDS_H */ -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 3/4] RapidIO: Use Component Tag for unified switch identification
Change the way how switchid value is set. Local counter variable does not provide unified way to identify switch devices in a system with multiple processors. Using local counter leads to the situation when the same RIO switch has different switch ID for each processor. Replacing local counter with unique portion of the Component Tag provides unified reference to the switch by every processor in the system. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index e655756..467e82b 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -46,7 +46,6 @@ static void rio_init_em(struct rio_dev *rdev); DEFINE_SPINLOCK(rio_global_list_lock); static int next_destid = 0; -static int next_switchid = 0; static int next_net = 0; static int next_comptag = 1; @@ -438,6 +437,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rio_mport_write_config_32(port, destid, hopcount, RIO_COMPONENT_TAG_CSR, next_comptag); rdev->comp_tag = next_comptag++; + } else { + rio_mport_read_config_32(port, destid, hopcount, +RIO_COMPONENT_TAG_CSR, +&rdev->comp_tag); } if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { @@ -461,7 +464,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { rswitch = rdev->rswitch; - rswitch->switchid = next_switchid; + rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; rswitch->port_ok = 0; rswitch->route_table = kzalloc(sizeof(u8)* RIO_MAX_ROUTE_ENTRIES(port->sys_size), @@ -816,7 +819,6 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, return -1; if (rio_is_switch(rdev)) { - next_switchid++; sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, port->host_deviceid, sw_inport, 0); @@ -964,8 +966,6 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, return -1; if (rio_is_switch(rdev)) { - next_switchid++; - /* Associated destid is how we accessed this switch */ rdev->destid = destid; -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 1/4] RapidIO: Add definitions of Component Tag fields
Add definition of the unique device identifier field in the component tag. RIO_CTAG_UDEVID does not take all 32 bits of the component tag value to allow future extensions to the component tag use. Selected size of the RIO_CTAG_UDEVID field (17 bits) is sufficient to accommodate maximum number of endpoints in large RIO network (16-bit id) plus switches. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio.c |2 +- include/linux/rio.h | 10 ++ 2 files changed, 11 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c13289e..cc2a3b7 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -710,7 +710,7 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) u32 err_status, em_perrdet, em_ltlerrdet; int rc, portnum; - rdev = rio_get_comptag(pw_msg->em.comptag, NULL); + rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL); if (rdev == NULL) { /* Device removed or enumeration error */ pr_debug("RIO: %s No matching device for CTag 0x%08x\n", diff --git a/include/linux/rio.h b/include/linux/rio.h index 9b55885..ff681eb 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -66,6 +66,16 @@ #define RIO_PW_MSG_SIZE64 +/* + * A component tag value (stored in the component tag CSR) is used as device's + * unique identifier assigned during enumeration. Besides being used for + * identifying switches (which do not have device ID register), it also is used + * by error management notification and therefore has to be assigned + * to endpoints as well. + */ +#define RIO_CTAG_RESRVD0xfffe /* Reserved */ +#define RIO_CTAG_UDEVID0x0001 /* Unique device identifier */ + extern struct bus_type rio_bus_type; extern struct device rio_bus; extern struct list_head rio_devices; /* list of all devices */ -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 0/4] RapidIO: Misc updates
The following four patches are follow-up to two RapidIO patches that are in the -mm tree now. Alexandre Bounine (4): RapidIO: Add definitions of Component Tag fields RapidIO: Add device object linking into discovery RapidIO: Use Component Tag for unified switch identification RapidIO: Add new sysfs attributes drivers/rapidio/rio-scan.c | 21 - drivers/rapidio/rio-sysfs.c | 39 ++- drivers/rapidio/rio.c |2 +- include/linux/rio.h | 10 ++ 4 files changed, 61 insertions(+), 11 deletions(-) -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 4/4] RapidIO: Add new sysfs attributes
Add new sysfs attributes. 1. Routing information required to to reach the RIO device: destid - device destination ID (real for for endpoint, route for switch) hopcount - hopcount for maintenance requests (switches only) 2. device linking information: lprev - name of device that precedes the given device in the enumeration or discovery order (displayed along with of the port to which it is attached). lnext - names of devices (with corresponding port numbers) that are attached to the given device as next in the enumeration or discovery order (switches only) Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-sysfs.c | 39 ++- 1 files changed, 38 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 76b4185..b8d9eaf 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -33,6 +33,8 @@ rio_config_attr(device_rev, "0x%08x\n"); rio_config_attr(asm_did, "0x%04x\n"); rio_config_attr(asm_vid, "0x%04x\n"); rio_config_attr(asm_rev, "0x%04x\n"); +rio_config_attr(destid, "0x%04x\n"); +rio_config_attr(hopcount, "0x%02x\n"); static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -52,6 +54,33 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch return (str - buf); } +static ssize_t lprev_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + + return sprintf(buf, "%02d %s\n", RIO_GET_PORT_NUM(rdev->swpinfo), + (rdev->prev) ? rio_name(rdev->prev) : "host"); +} + +static ssize_t lnext_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + char *str = buf; + int i; + + if (rdev->pef & RIO_PEF_SWITCH) { + for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) { + if (rdev->rswitch->nextdev[i]) + str += sprintf(str, "%02d %s\n", i, + rio_name(rdev->rswitch->nextdev[i])); + } + } + + return str - buf; +} + struct device_attribute rio_dev_attrs[] = { __ATTR_RO(did), __ATTR_RO(vid), @@ -59,10 +88,14 @@ struct device_attribute rio_dev_attrs[] = { __ATTR_RO(asm_did), __ATTR_RO(asm_vid), __ATTR_RO(asm_rev), + __ATTR_RO(lprev), + __ATTR_RO(destid), __ATTR_NULL, }; static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL); +static DEVICE_ATTR(lnext, S_IRUGO, lnext_show, NULL); +static DEVICE_ATTR(hopcount, S_IRUGO, hopcount_show, NULL); static ssize_t rio_read_config(struct file *filp, struct kobject *kobj, @@ -218,7 +251,9 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) err = device_create_bin_file(&rdev->dev, &rio_config_attr); if (!err && (rdev->pef & RIO_PEF_SWITCH)) { - err = device_create_file(&rdev->dev, &dev_attr_routes); + err |= device_create_file(&rdev->dev, &dev_attr_routes); + err |= device_create_file(&rdev->dev, &dev_attr_lnext); + err |= device_create_file(&rdev->dev, &dev_attr_hopcount); if (!err && rdev->rswitch->sw_sysfs) err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); } @@ -241,6 +276,8 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev) device_remove_bin_file(&rdev->dev, &rio_config_attr); if (rdev->pef & RIO_PEF_SWITCH) { device_remove_file(&rdev->dev, &dev_attr_routes); + device_remove_file(&rdev->dev, &dev_attr_lnext); + device_remove_file(&rdev->dev, &dev_attr_hopcount); if (rdev->rswitch->sw_sysfs) rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); } -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 2/4] RapidIO: Add device object linking into discovery
Add setting links between rio_dev objects into the discovery process. This needed to report device connections on agent (non-host) processors that perform RIO discovery. Originally, these links have been introduced for enumerating host only to support error management. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 11 +++ 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 45d14cd..e655756 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -947,7 +947,7 @@ static int rio_enum_complete(struct rio_mport *port) */ static int __devinit rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, - u8 hopcount) + u8 hopcount, struct rio_dev *prev, int prev_port) { u8 port_num, route_port; struct rio_dev *rdev; @@ -957,6 +957,9 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { /* Add device to the global and bus/net specific list. */ list_add_tail(&rdev->net_list, &net->devices); + rdev->prev = prev; + if (prev && rio_is_switch(prev)) + prev->rswitch->nextdev[prev_port] = rdev; } else return -1; @@ -998,8 +1001,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, if (ndestid == RIO_ANY_DESTID(port->sys_size)) continue; rio_unlock_device(port, destid, hopcount); - if (rio_disc_peer - (net, port, ndestid, hopcount + 1) < 0) + if (rio_disc_peer(net, port, ndestid, + hopcount + 1, rdev, port_num) < 0) return -1; } } @@ -1291,7 +1294,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport) mport->host_deviceid); if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), - 0) < 0) { + 0, NULL, 0) < 0) { printk(KERN_INFO "RIO: master port %d device has failed discovery\n", mport->id); -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 1/2] RapidIO: Use common destid storage for endpoints and switches
Changes code to use one storage location common for switches and endpoints. This eliminates unnecessary device type checks during basic access operations. Logic that assigns destid to RIO devices stays unchanged - as before, switches use an associated destid because they do not have their own. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 84 --- drivers/rapidio/rio.c | 74 --- drivers/rapidio/switches/idt_gen2.c | 93 --- drivers/rapidio/switches/idtcps.c |6 +-- drivers/rapidio/switches/tsi568.c | 13 ++--- drivers/rapidio/switches/tsi57x.c | 56 + include/linux/rio.h |8 +-- include/linux/rio_drv.h | 72 +-- 8 files changed, 141 insertions(+), 265 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 1eb82c4..51f0af2 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -437,9 +437,15 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, next_destid++; } else rdev->destid = rio_get_device_id(port, destid, hopcount); - } else - /* Switch device has an associated destID */ - rdev->destid = RIO_INVALID_DESTID; + + rdev->hopcount = 0xff; + } else { + /* Switch device has an associated destID which +* will be adjusted later +*/ + rdev->destid = destid; + rdev->hopcount = hopcount; + } /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { @@ -450,8 +456,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, if (!rswitch) goto cleanup; rswitch->switchid = next_switchid; - rswitch->hopcount = hopcount; - rswitch->destid = destid; rswitch->port_ok = 0; rswitch->route_table = kzalloc(sizeof(u8)* RIO_MAX_ROUTE_ENTRIES(port->sys_size), @@ -632,8 +636,7 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) /** * rio_route_add_entry- Add a route entry to a switch routing table - * @mport: Master port to send transaction - * @rswitch: Switch device + * @rdev: RIO device * @table: Routing table ID * @route_destid: Destination ID to be routed * @route_port: Port number to be routed @@ -647,31 +650,31 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) * on failure. */ static int -rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, +rio_route_add_entry(struct rio_dev *rdev, u16 table, u16 route_destid, u8 route_port, int lock) { int rc; if (lock) { - rc = rio_lock_device(mport, rswitch->destid, -rswitch->hopcount, 1000); + rc = rio_lock_device(rdev->net->hport, rdev->destid, +rdev->hopcount, 1000); if (rc) return rc; } - rc = rswitch->add_entry(mport, rswitch->destid, - rswitch->hopcount, table, - route_destid, route_port); + rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid, + rdev->hopcount, table, + route_destid, route_port); if (lock) - rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); + rio_unlock_device(rdev->net->hport, rdev->destid, + rdev->hopcount); return rc; } /** * rio_route_get_entry- Read a route entry in a switch routing table - * @mport: Master port to send transaction - * @rswitch: Switch device + * @rdev: RIO device * @table: Routing table ID * @route_destid: Destination ID to be routed * @route_port: Pointer to read port number into @@ -685,23 +688,24 @@ rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, * on failure. */ static int -rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, +rio_route_get_entry(struct rio_dev *rdev, u16 table, u16 route_destid, u8 *route_port, int lock) { int rc; if (lock) { - rc = rio_lock_device(mport, rswitch->destid, -rswitch->hopcount, 1000); + rc = rio
[PATCH -mm 2/2] RapidIO: Integrate rio_switch into rio_dev
Convert RIO switches device structures (rio_dev + rio_switch) into a single allocation unit. This change is based on the fact that RIO switches are using common RIO device objects anyway. Allocating RIO switch objects as RIO devices with added space for switch information simplifies handling of RIO switch devices. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 59 +-- drivers/rapidio/rio-sysfs.c |4 +- include/linux/rio.h | 82 +- 3 files changed, 75 insertions(+), 70 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 51f0af2..45d14cd 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -378,12 +378,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, struct rio_dev *rdev; struct rio_switch *rswitch = NULL; int result, rdid; + size_t size; + u32 swpinfo = 0; - rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); + size = sizeof(struct rio_dev); + if (rio_mport_read_config_32(port, destid, hopcount, +RIO_PEF_CAR, &result)) + return NULL; + + if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { + rio_mport_read_config_32(port, destid, hopcount, +RIO_SWP_INFO_CAR, &swpinfo); + if (result & RIO_PEF_SWITCH) { + size += (RIO_GET_TOTAL_PORTS(swpinfo) * + sizeof(rswitch->nextdev[0])) + sizeof(*rswitch); + } + } + + rdev = kzalloc(size, GFP_KERNEL); if (!rdev) return NULL; rdev->net = net; + rdev->pef = result; + rdev->swpinfo = swpinfo; rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, &result); rdev->did = result >> 16; @@ -397,8 +415,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, &result); rdev->asm_rev = result >> 16; - rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, -&rdev->pef); if (rdev->pef & RIO_PEF_EXT_FEATURES) { rdev->efptr = result & 0x; rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, @@ -408,11 +424,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, hopcount, RIO_EFB_ERR_MGMNT); } - if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { - rio_mport_read_config_32(port, destid, hopcount, -RIO_SWP_INFO_CAR, &rdev->swpinfo); - } - rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, &rdev->src_ops); rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, @@ -449,12 +460,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { - rswitch = kzalloc(sizeof(*rswitch) + - RIO_GET_TOTAL_PORTS(rdev->swpinfo) * - sizeof(rswitch->nextdev[0]), - GFP_KERNEL); - if (!rswitch) - goto cleanup; + rswitch = rdev->rswitch; rswitch->switchid = next_switchid; rswitch->port_ok = 0; rswitch->route_table = kzalloc(sizeof(u8)* @@ -466,15 +472,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); rdid++) rswitch->route_table[rdid] = RIO_INVALID_ROUTE; - rdev->rswitch = rswitch; - rswitch->rdev = rdev; dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, -rdev->rswitch->switchid); +rswitch->switchid); rio_switch_init(rdev, do_enum); - if (do_enum && rdev->rswitch->clr_table) - rdev->rswitch->clr_table(port, destid, hopcount, -RIO_GLOBAL_TABLE); + if (do_enum && rswitch->clr_table) + rswitch->clr_table(port,
[PATCH -mm 0/2] RapidIO: Changes to handling of RIO switches
The following two patches are produced as result of the discussion referenced below: http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-September/085829.html http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-October/086226.html Switches in RapidIO subsystem are presented the same way as endpoints - by using rio_dev structure plus an additional switch-specific extension allocated separately. This separation between two objects describing a RIO switch device also is reflected in the way how RIO address is stored for endpoints and switches. Proposed patches are attempt to address issues brought by differences in endpoint and switch handling in RapidIO subsystem. 1. Using one storage location common for switches and endpoints eliminates unnecessary device type checks during maintenance access operations. While destination IDs and hop counts have different meaning for endpoints and switches, this does not prevent us from storing them in the primary RIO device structure (rio_dev) for both types. The logic that assigns destination IDs to RIO devices stays unchanged - as before, switches use an associated destination ID because they do not have their own physical ID. The hop_count is set to 0xff for endpoints and to the actual value for switches. 2. Convert RIO switch device structures (rio_dev + rio_switch) into single allocation unit. This change is based on the fact that RIO switches are using common RIO device objects anyway. Allocating RIO switch objects as RIO devices with added space for switch information simplifies handling of RIO switch device objects. Alexandre Bounine (2): RapidIO: Use common destid storage for endpoints and switches RapidIO: Integrate rio_switch into rio_dev drivers/rapidio/rio-scan.c | 139 ++- drivers/rapidio/rio-sysfs.c |4 +- drivers/rapidio/rio.c | 74 ++- drivers/rapidio/switches/idt_gen2.c | 93 --- drivers/rapidio/switches/idtcps.c |6 +- drivers/rapidio/switches/tsi568.c | 13 +-- drivers/rapidio/switches/tsi57x.c | 56 ++ include/linux/rio.h | 90 +++ include/linux/rio_drv.h | 72 +++--- 9 files changed, 214 insertions(+), 333 deletions(-) -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 2/2] RapidIO: Fix destructive port EM initialization for Tsi568
Replaces possibly damaging broadcast writes into the per-port SP_MODE registers with individual writes for each port. This will preserve individual port configurations in case if ports are configured differently. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/switches/tsi568.c | 15 ++- 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c index f7fd789..b9a389b 100644 --- a/drivers/rapidio/switches/tsi568.c +++ b/drivers/rapidio/switches/tsi568.c @@ -29,7 +29,7 @@ #define SPP_ROUTE_CFG_DESTID(n)(0x11070 + 0x100*n) #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) -#define TSI568_SP_MODE_BC 0x10004 +#define TSI568_SP_MODE(n) (0x11004 + 0x100*n) #define TSI568_SP_MODE_PW_DIS 0x0800 static int @@ -117,14 +117,19 @@ tsi568_em_init(struct rio_dev *rdev) u16 destid = rdev->rswitch->destid; u8 hopcount = rdev->rswitch->hopcount; u32 regval; + int portnum; pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount); /* Make sure that Port-Writes are disabled (for all ports) */ - rio_mport_read_config_32(mport, destid, hopcount, - TSI568_SP_MODE_BC, ®val); - rio_mport_write_config_32(mport, destid, hopcount, - TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS); + for (portnum = 0; +portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { + rio_mport_read_config_32(mport, destid, hopcount, + TSI568_SP_MODE(portnum), ®val); + rio_mport_write_config_32(mport, destid, hopcount, + TSI568_SP_MODE(portnum), + regval | TSI568_SP_MODE_PW_DIS); + } return 0; } -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm 1/2] RapidIO: Fix maximum port number in tsi57x EM initialization
Replace hardcoded maximum port number with actual reported number of switch ports. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Micha Nelissen --- drivers/rapidio/switches/tsi57x.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c index d9e9492..2003fb6 100644 --- a/drivers/rapidio/switches/tsi57x.c +++ b/drivers/rapidio/switches/tsi57x.c @@ -166,7 +166,8 @@ tsi57x_em_init(struct rio_dev *rdev) pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount); - for (portnum = 0; portnum < 16; portnum++) { + for (portnum = 0; +portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { /* Make sure that Port-Writes are enabled (for all ports) */ rio_mport_read_config_32(mport, destid, hopcount, TSI578_SP_MODE(portnum), ®val); -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH -mm] RapidIO: fix IDLE2 bits corruption
RapidIO spec v.2.1 adds Idle Sequence 2 into LP-Serial Physical Layer. The fix ensures that corresponding bits are not corrupted during error handling. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio.c|9 ++--- include/linux/rio_regs.h |3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 7f18a65..68cf0c9 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -871,15 +871,10 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); } - /* Clear remaining error bits */ + /* Clear remaining error bits and Port-Write Pending bit */ rio_mport_write_config_32(mport, destid, hopcount, rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), - err_status & RIO_PORT_N_ERR_STS_CLR_MASK); - - /* Clear Port-Write Pending bit */ - rio_mport_write_config_32(mport, destid, hopcount, - rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), - RIO_PORT_N_ERR_STS_PW_PEND); + err_status); return 0; } diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index a18b2e2..d63dcba 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -229,7 +229,7 @@ #define RIO_MNT_REQ_CMD_IS0x04/* Input-status command */ #define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */ #define RIO_PORT_N_MNT_RSP_RVAL 0x8000 /* Response Valid */ -#define RIO_PORT_N_MNT_RSP_ASTAT 0x03e0 /* ackID Status */ +#define RIO_PORT_N_MNT_RSP_ASTAT 0x07e0 /* ackID Status */ #define RIO_PORT_N_MNT_RSP_LSTAT 0x001f /* Link Status */ #define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */ #define RIO_PORT_N_ACK_CLEAR 0x8000 @@ -243,7 +243,6 @@ #define RIO_PORT_N_ERR_STS_PORT_ERR 0x0004 #define RIO_PORT_N_ERR_STS_PORT_OK0x0002 #define RIO_PORT_N_ERR_STS_PORT_UNINIT0x0001 -#define RIO_PORT_N_ERR_STS_CLR_MASK 0x07120204 #define RIO_PORT_N_CTL_CSR(x) (0x005c + x*0x20) #define RIO_PORT_N_CTL_PWIDTH 0xc000 #define RIO_PORT_N_CTL_PWIDTH_1 0x -- 1.7.3.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 09/10] RapidIO: Add support for IDT CPS Gen2 switches
Add the RIO switch driver and definitions for IDT CPS-1848 and CPS-1616 Gen2 devices. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/switches/Kconfig|7 + drivers/rapidio/switches/Makefile |1 + drivers/rapidio/switches/idt_gen2.c | 447 +++ include/linux/rio_ids.h |2 + include/linux/rio_regs.h|5 + 5 files changed, 462 insertions(+), 0 deletions(-) create mode 100644 drivers/rapidio/switches/idt_gen2.c diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig index 2b4e9b2..f47fee5 100644 --- a/drivers/rapidio/switches/Kconfig +++ b/drivers/rapidio/switches/Kconfig @@ -20,6 +20,13 @@ config RAPIDIO_TSI568 ---help--- Includes support for IDT Tsi568 serial RapidIO switch. +config RAPIDIO_CPS_GEN2 + bool "IDT CPS Gen.2 SRIO switch support" + depends on RAPIDIO + default n + ---help--- + Includes support for ITD CPS Gen.2 serial RapidIO switches. + config RAPIDIO_TSI500 bool "Tsi500 Parallel RapidIO switch support" depends on RAPIDIO diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index fe4adc3..48d67a6 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X)+= tsi57x.o obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o +obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o ifeq ($(CONFIG_RAPIDIO_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c new file mode 100644 index 000..0bb871c --- /dev/null +++ b/drivers/rapidio/switches/idt_gen2.c @@ -0,0 +1,447 @@ +/* + * IDT CPS Gen.2 Serial RapidIO switch family support + * + * Copyright 2010 Integrated Device Technology, Inc. + * Alexandre Bounine + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include "../rio.h" + +#define LOCAL_RTE_CONF_DESTID_SEL 0x010070 +#define LOCAL_RTE_CONF_DESTID_SEL_PSEL 0x001f + +#define IDT_LT_ERR_REPORT_EN 0x03100c + +#define IDT_PORT_ERR_REPORT_EN(n) (0x031044 + (n)*0x40) +#define IDT_PORT_ERR_REPORT_EN_BC 0x03ff04 + +#define IDT_PORT_ISERR_REPORT_EN(n)(0x03104C + (n)*0x40) +#define IDT_PORT_ISERR_REPORT_EN_BC0x03ff0c +#define IDT_PORT_INIT_TX_ACQUIRED 0x0020 + +#define IDT_LANE_ERR_REPORT_EN(n) (0x038010 + (n)*0x100) +#define IDT_LANE_ERR_REPORT_EN_BC 0x03ff10 + +#define IDT_DEV_CTRL_1 0xf2000c +#define IDT_DEV_CTRL_1_GENPW 0x0200 +#define IDT_DEV_CTRL_1_PRSTBEH 0x0001 + +#define IDT_CFGBLK_ERR_CAPTURE_EN 0x020008 +#define IDT_CFGBLK_ERR_REPORT 0xf20014 +#define IDT_CFGBLK_ERR_REPORT_GENPW0x0002 + +#define IDT_AUX_PORT_ERR_CAP_EN0x02 +#define IDT_AUX_ERR_REPORT_EN 0xf20018 +#define IDT_AUX_PORT_ERR_LOG_I2C 0x0002 +#define IDT_AUX_PORT_ERR_LOG_JTAG 0x0001 + +#defineIDT_ISLTL_ADDRESS_CAP 0x021014 + +#define IDT_RIO_DOMAIN 0xf20020 +#define IDT_RIO_DOMAIN_MASK0x00ff + +#define IDT_PW_INFO_CSR0xf20024 + +#define IDT_SOFT_RESET 0xf20040 +#define IDT_SOFT_RESET_REQ 0x00030097 + +#define IDT_I2C_MCTRL 0xf20050 +#define IDT_I2C_MCTRL_GENPW0x0400 + +#define IDT_JTAG_CTRL 0xf2005c +#define IDT_JTAG_CTRL_GENPW0x0002 + +#define IDT_LANE_CTRL(n) (0xff8000 + (n)*0x100) +#define IDT_LANE_CTRL_BC 0x00 +#define IDT_LANE_CTRL_GENPW0x0020 +#define IDT_LANE_DFE_1_BC 0x18 +#define IDT_LANE_DFE_2_BC 0x1c + +#define IDT_PORT_OPS(n)(0xf40004 + (n)*0x100) +#define IDT_PORT_OPS_GENPW 0x0800 +#define IDT_PORT_OPS_PL_ELOG 0x0040 +#define IDT_PORT_OPS_LL_ELOG 0x0020 +#define IDT_PORT_OPS_LT_ELOG 0x0010 +#define IDT_PORT_OPS_BC0xf4ff04 + +#define IDT_PORT_ISERR_DET(n) (0xf40008 + (n)*0x100) + +#define IDT_ERR_CAP0xfd +#define IDT_ERR_CAP_LOG_OVERWR 0x0004 + +#define IDT_ERR_RD 0xfd0004 + +#define IDT_DEFAULT_ROUTE 0xde +#define IDT_NO_ROUTE 0xdf + +static int +idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port) +{ + /* +* Select routing table to update +*/ +
[PATCH v2 05/10] RapidIO: Add default handler for error-stopped state
The default error-stopped state handler provides recovery mechanism as defined by RIO specification. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio.c | 218 +++- drivers/rapidio/switches/idtcps.c | 10 ++ drivers/rapidio/switches/tsi57x.c |4 + include/linux/rio_regs.h |8 +- 4 files changed, 206 insertions(+), 34 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 74e9d22..77bd416 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -495,6 +495,148 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) } /** + * rio_get_input_status - Sends a Link-Request/Input-Status control symbol and + *returns link-response (if requested). + * @rdev: RIO devive to issue Input-status command + * @pnum: Device port number to issue the command + * @lnkresp: Response from a link partner + */ +static int +rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) +{ + struct rio_mport *mport = rdev->net->hport; + u16 destid = rdev->rswitch->destid; + u8 hopcount = rdev->rswitch->hopcount; + u32 regval; + int checkcount; + + if (lnkresp) { + /* Read from link maintenance response register +* to clear valid bit */ + rio_mport_read_config_32(mport, destid, hopcount, + rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), + ®val); + udelay(50); + } + + /* Issue Input-status command */ + rio_mport_write_config_32(mport, destid, hopcount, + rdev->phys_efptr + RIO_PORT_N_MNT_REQ_CSR(pnum), + RIO_MNT_REQ_CMD_IS); + + /* Exit if the response is not expected */ + if (lnkresp == NULL) + return 0; + + checkcount = 3; + while (checkcount--) { + udelay(50); + rio_mport_read_config_32(mport, destid, hopcount, + rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), + ®val); + if (regval & RIO_PORT_N_MNT_RSP_RVAL) { + *lnkresp = regval; + return 0; + } + } + + return -EIO; +} + +/** + * rio_clr_err_stopped - Clears port Error-stopped states. + * @rdev: Pointer to RIO device control structure + * @pnum: Switch port number to clear errors + * @err_status: port error status (if 0 reads register from device) + */ +static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) +{ + struct rio_mport *mport = rdev->net->hport; + u16 destid = rdev->rswitch->destid; + u8 hopcount = rdev->rswitch->hopcount; + struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum]; + u32 regval; + u32 far_ackid, far_linkstat, near_ackid; + + if (err_status == 0) + rio_mport_read_config_32(mport, destid, hopcount, + rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), + &err_status); + + if (err_status & RIO_PORT_N_ERR_STS_PW_OUT_ES) { + pr_debug("RIO_EM: servicing Output Error-Stopped state\n"); + /* +* Send a Link-Request/Input-Status control symbol +*/ + if (rio_get_input_status(rdev, pnum, ®val)) { + pr_debug("RIO_EM: Input-status response timeout\n"); + goto rd_err; + } + + pr_debug("RIO_EM: SP%d Input-status response=0x%08x\n", +pnum, regval); + far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5; + far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT; + rio_mport_read_config_32(mport, destid, hopcount, + rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum), + ®val); + pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval); + near_ackid = (regval & RIO_PORT_N_ACK_INBOUND) >> 24; + pr_debug("RIO_EM: SP%d far_ackID=0x%02x far_linkstat=0x%02x" \ +" near_ackID=0x%02x\n", + pnum, far_ackid, far_linkstat, near_ackid); + + /* +* If required, synchronize ackIDs of near and +* far sides. +*/ + if ((far_ackid != ((regval & RIO_PORT_N_ACK_OUTSTAND) >> 8)) || + (far_ackid != (regval & RIO_PORT_N_ACK_OUTBOUND))) { + /* Align near outstanding/outbound ackIDs with +
[PATCH v2 10/10] RapidIO: Add handling of redundant routes
Detects RIO link to the already enumerated device and properly sets links between device objects. Changes to the enumeration/discovery logic: 1. Use Master Enable bit to signal end of the enumeration - agents may start their discovery process as soon as they see this bit set (Component Tag register was used before for this purpose). 2. Enumerator sets Component Tag (!= 0) immediately during device setup. This allows to identify the device if the redundant route exists in a RIO system. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- arch/powerpc/sysdev/fsl_rio.c |8 drivers/rapidio/rio-scan.c| 88 +--- drivers/rapidio/rio.c | 16 +++ drivers/rapidio/rio.h |1 + include/linux/rio.h |2 + 5 files changed, 64 insertions(+), 51 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 551e8e2..91b7b89 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -50,6 +50,7 @@ #define RIO_ATMU_REGS_OFFSET 0x10c00 #define RIO_P_MSG_REGS_OFFSET 0x11000 #define RIO_S_MSG_REGS_OFFSET 0x13000 +#define RIO_GCCSR 0x13c #define RIO_ESCSR 0x158 #define RIO_CCSR 0x15c #define RIO_LTLEDCSR 0x0608 @@ -1456,6 +1457,7 @@ int fsl_rio_setup(struct platform_device *dev) port->host_deviceid = fsl_rio_get_hdid(port->id); port->priv = priv; + port->phys_efptr = 0x100; rio_register_mport(port); priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); @@ -1503,6 +1505,12 @@ int fsl_rio_setup(struct platform_device *dev) dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", port->sys_size ? 65536 : 256); + if (port->host_deviceid >= 0) + out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | + RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); + else + out_be32(priv->regs_win + RIO_GCCSR, 0x); + priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win + RIO_ATMU_REGS_OFFSET); priv->maint_atmu_regs = priv->atmu_regs + 1; diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index e3efdf9..1eb82c4 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock); static int next_destid = 0; static int next_switchid = 0; static int next_net = 0; -static int next_comptag; +static int next_comptag = 1; static struct timer_list rio_enum_timer = TIMER_INITIALIZER(rio_enum_timeout, 0, 0); @@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port) u32 result; int ret = 0; - /* Assign component tag to all devices */ - next_comptag = 1; - rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++); - - list_for_each_entry(rdev, &rio_devices, global_list) { - /* Mark device as discovered */ - rio_read_config_32(rdev, - rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, - &result); - rio_write_config_32(rdev, - rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, - result | RIO_PORT_GEN_DISCOVERED); - - rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag); - rdev->comp_tag = next_comptag++; - if (next_comptag >= 0x1) { - pr_err("RIO: Component Tag Counter Overflow\n"); - break; - } - } - /* Release host device id locks */ rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, port->host_deviceid); @@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port) rdev->vid, rdev->did); ret = -EINVAL; } + + /* Mark device as discovered and enable master */ + rio_read_config_32(rdev, + rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, + &result); + result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER; + rio_write_config_32(rdev, + rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, + result); } return ret; @@ -430,6 +418,17 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, &
[PATCH v2 04/10] RapidIO: Add relation links between RIO device structures
Create back and forward links between RIO devices. These links are intended for use by error management and hot-plug extensions. Links for redundant RIO connections between switches are not set (will be fixed in a separate patch). Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 56 ++-- include/linux/rio.h|4 +++ 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index d09c359..d2ea018 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -444,7 +444,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { - rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); + rswitch = kzalloc(sizeof(*rswitch) + + RIO_GET_TOTAL_PORTS(rdev->swpinfo) * + sizeof(rswitch->nextdev[0]), + GFP_KERNEL); if (!rswitch) goto cleanup; rswitch->switchid = next_switchid; @@ -723,25 +726,6 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) } /** - * rio_get_swpinfo_tports- Gets total number of ports on the switch - * @mport: Master port to send transaction - * @destid: Destination ID associated with the switch - * @hopcount: Number of hops to the device - * - * Returns total numbers of ports implemented by the switch device. - */ -static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, -u8 hopcount) -{ - u32 result; - - rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, -&result); - - return RIO_GET_TOTAL_PORTS(result); -} - -/** * rio_net_add_mport- Add a master port to a RIO network * @net: RIO network * @port: Master port to add @@ -761,15 +745,16 @@ static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) * @net: RIO network being enumerated * @port: Master port to send transactions * @hopcount: Number of hops into the network + * @prev: Previous RIO device connected to the enumerated one + * @prev_port: Port on previous RIO device * * Recursively enumerates a RIO network. Transactions are sent via the * master port passed in @port. */ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, -u8 hopcount) +u8 hopcount, struct rio_dev *prev, int prev_port) { int port_num; - int num_ports; int cur_destid; int sw_destid; int sw_inport; @@ -814,6 +799,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, if (rdev) { /* Add device to the global and bus/net specific list. */ list_add_tail(&rdev->net_list, &net->devices); + rdev->prev = prev; + if (prev && rio_is_switch(prev)) + prev->rswitch->nextdev[prev_port] = rdev; } else return -1; @@ -832,14 +820,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, rdev->rswitch->route_table[destid] = sw_inport; } - num_ports = - rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size), - hopcount); pr_debug( "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", - rio_name(rdev), rdev->vid, rdev->did, num_ports); + rio_name(rdev), rdev->vid, rdev->did, + RIO_GET_TOTAL_PORTS(rdev->swpinfo)); sw_destid = next_destid; - for (port_num = 0; port_num < num_ports; port_num++) { + for (port_num = 0; +port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); +port_num++) { /*Enable Input Output Port (transmitter reviever)*/ rio_enable_rx_tx_port(port, 0, RIO_ANY_DESTID(port->sys_size), @@ -864,7 +852,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, RIO_ANY_DESTID(port->sys_size), port_num, 0); - if (rio_enum_peer(net, port, hopcount + 1) < 0) + if (rio_enum_peer(net, port, hopcount + 1, +
[PATCH v2 03/10] RapidIO: Use stored ingress port number instead of register read
A switch port information is obtained and stored during RIO device setup. Therefore repeated reads from Switch Port Information CAR may be removed. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c | 36 +--- include/linux/rio.h|4 +++- include/linux/rio_regs.h |2 ++ 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 1123be8..d09c359 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -420,6 +420,11 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, hopcount, RIO_EFB_ERR_MGMNT); } + if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { + rio_mport_read_config_32(port, destid, hopcount, +RIO_SWP_INFO_CAR, &rdev->swpinfo); + } + rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, &rdev->src_ops); rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, @@ -439,8 +444,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, /* If a PE has both switch and other functions, show it as a switch */ if (rio_is_switch(rdev)) { - rio_mport_read_config_32(port, destid, hopcount, -RIO_SWP_INFO_CAR, &rdev->swpinfo); rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); if (!rswitch) goto cleanup; @@ -458,6 +461,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, rdid++) rswitch->route_table[rdid] = RIO_INVALID_ROUTE; rdev->rswitch = rswitch; + rswitch->rdev = rdev; dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, rdev->rswitch->switchid); rio_switch_init(rdev, do_enum); @@ -719,25 +723,6 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) } /** - * rio_get_swpinfo_inport- Gets the ingress port number - * @mport: Master port to send transaction - * @destid: Destination ID associated with the switch - * @hopcount: Number of hops to the device - * - * Returns port number being used to access the switch device. - */ -static u8 -rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) -{ - u32 result; - - rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, -&result); - - return (u8) (result & 0xff); -} - -/** * rio_get_swpinfo_tports- Gets total number of ports on the switch * @mport: Master port to send transaction * @destid: Destination ID associated with the switch @@ -834,8 +819,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, if (rio_is_switch(rdev)) { next_switchid++; - sw_inport = rio_get_swpinfo_inport(port, - RIO_ANY_DESTID(port->sys_size), hopcount); + sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, port->host_deviceid, sw_inport, 0); rdev->rswitch->route_table[port->host_deviceid] = sw_inport; @@ -989,8 +973,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", rio_name(rdev), rdev->vid, rdev->did, num_ports); for (port_num = 0; port_num < num_ports; port_num++) { - if (rio_get_swpinfo_inport(port, destid, hopcount) == - port_num) + if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num) continue; if (rio_sport_is_active @@ -1109,8 +1092,7 @@ static void rio_update_route_tables(struct rio_mport *port) if (rswitch->destid == destid) continue; - sport = rio_get_swpinfo_inport(port, - rswitch->destid, rswitch->hopcount); + sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); if (rswitch->add_entry) { rio_route_add_entry(port, rswitch, diff --git a/include/linux/rio.h b/include/linux/rio.h index 84c9f8c..ffdfe5a 100644 --- a/inc
[PATCH v2 07/10] RapidIO: Add handling of orphan port-write message
Add check for access to port-write (PW) message source device before processing the PW message. If source RIO device is not available (power down or RIO link failure) trace back to a last available switch/port on the PW message route and service failure at that point. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio.c | 113 ++-- drivers/rapidio/rio.h |2 + 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 77bd416..aefc2a0 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -495,6 +495,92 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) } /** + * rio_chk_dev_route - Validate route to the specified device. + * @rdev: RIO device failed to respond + * @nrdev: Last active device on the route to rdev + * @npnum: nrdev's port number on the route to rdev + * + * Follows a route to the specified RIO device to determine the last available + * device (and corresponding RIO port) on the route. + */ +static int +rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) +{ + u32 result; + int p_port, rc = -EIO; + struct rio_dev *prev = NULL; + + /* Find switch with failed RIO link */ + while (rdev->prev && (rdev->prev->pef & RIO_PEF_SWITCH)) { + if (!rio_read_config_32(rdev->prev, RIO_DEV_ID_CAR, &result)) { + prev = rdev->prev; + break; + } + rdev = rdev->prev; + } + + if (prev == NULL) + goto err_out; + + /* Find port with failed RIO link */ + for (p_port = 0; +p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo); p_port++) + if (prev->rswitch->nextdev[p_port] == rdev) + break; + + if (p_port < RIO_GET_TOTAL_PORTS(prev->swpinfo)) { + pr_debug("RIO: link failed on [%s]-P%d\n", +rio_name(prev), p_port); + *nrdev = prev; + *npnum = p_port; + rc = 0; + } else + pr_debug("RIO: failed to trace route to %s\n", rio_name(prev)); +err_out: + return rc; +} + +/** + * rio_mport_chk_dev_access - Validate access to the specified device. + * @mport: Master port to send transactions + * @destid: Device destination ID in network + * @hopcount: Number of hops into the network + */ +static int +rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) +{ + int i = 0; + u32 tmp; + + while (rio_mport_read_config_32(mport, destid, hopcount, + RIO_DEV_ID_CAR, &tmp)) { + i++; + if (i == RIO_MAX_CHK_RETRY) + return -EIO; + mdelay(1); + } + + return 0; +} + +/** + * rio_chk_dev_access - Validate access to the specified device. + * @rdev: Pointer to RIO device control structure + */ +static int rio_chk_dev_access(struct rio_dev *rdev) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_chk_dev_access(rdev->net->hport, destid, hopcount); +} + +/** * rio_get_input_status - Sends a Link-Request/Input-Status control symbol and *returns link-response (if requested). * @rdev: RIO devive to issue Input-status command @@ -654,8 +740,8 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) rdev = rio_get_comptag(pw_msg->em.comptag, NULL); if (rdev == NULL) { - /* Someting bad here (probably enumeration error) */ - pr_err("RIO: %s No matching device for CTag 0x%08x\n", + /* Device removed or enumeration error */ + pr_debug("RIO: %s No matching device for CTag 0x%08x\n", __func__, pw_msg->em.comptag); return -EIO; } @@ -686,6 +772,26 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) return 0; } + portnum = pw_msg->em.is_port & 0xFF; + + /* Check if device and route to it are functional: +* Sometimes devices may send PW message(s) just before being +* powered down (or link being lost). +*/ + if (rio_chk_dev_access(rdev)) { + pr_debug("RIO: device access failed - get link partner\n"); + /* Scan route to the device and identify failed link. +* This will replace device and port reported in PW message. +* PW message should not be u
[PATCH v2 02/10] RapidIO:powerpc/85xx: Modify RIO port-write interrupt handler
- Rearranged RIO port-write interrupt handling to perform message buffering as soon as possible. - Modified to disable port-write controller when clearing Transaction Error (TE) bit. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- arch/powerpc/sysdev/fsl_rio.c | 68 +++- 1 files changed, 39 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 3017532..551e8e2 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -87,6 +87,9 @@ #define RIO_IPWSR_PWD 0x0008 #define RIO_IPWSR_PWB 0x0004 +#define RIO_EPWISR_PINT0x8000 +#define RIO_EPWISR_PW 0x0001 + #define RIO_MSG_DESC_SIZE 32 #define RIO_MSG_BUFFER_SIZE4096 #define RIO_MIN_TX_RING_SIZE 2 @@ -1067,18 +1070,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) struct rio_priv *priv = port->priv; u32 epwisr, tmp; - ipwmr = in_be32(&priv->msg_regs->pwmr); - ipwsr = in_be32(&priv->msg_regs->pwsr); - epwisr = in_be32(priv->regs_win + RIO_EPWISR); - if (epwisr & 0x8000) { - tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); - pr_info("RIO_LTLEDCSR = 0x%x\n", tmp); - out_be32(priv->regs_win + RIO_LTLEDCSR, 0); - } + if (!(epwisr & RIO_EPWISR_PW)) + goto pw_done; - if (!(epwisr & 0x0001)) - return IRQ_HANDLED; + ipwmr = in_be32(&priv->msg_regs->pwmr); + ipwsr = in_be32(&priv->msg_regs->pwsr); #ifdef DEBUG_PW pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); @@ -1094,20 +1091,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) pr_debug(" PWB"); pr_debug(" )\n"); #endif - out_be32(&priv->msg_regs->pwsr, -ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); - - if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { - priv->port_write_msg.err_count++; - pr_info("RIO: Port-Write Transaction Err (%d)\n", -priv->port_write_msg.err_count); - } - if (ipwsr & RIO_IPWSR_PWD) { - priv->port_write_msg.discard_count++; - pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n", -priv->port_write_msg.discard_count); - } - /* Schedule deferred processing if PW was received */ if (ipwsr & RIO_IPWSR_QFI) { /* Save PW message (if there is room in FIFO), @@ -1119,16 +1102,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) RIO_PW_MSG_SIZE); } else { priv->port_write_msg.discard_count++; - pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", + pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", priv->port_write_msg.discard_count); } + /* Clear interrupt and issue Clear Queue command. This allows +* another port-write to be received. +*/ + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_QFI); + out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); + schedule_work(&priv->pw_work); } - /* Issue Clear Queue command. This allows another -* port-write to be received. -*/ - out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); + if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { + priv->port_write_msg.err_count++; + pr_debug("RIO: Port-Write Transaction Err (%d)\n", +priv->port_write_msg.err_count); + /* Clear Transaction Error: port-write controller should be +* disabled when clearing this error +*/ + out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_TE); + out_be32(&priv->msg_regs->pwmr, ipwmr); + } + + if (ipwsr & RIO_IPWSR_PWD) { + priv->port_write_msg.discard_count++; + pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", +priv->port_write_msg.discard_count); + out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD); + } + +pw_done: + if (epwisr & RIO_EPWISR_PINT) { + tmp = in_be32(p
[PATCH v2 06/10] RapidIO: Modify sysfs initialization for switches
1. Change to create attribute "routes" only for switches. 2. Add a switch-specific callback to create/remove proprietary attributes. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio-sysfs.c | 26 +++--- include/linux/rio.h |6 ++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 00b4756..137ed93 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -40,9 +40,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch char *str = buf; int i; - if (!rdev->rswitch) - goto out; - for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); i++) { if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) @@ -52,7 +49,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch rdev->rswitch->route_table[i]); } - out: return (str - buf); } @@ -63,10 +59,11 @@ struct device_attribute rio_dev_attrs[] = { __ATTR_RO(asm_did), __ATTR_RO(asm_vid), __ATTR_RO(asm_rev), - __ATTR_RO(routes), __ATTR_NULL, }; +static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL); + static ssize_t rio_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -218,7 +215,17 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) { int err = 0; - err = sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr); + err = device_create_bin_file(&rdev->dev, &rio_config_attr); + + if (!err && rdev->rswitch) { + err = device_create_file(&rdev->dev, &dev_attr_routes); + if (!err && rdev->rswitch->sw_sysfs) + err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); + } + + if (err) + pr_warning("RIO: Failed to create attribute file(s) for %s\n", + rio_name(rdev)); return err; } @@ -231,5 +238,10 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) */ void rio_remove_sysfs_dev_files(struct rio_dev *rdev) { - sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr); + device_remove_bin_file(&rdev->dev, &rio_config_attr); + if (rdev->rswitch) { + device_remove_file(&rdev->dev, &dev_attr_routes); + if (rdev->rswitch->sw_sysfs) + rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); + } } diff --git a/include/linux/rio.h b/include/linux/rio.h index 8d9e66d..4fa5e3d 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -218,6 +218,10 @@ struct rio_net { unsigned char id; /* RIO network ID */ }; +/* Definitions used by switch sysfs initialization callback */ +#define RIO_SW_SYSFS_CREATE1 /* Create switch attributes */ +#define RIO_SW_SYSFS_REMOVE0 /* Remove switch attributes */ + /** * struct rio_switch - RIO switch info * @node: Node in global list of switches @@ -234,6 +238,7 @@ struct rio_net { * @get_domain: Callback for switch-specific domain get function * @em_init: Callback for switch-specific error management initialization function * @em_handle: Callback for switch-specific error management handler function + * @sw_sysfs: Callback that initializes switch-specific sysfs attributes * @nextdev: Array of per-port pointers to the next attached device */ struct rio_switch { @@ -256,6 +261,7 @@ struct rio_switch { u8 *sw_domain); int (*em_init) (struct rio_dev *dev); int (*em_handle) (struct rio_dev *dev, u8 swport); + int (*sw_sysfs) (struct rio_dev *dev, int create); struct rio_dev *nextdev[0]; }; -- 1.7.0.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 08/10] RapidIO: Add device access check into the enumeration
Add explicit device access check before performing device enumeration. This gives a chance to clear possible link error conditions by issuing safe maintenance read request(s). Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio-scan.c |6 ++ drivers/rapidio/rio.c |2 +- drivers/rapidio/rio.h |2 ++ 3 files changed, 9 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index d2ea018..e3efdf9 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -762,6 +762,12 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, u16 destid; int tmp; + if (rio_mport_chk_dev_access(port, + RIO_ANY_DESTID(port->sys_size), hopcount)) { + pr_debug("RIO: device access check failed\n"); + return -1; + } + if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { pr_debug("RIO: PE already discovered by this host\n"); /* diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index aefc2a0..fa5e3cb 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -546,7 +546,7 @@ err_out: * @destid: Device destination ID in network * @hopcount: Number of hops into the network */ -static int +int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) { int i = 0; diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index bc71ba1..d249a12 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h @@ -24,6 +24,8 @@ extern u32 rio_mport_get_physefb(struct rio_mport *port, int local, u16 destid, u8 hopcount); extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, u8 hopcount, u32 from); +extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, + u8 hopcount); extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); extern int rio_enum_mport(struct rio_mport *mport); extern int rio_disc_mport(struct rio_mport *mport); -- 1.7.0.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 01/10] RapidIO: Fix RapidIO sysfs hierarchy
Make RapidIO devices appear in /sys/devices/rapidio directory instead of top of /sys/devices directory. Signed-off-by: Alexandre Bounine Cc: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala Cc: Micha Nelissen --- drivers/rapidio/rio-driver.c |2 +- drivers/rapidio/rio-scan.c |1 + include/linux/rio.h |1 + 3 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 3222fa3..0f4a53b 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -192,7 +192,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) out:return 0; } -static struct device rio_bus = { +struct device rio_bus = { .init_name = "rapidio", }; diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 8070e07..1123be8 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -478,6 +478,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, } rdev->dev.bus = &rio_bus_type; + rdev->dev.parent = &rio_bus; device_initialize(&rdev->dev); rdev->dev.release = rio_release_dev; diff --git a/include/linux/rio.h b/include/linux/rio.h index bd6eb0e..84c9f8c 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -67,6 +67,7 @@ #define RIO_PW_MSG_SIZE64 extern struct bus_type rio_bus_type; +extern struct device rio_bus; extern struct list_head rio_devices; /* list of all devices */ struct rio_mport; -- 1.7.0.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 0/10] RapidIO: Set of patches to add Gen2 switches
This set of RapidIO patches extends support for standard error recovery mechanism and adds new IDT Gen2 sRIO switch devices - CPS-1848 and CPS-1616. Implementation of the standard error-stopped state recovery mechanism (as defined by the RapidIO specification) is required for the new switches. The version 2 of this set of patches addresses received comments and fixes an error notification setup issue found in the idt_gen2.c after the first version was released. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 9/9] RapidIO: Add support for IDT CPS Gen2 switches
Add the RIO switch driver and definitions for IDT CPS-1848 and CPS-1616 Gen2 devices. Signed-off-by: Alexandre Bounine Reviewed-by: Thomas Moll Cc: Matt Porter Cc: Li Yang Cc: Kumar Gala --- drivers/rapidio/switches/Kconfig|7 + drivers/rapidio/switches/Makefile |1 + drivers/rapidio/switches/idt_gen2.c | 439 +++ include/linux/rio_ids.h |2 + include/linux/rio_regs.h|4 + 5 files changed, 453 insertions(+), 0 deletions(-) create mode 100644 drivers/rapidio/switches/idt_gen2.c diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig index 2b4e9b2..f47fee5 100644 --- a/drivers/rapidio/switches/Kconfig +++ b/drivers/rapidio/switches/Kconfig @@ -20,6 +20,13 @@ config RAPIDIO_TSI568 ---help--- Includes support for IDT Tsi568 serial RapidIO switch. +config RAPIDIO_CPS_GEN2 + bool "IDT CPS Gen.2 SRIO switch support" + depends on RAPIDIO + default n + ---help--- + Includes support for ITD CPS Gen.2 serial RapidIO switches. + config RAPIDIO_TSI500 bool "Tsi500 Parallel RapidIO switch support" depends on RAPIDIO diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index fe4adc3..48d67a6 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X)+= tsi57x.o obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o +obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o ifeq ($(CONFIG_RAPIDIO_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c new file mode 100644 index 000..0de4a9c --- /dev/null +++ b/drivers/rapidio/switches/idt_gen2.c @@ -0,0 +1,439 @@ +/* + * IDT CPS Gen.2 Serial RapidIO switch family support + * + * Copyright 2010 Integrated Device Technology, Inc. + * Alexandre Bounine + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include "../rio.h" + +#define LOCAL_RTE_CONF_DESTID_SEL 0x010070 +#define LOCAL_RTE_CONF_DESTID_SEL_PSEL 0x001f + +#define IDT_LT_ERR_REPORT_EN 0x03100c + +#define IDT_PORT_ERR_REPORT_EN(n) (0x031044 + (n)*0x40) +#define IDT_PORT_ERR_REPORT_EN_BC 0x03ff04 + +#define IDT_PORT_ISERR_REPORT_EN(n)(0x03104C + (n)*0x40) +#define IDT_PORT_ISERR_REPORT_EN_BC0x03ff0c +#define IDT_PORT_INIT_TX_ACQUIRED 0x0020 + +#define IDT_LANE_ERR_REPORT_EN(n) (0x038010 + (n)*0x100) +#define IDT_LANE_ERR_REPORT_EN_BC 0x03ff10 + +#define IDT_DEV_CTRL_1 0xf2000c +#define IDT_DEV_CTRL_1_GENPW 0x0200 +#define IDT_DEV_CTRL_1_PRSTBEH 0x0001 + +#define IDT_CFGBLK_ERR_CAPTURE_EN 0x020008 +#define IDT_CFGBLK_ERR_REPORT 0xf20014 +#define IDT_CFGBLK_ERR_REPORT_GENPW0x0002 + +#define IDT_AUX_PORT_ERR_CAP_EN0x02 +#define IDT_AUX_ERR_REPORT_EN 0xf20018 +#define IDT_AUX_PORT_ERR_LOG_I2C 0x0002 +#define IDT_AUX_PORT_ERR_LOG_JTAG 0x0001 + +#defineIDT_ISLTL_ADDRESS_CAP 0x021014 + +#define IDT_RIO_DOMAIN 0xf20020 +#define IDT_RIO_DOMAIN_MASK0x00ff + +#define IDT_PW_INFO_CSR0xf20024 + +#define IDT_SOFT_RESET 0xf20040 +#define IDT_SOFT_RESET_REQ 0x00030097 + +#define IDT_I2C_MCTRL 0xf20050 +#define IDT_I2C_MCTRL_GENPW0x0400 + +#define IDT_JTAG_CTRL 0xf2005c +#define IDT_JTAG_CTRL_GENPW0x0002 + +#define IDT_LANE_CTRL(n) (0xff8000 + (n)*0x100) +#define IDT_LANE_CTRL_BC 0x00 +#define IDT_LANE_CTRL_GENPW0x0020 +#define IDT_LANE_DFE_1_BC 0x18 +#define IDT_LANE_DFE_2_BC 0x1c + +#define IDT_PORT_OPS(n)(0xf40004 + (n)*0x100) +#define IDT_PORT_OPS_GENPW 0x0800 +#define IDT_PORT_OPS_PL_ELOG 0x0040 +#define IDT_PORT_OPS_LL_ELOG 0x0020 +#define IDT_PORT_OPS_LT_ELOG 0x0010 +#define IDT_PORT_OPS_BC0xf4ff04 + +#define IDT_PORT_ISERR_DET(n) (0xf40008 + (n)*0x100) + +#define IDT_ERR_CAP0xfd +#define IDT_ERR_CAP_LOG_OVERWR 0x0004 + +#define IDT_ERR_RD 0xfd0004 + +#define IDT_DEFAULT_ROUTE 0xde +#define IDT_NO_ROUTE 0xdf + +static int +idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port) +{ + /* +* Select routing table to update +*/ + if (table == RIO_GLOBAL_TA