diff options
Diffstat (limited to 'drivers/staging/fsl-mc')
-rw-r--r-- | drivers/staging/fsl-mc/README.txt | 138 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/TODO | 13 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dpbp.c | 77 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 7 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dpmcp.c | 35 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dpmcp.h | 10 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dprc-cmd.h | 6 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dprc-driver.c | 33 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/dprc.c | 26 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/mc-allocator.c | 79 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/mc-bus.c | 90 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/bus/mc-msi.c | 14 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/include/dpbp-cmd.h | 4 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/include/dpbp.h | 51 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/include/dprc.h | 19 | ||||
-rw-r--r-- | drivers/staging/fsl-mc/include/mc-private.h | 2 |
16 files changed, 360 insertions, 244 deletions
diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt index 8214102f1..179536a9b 100644 --- a/drivers/staging/fsl-mc/README.txt +++ b/drivers/staging/fsl-mc/README.txt @@ -11,11 +11,11 @@ Contents summary -Overview of DPAA2 objects -DPAA2 Linux driver architecture overview -bus driver - -dprc driver + -DPRC driver -allocator - -dpio driver + -DPIO driver -Ethernet - -mac + -MAC DPAA2 Overview -------------- @@ -37,6 +37,9 @@ interfaces, an L2 switch, or accelerator instances. The MC provides memory-mapped I/O command interfaces (MC portals) which DPAA2 software drivers use to operate on DPAA2 objects: +The diagram below shows an overview of the DPAA2 resource management +architecture: + +--------------------------------------+ | OS | | DPAA2 drivers | @@ -77,13 +80,13 @@ DPIO objects. Overview of DPAA2 Objects ------------------------- -The section provides a brief overview of some key objects -in the DPAA2 hardware. A simple scenario is described illustrating -the objects involved in creating a network interfaces. +The section provides a brief overview of some key DPAA2 objects. +A simple scenario is described illustrating the objects involved +in creating a network interfaces. -DPRC (Datapath Resource Container) - A DPRC is an container object that holds all the other + A DPRC is a container object that holds all the other types of DPAA2 objects. In the example diagram below there are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC) in the container. @@ -101,23 +104,23 @@ the objects involved in creating a network interfaces. | | +---------------------------------------------------------+ - From the point of view of an OS, a DPRC is bus-like. Like - a plug-and-play bus, such as PCI, DPRC commands can be used to - enumerate the contents of the DPRC, discover the hardware - objects present (including mappable regions and interrupts). + From the point of view of an OS, a DPRC behaves similar to a plug and + play bus, like PCI. DPRC commands can be used to enumerate the contents + of the DPRC, discover the hardware objects present (including mappable + regions and interrupts). - dprc.1 (bus) + DPRC.1 (bus) | +--+--------+-------+-------+-------+ | | | | | - dpmcp.1 dpio.1 dpbp.1 dpni.1 dpmac.1 - dpmcp.2 dpio.2 - dpmcp.3 + DPMCP.1 DPIO.1 DPBP.1 DPNI.1 DPMAC.1 + DPMCP.2 DPIO.2 + DPMCP.3 Hardware objects can be created and destroyed dynamically, providing the ability to hot plug/unplug objects in and out of the DPRC. - A DPRC has a mappable mmio region (an MC portal) that can be used + A DPRC has a mappable MMIO region (an MC portal) that can be used to send MC commands. It has an interrupt for status events (like hotplug). @@ -137,10 +140,11 @@ the objects involved in creating a network interfaces. A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX queuing mechanisms, configuration mechanisms, buffer management, physical ports, and interrupts. DPAA2 uses a more granular approach - utilizing multiple hardware objects. Each object has specialized - functions, and are used together by software to provide Ethernet network - interface functionality. This approach provides efficient use of finite - hardware resources, flexibility, and performance advantages. + utilizing multiple hardware objects. Each object provides specialized + functions. Groups of these objects are used by software to provide + Ethernet network interface functionality. This approach provides + efficient use of finite hardware resources, flexibility, and + performance advantages. The diagram below shows the objects needed for a simple network interface configuration on a system with 2 CPUs. @@ -168,46 +172,52 @@ the objects involved in creating a network interfaces. Below the objects are described. For each object a brief description is provided along with a summary of the kinds of operations the object - supports and a summary of key resources of the object (mmio regions - and irqs). + supports and a summary of key resources of the object (MMIO regions + and IRQs). -DPMAC (Datapath Ethernet MAC): represents an Ethernet MAC, a hardware device that connects to an Ethernet PHY and allows physical transmission and reception of Ethernet frames. - -mmio regions: none - -irqs: dpni link change + -MMIO regions: none + -IRQs: DPNI link change -commands: set link up/down, link config, get stats, - irq config, enable, reset + IRQ config, enable, reset -DPNI (Datapath Network Interface): contains TX/RX queues, - network interface configuration, and rx buffer pool configuration - mechanisms. - -mmio regions: none - -irqs: link state + network interface configuration, and RX buffer pool configuration + mechanisms. The TX/RX queues are in memory and are identified by + queue number. + -MMIO regions: none + -IRQs: link state -commands: port config, offload config, queue config, - parse/classify config, irq config, enable, reset + parse/classify config, IRQ config, enable, reset -DPIO (Datapath I/O): provides interfaces to enqueue and dequeue - packets and do hardware buffer pool management operations. For - optimum performance there is typically DPIO per CPU. This allows - each CPU to perform simultaneous enqueue/dequeue operations. - -mmio regions: queue operations, buffer mgmt - -irqs: data availability, congestion notification, buffer + packets and do hardware buffer pool management operations. The DPAA2 + architecture separates the mechanism to access queues (the DPIO object) + from the queues themselves. The DPIO provides an MMIO interface to + enqueue/dequeue packets. To enqueue something a descriptor is written + to the DPIO MMIO region, which includes the target queue number. + There will typically be one DPIO assigned to each CPU. This allows all + CPUs to simultaneously perform enqueue/dequeued operations. DPIOs are + expected to be shared by different DPAA2 drivers. + -MMIO regions: queue operations, buffer management + -IRQs: data availability, congestion notification, buffer pool depletion - -commands: irq config, enable, reset + -commands: IRQ config, enable, reset -DPBP (Datapath Buffer Pool): represents a hardware buffer pool. - -mmio regions: none - -irqs: none + -MMIO regions: none + -IRQs: none -commands: enable, reset -DPMCP (Datapath MC Portal): provides an MC command portal. Used by drivers to send commands to the MC to manage objects. - -mmio regions: MC command portal - -irqs: command completion - -commands: irq config, enable, reset + -MMIO regions: MC command portal + -IRQs: command completion + -commands: IRQ config, enable, reset Object Connections ------------------ @@ -268,22 +278,22 @@ of each driver follows. | Stack | +------------+ +------------+ | Allocator |. . . . . . . | Ethernet | - |(dpmcp,dpbp)| | (dpni) | + |(DPMCP,DPBP)| | (DPNI) | +-.----------+ +---+---+----+ . . ^ | . . <data avail, | |<enqueue, . . tx confirm> | | dequeue> +-------------+ . | | | DPRC driver | . +---+---V----+ +---------+ - | (dprc) | . . . . . .| DPIO driver| | MAC | - +----------+--+ | (dpio) | | (dpmac) | + | (DPRC) | . . . . . .| DPIO driver| | MAC | + +----------+--+ | (DPIO) | | (DPMAC) | | +------+-----+ +-----+---+ |<dev add/remove> | | | | | +----+--------------+ | +--+---+ - | mc-bus driver | | | PHY | + | MC-bus driver | | | PHY | | | | |driver| - | /fsl-mc@80c000000 | | +--+---+ + | /soc/fsl-mc | | +--+---+ +-------------------+ | | | | ================================ HARDWARE =========|=================|====== @@ -298,25 +308,27 @@ of each driver follows. A brief description of each driver is provided below. - mc-bus driver + MC-bus driver ------------- - The mc-bus driver is a platform driver and is probed from an - "/fsl-mc@xxxx" node in the device tree passed in by boot firmware. - It is responsible for bootstrapping the DPAA2 kernel infrastructure. + The MC-bus driver is a platform driver and is probed from a + node in the device tree (compatible "fsl,qoriq-mc") passed in by boot + firmware. It is responsible for bootstrapping the DPAA2 kernel + infrastructure. Key functions include: -registering a new bus type named "fsl-mc" with the kernel, and implementing bus call-backs (e.g. match/uevent/dev_groups) - -implemeting APIs for DPAA2 driver registration and for device + -implementing APIs for DPAA2 driver registration and for device add/remove - -creates an MSI irq domain - -do a device add of the 'root' DPRC device, which is needed - to bootstrap things + -creates an MSI IRQ domain + -doing a 'device add' to expose the 'root' DPRC, in turn triggering + a bind of the root DPRC to the DPRC driver DPRC driver ----------- - The dprc-driver is bound DPRC objects and does runtime management + The DPRC driver is bound to DPRC objects and does runtime management of a bus instance. It performs the initial bus scan of the DPRC - and handles interrupts for container events such as hot plug. + and handles interrupts for container events such as hot plug by + re-scanning the DPRC. Allocator ---------- @@ -334,14 +346,20 @@ A brief description of each driver is provided below. DPIO driver ----------- The DPIO driver is bound to DPIO objects and provides services that allow - other drivers such as the Ethernet driver to receive and transmit data. + other drivers such as the Ethernet driver to enqueue and dequeue data for + their respective objects. Key services include: -data availability notifications -hardware queuing operations (enqueue and dequeue of data) -hardware buffer pool management + To transmit a packet the Ethernet driver puts data on a queue and + invokes a DPIO API. For receive, the Ethernet driver registers + a data availability notification callback. To dequeue a packet + a DPIO API is used. + There is typically one DPIO object per physical CPU for optimum - performance, allowing each CPU to simultaneously enqueue + performance, allowing different CPUs to simultaneously enqueue and dequeue data. The DPIO driver operates on behalf of all DPAA2 drivers @@ -362,3 +380,7 @@ A brief description of each driver is provided below. by the appropriate PHY driver via an mdio bus. The MAC driver plays a role of being a proxy between the PHY driver and the MC. It does this proxy via the MC commands to a DPMAC object. + If the PHY driver signals a link change, the MAC driver notifies + the MC via a DPMAC command. If a network interface is brought + up or down, the MC notifies the DPMAC driver via an interrupt and + the driver can take appropriate action. diff --git a/drivers/staging/fsl-mc/TODO b/drivers/staging/fsl-mc/TODO index 389436891..54a8bc692 100644 --- a/drivers/staging/fsl-mc/TODO +++ b/drivers/staging/fsl-mc/TODO @@ -1,21 +1,8 @@ -* Decide if multiple root fsl-mc buses will be supported per Linux instance, - and if so add support for this. - * Add at least one device driver for a DPAA2 object (child device of the fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet driver support, which depends on drivers for several objects: DPNI, DPIO, DPMAC. Other pre-requisites include: - * interrupt support. for meaningful driver support we need - interrupts, and thus need message interrupt support by the bus - driver. - -Note: this has dependencies on generic MSI support work - in process upstream, see [1] and [2]. - - * Management Complex (MC) command serialization. locking mechanisms - are needed by drivers to serialize commands sent to the MC, including - from atomic context. - * MC firmware uprev. The MC firmware upon which the fsl-mc bus driver and DPAA2 object drivers are based is continuing to evolve, so minor updates are needed to keep in sync with binary diff --git a/drivers/staging/fsl-mc/bus/dpbp.c b/drivers/staging/fsl-mc/bus/dpbp.c index 2d97173f8..c31fe1bca 100644 --- a/drivers/staging/fsl-mc/bus/dpbp.c +++ b/drivers/staging/fsl-mc/bus/dpbp.c @@ -293,7 +293,7 @@ int dpbp_set_irq(struct fsl_mc_io *mc_io, cmd.params[0] |= mc_enc(0, 8, irq_index); cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); cmd.params[1] |= mc_enc(0, 64, irq_cfg->addr); - cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -334,7 +334,7 @@ int dpbp_get_irq(struct fsl_mc_io *mc_io, /* retrieve response parameters */ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); irq_cfg->addr = (u64)mc_dec(cmd.params[1], 0, 64); - irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32); *type = (int)mc_dec(cmd.params[2], 32, 32); return 0; } @@ -502,6 +502,7 @@ int dpbp_get_irq_status(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, cmd_flags, token); + cmd.params[0] |= mc_enc(0, 32, *status); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -580,3 +581,75 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, return 0; } EXPORT_SYMBOL(dpbp_get_attributes); + +/** + * dpbp_set_notifications() - Set notifications towards software + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @cfg: notifications configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_set_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS, + cmd_flags, + token); + + cmd.params[0] |= mc_enc(0, 32, cfg->depletion_entry); + cmd.params[0] |= mc_enc(32, 32, cfg->depletion_exit); + cmd.params[1] |= mc_enc(0, 32, cfg->surplus_entry); + cmd.params[1] |= mc_enc(32, 32, cfg->surplus_exit); + cmd.params[2] |= mc_enc(0, 16, cfg->options); + cmd.params[3] |= mc_enc(0, 64, cfg->message_ctx); + cmd.params[4] |= mc_enc(0, 64, cfg->message_iova); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +/** + * dpbp_get_notifications() - Get the notifications configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPBP object + * @cfg: notifications configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_get_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS, + cmd_flags, + token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + cfg->depletion_entry = (u32)mc_dec(cmd.params[0], 0, 32); + cfg->depletion_exit = (u32)mc_dec(cmd.params[0], 32, 32); + cfg->surplus_entry = (u32)mc_dec(cmd.params[1], 0, 32); + cfg->surplus_exit = (u32)mc_dec(cmd.params[1], 32, 32); + cfg->options = (u16)mc_dec(cmd.params[2], 0, 16); + cfg->message_ctx = (u64)mc_dec(cmd.params[3], 0, 64); + cfg->message_iova = (u64)mc_dec(cmd.params[4], 0, 64); + + return 0; +} diff --git a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h index a87e9f84f..c9b52dd7b 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h +++ b/drivers/staging/fsl-mc/bus/dpmcp-cmd.h @@ -32,9 +32,9 @@ #ifndef _FSL_DPMCP_CMD_H #define _FSL_DPMCP_CMD_H -/* DPMCP Version */ -#define DPMCP_VER_MAJOR 2 -#define DPMCP_VER_MINOR 1 +/* Minimal supported DPMCP Version */ +#define DPMCP_MIN_VER_MAJOR 3 +#define DPMCP_MIN_VER_MINOR 0 /* Command IDs */ #define DPMCP_CMDID_CLOSE 0x800 @@ -52,6 +52,5 @@ #define DPMCP_CMDID_SET_IRQ_MASK 0x014 #define DPMCP_CMDID_GET_IRQ_MASK 0x015 #define DPMCP_CMDID_GET_IRQ_STATUS 0x016 -#define DPMCP_CMDID_CLEAR_IRQ_STATUS 0x017 #endif /* _FSL_DPMCP_CMD_H */ diff --git a/drivers/staging/fsl-mc/bus/dpmcp.c b/drivers/staging/fsl-mc/bus/dpmcp.c index b0248f574..fd6dd4e07 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.c +++ b/drivers/staging/fsl-mc/bus/dpmcp.c @@ -213,7 +213,7 @@ int dpmcp_set_irq(struct fsl_mc_io *mc_io, cmd.params[0] |= mc_enc(0, 8, irq_index); cmd.params[0] |= mc_enc(32, 32, irq_cfg->val); cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); - cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -254,7 +254,7 @@ int dpmcp_get_irq(struct fsl_mc_io *mc_io, /* retrieve response parameters */ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64); - irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32); *type = (int)mc_dec(cmd.params[2], 32, 32); return 0; } @@ -435,37 +435,6 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, } /** - * dpmcp_clear_irq_status() - Clear a pending interrupt's status - * - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPMCP object - * @irq_index: The interrupt index to configure - * @status: Bits to clear (W1C) - one bit per cause: - * 0 = don't change - * 1 = clear status bit - * - * Return: '0' on Success; Error code otherwise. - */ -int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, - u32 cmd_flags, - u16 token, - u8 irq_index, - u32 status) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS, - cmd_flags, token); - cmd.params[0] |= mc_enc(0, 32, status); - cmd.params[0] |= mc_enc(32, 8, irq_index); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -/** * dpmcp_get_attributes - Retrieve DPMCP attributes. * * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-mc/bus/dpmcp.h b/drivers/staging/fsl-mc/bus/dpmcp.h index 6df351f0c..fe79d4d92 100644 --- a/drivers/staging/fsl-mc/bus/dpmcp.h +++ b/drivers/staging/fsl-mc/bus/dpmcp.h @@ -82,12 +82,12 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, * struct dpmcp_irq_cfg - IRQ configuration * @paddr: Address that must be written to signal a message-based interrupt * @val: Value to write into irq_addr address - * @user_irq_id: A user defined number associated with this IRQ + * @irq_num: A user defined number associated with this IRQ */ struct dpmcp_irq_cfg { uint64_t paddr; uint32_t val; - int user_irq_id; + int irq_num; }; int dpmcp_set_irq(struct fsl_mc_io *mc_io, @@ -133,12 +133,6 @@ int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, uint8_t irq_index, uint32_t *status); -int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t irq_index, - uint32_t status); - /** * struct dpmcp_attr - Structure representing DPMCP attributes * @id: DPMCP object ID diff --git a/drivers/staging/fsl-mc/bus/dprc-cmd.h b/drivers/staging/fsl-mc/bus/dprc-cmd.h index 6552c2034..9b854fa8e 100644 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h +++ b/drivers/staging/fsl-mc/bus/dprc-cmd.h @@ -40,9 +40,9 @@ #ifndef _FSL_DPRC_CMD_H #define _FSL_DPRC_CMD_H -/* DPRC Version */ -#define DPRC_VER_MAJOR 4 -#define DPRC_VER_MINOR 0 +/* Minimal supported DPRC Version */ +#define DPRC_MIN_VER_MAJOR 5 +#define DPRC_MIN_VER_MINOR 0 /* Command IDs */ #define DPRC_CMDID_CLOSE 0x800 diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 31488a7b9..7fc47173c 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -312,6 +312,15 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, continue; } + /* + * add a quirk for all versions of dpsec < 4.0...none + * are coherent regardless of what the MC reports. + */ + if ((strcmp(obj_desc->type, "dpseci") == 0) && + (obj_desc->ver_major < 4)) + obj_desc->flags |= + DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY; + irq_count += obj_desc->irq_count; dev_dbg(&mc_bus_dev->dev, "Discovered object: type %s, id %d\n", @@ -423,6 +432,7 @@ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) goto out; + status = 0; error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, &status); if (error < 0) { @@ -692,6 +702,25 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) goto error_cleanup_msi_domain; } + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle, + &mc_bus->dprc_attr); + if (error < 0) { + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n", + error); + goto error_cleanup_open; + } + + if (mc_bus->dprc_attr.version.major < DPRC_MIN_VER_MAJOR || + (mc_bus->dprc_attr.version.major == DPRC_MIN_VER_MAJOR && + mc_bus->dprc_attr.version.minor < DPRC_MIN_VER_MINOR)) { + dev_err(&mc_dev->dev, + "ERROR: DPRC version %d.%d not supported\n", + mc_bus->dprc_attr.version.major, + mc_bus->dprc_attr.version.minor); + error = -ENOTSUPP; + goto error_cleanup_open; + } + mutex_init(&mc_bus->scan_mutex); /* @@ -779,9 +808,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) static const struct fsl_mc_device_match_id match_id_table[] = { { .vendor = FSL_MC_VENDOR_FREESCALE, - .obj_type = "dprc", - .ver_major = DPRC_VER_MAJOR, - .ver_minor = DPRC_VER_MINOR}, + .obj_type = "dprc"}, {.vendor = 0x0}, }; diff --git a/drivers/staging/fsl-mc/bus/dprc.c b/drivers/staging/fsl-mc/bus/dprc.c index 381b9a96a..a2c47377c 100644 --- a/drivers/staging/fsl-mc/bus/dprc.c +++ b/drivers/staging/fsl-mc/bus/dprc.c @@ -265,7 +265,7 @@ int dprc_get_irq(struct fsl_mc_io *mc_io, /* retrieve response parameters */ irq_cfg->val = mc_dec(cmd.params[0], 0, 32); irq_cfg->paddr = mc_dec(cmd.params[1], 0, 64); - irq_cfg->user_irq_id = mc_dec(cmd.params[2], 0, 32); + irq_cfg->irq_num = mc_dec(cmd.params[2], 0, 32); *type = mc_dec(cmd.params[2], 32, 32); return 0; @@ -296,7 +296,7 @@ int dprc_set_irq(struct fsl_mc_io *mc_io, cmd.params[0] |= mc_enc(32, 8, irq_index); cmd.params[0] |= mc_enc(0, 32, irq_cfg->val); cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); - cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -466,6 +466,7 @@ int dprc_get_irq_status(struct fsl_mc_io *mc_io, /* prepare command */ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, cmd_flags, token); + cmd.params[0] |= mc_enc(0, 32, *status); cmd.params[0] |= mc_enc(32, 8, irq_index); /* send command to mc*/ @@ -948,6 +949,7 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, obj_desc->state = mc_dec(cmd.params[1], 32, 32); obj_desc->ver_major = mc_dec(cmd.params[2], 0, 16); obj_desc->ver_minor = mc_dec(cmd.params[2], 16, 16); + obj_desc->flags = mc_dec(cmd.params[2], 32, 16); obj_desc->type[0] = mc_dec(cmd.params[3], 0, 8); obj_desc->type[1] = mc_dec(cmd.params[3], 8, 8); obj_desc->type[2] = mc_dec(cmd.params[3], 16, 8); @@ -1042,6 +1044,7 @@ int dprc_get_obj_desc(struct fsl_mc_io *mc_io, obj_desc->state = (u32)mc_dec(cmd.params[1], 32, 32); obj_desc->ver_major = (u16)mc_dec(cmd.params[2], 0, 16); obj_desc->ver_minor = (u16)mc_dec(cmd.params[2], 16, 16); + obj_desc->flags = mc_dec(cmd.params[2], 32, 16); obj_desc->type[0] = (char)mc_dec(cmd.params[3], 0, 8); obj_desc->type[1] = (char)mc_dec(cmd.params[3], 8, 8); obj_desc->type[2] = (char)mc_dec(cmd.params[3], 16, 8); @@ -1108,7 +1111,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, cmd.params[0] |= mc_enc(32, 8, irq_index); cmd.params[0] |= mc_enc(0, 32, irq_cfg->val); cmd.params[1] |= mc_enc(0, 64, irq_cfg->paddr); - cmd.params[2] |= mc_enc(0, 32, irq_cfg->user_irq_id); + cmd.params[2] |= mc_enc(0, 32, irq_cfg->irq_num); cmd.params[2] |= mc_enc(32, 32, obj_id); cmd.params[3] |= mc_enc(0, 8, obj_type[0]); cmd.params[3] |= mc_enc(8, 8, obj_type[1]); @@ -1189,7 +1192,7 @@ int dprc_get_obj_irq(struct fsl_mc_io *mc_io, /* retrieve response parameters */ irq_cfg->val = (u32)mc_dec(cmd.params[0], 0, 32); irq_cfg->paddr = (u64)mc_dec(cmd.params[1], 0, 64); - irq_cfg->user_irq_id = (int)mc_dec(cmd.params[2], 0, 32); + irq_cfg->irq_num = (int)mc_dec(cmd.params[2], 0, 32); *type = (int)mc_dec(cmd.params[2], 32, 32); return 0; @@ -1437,14 +1440,8 @@ EXPORT_SYMBOL(dprc_set_obj_label); * @endpoint1: Endpoint 1 configuration parameters * @endpoint2: Endpoint 2 configuration parameters * @cfg: Connection configuration. The connection configuration is ignored for - * connections made to DPMAC objects, where rate is set according to - * MAC configuration. - * The committed rate is the guaranteed rate for the connection. - * The maximum rate is an upper limit allowed for the connection; it is - * expected to be equal or higher than the committed rate. - * When committed and maximum rates are both zero, the connection is set - * to "best effort" mode, having lower priority compared to connections - * with committed or maximum rates. + * connections made to DPMAC objects, where rate is retrieved from the + * MAC configuration. * * Return: '0' on Success; Error code otherwise. */ @@ -1555,7 +1552,10 @@ int dprc_disconnect(struct fsl_mc_io *mc_io, * @token: Token of DPRC object * @endpoint1: Endpoint 1 configuration parameters * @endpoint2: Returned endpoint 2 configuration parameters -* @state: Returned link state: 1 - link is up, 0 - link is down +* @state: Returned link state: +* 1 - link is up; +* 0 - link is down; +* -1 - no connection (endpoint2 information is irrelevant) * * Return: '0' on Success; -ENAVAIL if connection does not exist. */ diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index 86f8543c2..fb08f22a7 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -39,7 +39,6 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus struct fsl_mc_resource *resource; struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; int error = -EINVAL; - bool mutex_locked = false; if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) goto out; @@ -55,13 +54,12 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus goto out; mutex_lock(&res_pool->mutex); - mutex_locked = true; if (WARN_ON(res_pool->max_count < 0)) - goto out; + goto out_unlock; if (WARN_ON(res_pool->free_count < 0 || res_pool->free_count > res_pool->max_count)) - goto out; + goto out_unlock; resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), GFP_KERNEL); @@ -69,7 +67,7 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus error = -ENOMEM; dev_err(&mc_bus_dev->dev, "Failed to allocate memory for fsl_mc_resource\n"); - goto out; + goto out_unlock; } resource->type = pool_type; @@ -82,10 +80,9 @@ static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus res_pool->free_count++; res_pool->max_count++; error = 0; +out_unlock: + mutex_unlock(&res_pool->mutex); out: - if (mutex_locked) - mutex_unlock(&res_pool->mutex); - return error; } @@ -106,7 +103,6 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device struct fsl_mc_resource_pool *res_pool; struct fsl_mc_resource *resource; int error = -EINVAL; - bool mutex_locked = false; if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type))) goto out; @@ -122,13 +118,12 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device goto out; mutex_lock(&res_pool->mutex); - mutex_locked = true; if (WARN_ON(res_pool->max_count <= 0)) - goto out; + goto out_unlock; if (WARN_ON(res_pool->free_count <= 0 || res_pool->free_count > res_pool->max_count)) - goto out; + goto out_unlock; /* * If the device is currently allocated, its resource is not @@ -139,7 +134,7 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device dev_err(&mc_bus_dev->dev, "Device %s cannot be removed from resource pool\n", dev_name(&mc_dev->dev)); - goto out; + goto out_unlock; } list_del(&resource->node); @@ -150,10 +145,9 @@ static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device devm_kfree(&mc_bus_dev->dev, resource); mc_dev->resource = NULL; error = 0; +out_unlock: + mutex_unlock(&res_pool->mutex); out: - if (mutex_locked) - mutex_unlock(&res_pool->mutex); - return error; } @@ -188,21 +182,19 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, struct fsl_mc_resource *resource; struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; int error = -EINVAL; - bool mutex_locked = false; BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) != FSL_MC_NUM_POOL_TYPES); *new_resource = NULL; if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)) - goto error; + goto out; res_pool = &mc_bus->resource_pools[pool_type]; if (WARN_ON(res_pool->mc_bus != mc_bus)) - goto error; + goto out; mutex_lock(&res_pool->mutex); - mutex_locked = true; resource = list_first_entry_or_null(&res_pool->free_list, struct fsl_mc_resource, node); @@ -212,28 +204,26 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, dev_err(&mc_bus_dev->dev, "No more resources of type %s left\n", fsl_mc_pool_type_strings[pool_type]); - goto error; + goto out_unlock; } if (WARN_ON(resource->type != pool_type)) - goto error; + goto out_unlock; if (WARN_ON(resource->parent_pool != res_pool)) - goto error; + goto out_unlock; if (WARN_ON(res_pool->free_count <= 0 || res_pool->free_count > res_pool->max_count)) - goto error; + goto out_unlock; list_del(&resource->node); INIT_LIST_HEAD(&resource->node); res_pool->free_count--; + error = 0; +out_unlock: mutex_unlock(&res_pool->mutex); *new_resource = resource; - return 0; -error: - if (mutex_locked) - mutex_unlock(&res_pool->mutex); - +out: return error; } EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); @@ -241,26 +231,23 @@ EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate); void fsl_mc_resource_free(struct fsl_mc_resource *resource) { struct fsl_mc_resource_pool *res_pool; - bool mutex_locked = false; res_pool = resource->parent_pool; if (WARN_ON(resource->type != res_pool->type)) - goto out; + return; mutex_lock(&res_pool->mutex); - mutex_locked = true; if (WARN_ON(res_pool->free_count < 0 || res_pool->free_count >= res_pool->max_count)) - goto out; + goto out_unlock; if (WARN_ON(!list_empty(&resource->node))) - goto out; + goto out_unlock; list_add_tail(&resource->node, &res_pool->free_list); res_pool->free_count++; -out: - if (mutex_locked) - mutex_unlock(&res_pool->mutex); +out_unlock: + mutex_unlock(&res_pool->mutex); } EXPORT_SYMBOL_GPL(fsl_mc_resource_free); @@ -306,10 +293,22 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev, if (error < 0) return error; + error = -EINVAL; dpmcp_dev = resource->data; if (WARN_ON(!dpmcp_dev)) goto error_cleanup_resource; + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR || + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR && + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) { + dev_err(&dpmcp_dev->dev, + "ERROR: Version %d.%d of DPMCP not supported.\n", + dpmcp_dev->obj_desc.ver_major, + dpmcp_dev->obj_desc.ver_minor); + error = -ENOTSUPP; + goto error_cleanup_resource; + } + if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0)) goto error_cleanup_resource; @@ -722,20 +721,14 @@ static const struct fsl_mc_device_match_id match_id_table[] = { { .vendor = FSL_MC_VENDOR_FREESCALE, .obj_type = "dpbp", - .ver_major = DPBP_VER_MAJOR, - .ver_minor = DPBP_VER_MINOR }, { .vendor = FSL_MC_VENDOR_FREESCALE, .obj_type = "dpmcp", - .ver_major = DPMCP_VER_MAJOR, - .ver_minor = DPMCP_VER_MINOR }, { .vendor = FSL_MC_VENDOR_FREESCALE, .obj_type = "dpcon", - .ver_major = DPCON_VER_MAJOR, - .ver_minor = DPCON_VER_MINOR }, {.vendor = 0x0}, }; diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index b59455661..405364307 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -40,8 +40,6 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); bool found = false; - bool major_version_mismatch = false; - bool minor_version_mismatch = false; if (WARN_ON(!fsl_mc_bus_exists())) goto out; @@ -64,32 +62,12 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) { if (id->vendor == mc_dev->obj_desc.vendor && strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) { - if (id->ver_major == mc_dev->obj_desc.ver_major) { - found = true; - if (id->ver_minor != mc_dev->obj_desc.ver_minor) - minor_version_mismatch = true; - } else { - major_version_mismatch = true; - } + found = true; break; } } - if (major_version_mismatch) { - dev_warn(dev, - "Major version mismatch: driver version %u.%u, MC object version %u.%u\n", - id->ver_major, id->ver_minor, - mc_dev->obj_desc.ver_major, - mc_dev->obj_desc.ver_minor); - } else if (minor_version_mismatch) { - dev_warn(dev, - "Minor version mismatch: driver version %u.%u, MC object version %u.%u\n", - id->ver_major, id->ver_minor, - mc_dev->obj_desc.ver_major, - mc_dev->obj_desc.ver_minor); - } - out: dev_dbg(dev, "%smatched\n", found ? "" : "not "); return found; @@ -251,11 +229,10 @@ static bool fsl_mc_is_root_dprc(struct device *dev) return dev == root_dprc_dev; } -static int get_dprc_icid(struct fsl_mc_io *mc_io, - int container_id, u16 *icid) +static int get_dprc_attr(struct fsl_mc_io *mc_io, + int container_id, struct dprc_attributes *attr) { u16 dprc_handle; - struct dprc_attributes attr; int error; error = dprc_open(mc_io, 0, container_id, &dprc_handle); @@ -264,15 +241,14 @@ static int get_dprc_icid(struct fsl_mc_io *mc_io, return error; } - memset(&attr, 0, sizeof(attr)); - error = dprc_get_attributes(mc_io, 0, dprc_handle, &attr); + memset(attr, 0, sizeof(struct dprc_attributes)); + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr); if (error < 0) { dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n", error); goto common_cleanup; } - *icid = attr.icid; error = 0; common_cleanup: @@ -280,6 +256,34 @@ common_cleanup: return error; } +static int get_dprc_icid(struct fsl_mc_io *mc_io, + int container_id, u16 *icid) +{ + struct dprc_attributes attr; + int error; + + error = get_dprc_attr(mc_io, container_id, &attr); + if (error == 0) + *icid = attr.icid; + + return error; +} + +static int get_dprc_version(struct fsl_mc_io *mc_io, + int container_id, u16 *major, u16 *minor) +{ + struct dprc_attributes attr; + int error; + + error = get_dprc_attr(mc_io, container_id, &attr); + if (error == 0) { + *major = attr.version.major; + *minor = attr.version.minor; + } + + return error; +} + static int translate_mc_addr(struct fsl_mc_device *mc_dev, enum dprc_region_type mc_region_type, u64 mc_offset, phys_addr_t *phys_addr) @@ -376,6 +380,8 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, regions[i].end = regions[i].start + region_desc.size - 1; regions[i].name = "fsl-mc object MMIO region"; regions[i].flags = IORESOURCE_IO; + if (region_desc.flags & DPRC_REGION_CACHEABLE) + regions[i].flags |= IORESOURCE_CACHEABLE; } mc_dev->regions = regions; @@ -491,6 +497,10 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, goto error_cleanup_dev; } + /* Objects are coherent, unless 'no shareability' flag set. */ + if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY)) + arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true); + /* * The device-specific probe callback will get invoked by device_add() */ @@ -722,20 +732,6 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) "Freescale Management Complex Firmware version: %u.%u.%u\n", mc_version.major, mc_version.minor, mc_version.revision); - if (mc_version.major < MC_VER_MAJOR) { - dev_err(&pdev->dev, - "ERROR: MC firmware version not supported by driver (driver version: %u.%u)\n", - MC_VER_MAJOR, MC_VER_MINOR); - error = -ENOTSUPP; - goto error_cleanup_mc_io; - } - - if (mc_version.major > MC_VER_MAJOR) { - dev_warn(&pdev->dev, - "WARNING: driver may not support newer MC firmware features (driver version: %u.%u)\n", - MC_VER_MAJOR, MC_VER_MINOR); - } - error = get_mc_addr_translation_ranges(&pdev->dev, &mc->translation_ranges, &mc->num_translation_ranges); @@ -749,11 +745,15 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) goto error_cleanup_mc_io; } + memset(&obj_desc, 0, sizeof(struct dprc_obj_desc)); + error = get_dprc_version(mc_io, container_id, + &obj_desc.ver_major, &obj_desc.ver_minor); + if (error < 0) + goto error_cleanup_mc_io; + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; strcpy(obj_desc.type, "dprc"); obj_desc.id = container_id; - obj_desc.ver_major = DPRC_VER_MAJOR; - obj_desc.ver_minor = DPRC_VER_MINOR; obj_desc.irq_count = 1; obj_desc.region_count = 0; diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c index 3a8258ff4..e202b2b88 100644 --- a/drivers/staging/fsl-mc/bus/mc-msi.c +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -37,10 +37,8 @@ static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) /* * set_desc should not be set by the caller */ - if (WARN_ON(ops->set_desc)) - return; - - ops->set_desc = fsl_mc_msi_set_desc; + if (ops->set_desc == NULL) + ops->set_desc = fsl_mc_msi_set_desc; } static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, @@ -65,7 +63,7 @@ static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | msi_desc->msg.address_lo; irq_cfg.val = msi_desc->msg.data; - irq_cfg.user_irq_id = msi_desc->irq; + irq_cfg.irq_num = msi_desc->irq; if (owner_mc_dev == mc_bus_dev) { /* @@ -129,10 +127,8 @@ static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) /* * irq_write_msi_msg should not be set by the caller */ - if (WARN_ON(chip->irq_write_msi_msg)) - return; - - chip->irq_write_msi_msg = fsl_mc_msi_write_msg; + if (chip->irq_write_msi_msg == NULL) + chip->irq_write_msi_msg = fsl_mc_msi_write_msg; } /** diff --git a/drivers/staging/fsl-mc/include/dpbp-cmd.h b/drivers/staging/fsl-mc/include/dpbp-cmd.h index efa9bf33c..c57b454a2 100644 --- a/drivers/staging/fsl-mc/include/dpbp-cmd.h +++ b/drivers/staging/fsl-mc/include/dpbp-cmd.h @@ -34,7 +34,7 @@ /* DPBP Version */ #define DPBP_VER_MAJOR 2 -#define DPBP_VER_MINOR 1 +#define DPBP_VER_MINOR 2 /* Command IDs */ #define DPBP_CMDID_CLOSE 0x800 @@ -57,4 +57,6 @@ #define DPBP_CMDID_GET_IRQ_STATUS 0x016 #define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 +#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 +#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 #endif /* _FSL_DPBP_CMD_H */ diff --git a/drivers/staging/fsl-mc/include/dpbp.h b/drivers/staging/fsl-mc/include/dpbp.h index 37ed95143..e14e85a5d 100644 --- a/drivers/staging/fsl-mc/include/dpbp.h +++ b/drivers/staging/fsl-mc/include/dpbp.h @@ -85,12 +85,12 @@ int dpbp_reset(struct fsl_mc_io *mc_io, * struct dpbp_irq_cfg - IRQ configuration * @addr: Address that must be written to signal a message-based interrupt * @val: Value to write into irq_addr address - * @user_irq_id: A user defined number associated with this IRQ + * @irq_num: A user defined number associated with this IRQ */ struct dpbp_irq_cfg { u64 addr; u32 val; - int user_irq_id; + int irq_num; }; int dpbp_set_irq(struct fsl_mc_io *mc_io, @@ -168,6 +168,53 @@ int dpbp_get_attributes(struct fsl_mc_io *mc_io, u16 token, struct dpbp_attr *attr); +/** + * DPBP notifications options + */ + +/** + * BPSCN write will attempt to allocate into a cache (coherent write) + */ +#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001 + +/** + * struct dpbp_notification_cfg - Structure representing DPBP notifications + * towards software + * @depletion_entry: below this threshold the pool is "depleted"; + * set it to '0' to disable it + * @depletion_exit: greater than or equal to this threshold the pool exit its + * "depleted" state + * @surplus_entry: above this threshold the pool is in "surplus" state; + * set it to '0' to disable it + * @surplus_exit: less than or equal to this threshold the pool exit its + * "surplus" state + * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry' + * is not '0' (enable); I/O virtual address (must be in DMA-able memory), + * must be 16B aligned. + * @message_ctx: The context that will be part of the BPSCN message and will + * be written to 'message_iova' + * @options: Mask of available options; use 'DPBP_NOTIF_OPT_<X>' values + */ +struct dpbp_notification_cfg { + u32 depletion_entry; + u32 depletion_exit; + u32 surplus_entry; + u32 surplus_exit; + u64 message_iova; + u64 message_ctx; + u16 options; +}; + +int dpbp_set_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg); + +int dpbp_get_notifications(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + struct dpbp_notification_cfg *cfg); + /** @} */ #endif /* __FSL_DPBP_H */ diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index 94c492706..593b2bbe7 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -94,11 +94,6 @@ int dprc_close(struct fsl_mc_io *mc_io, */ #define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008 -/* IOMMU bypass - indicates whether objects of this container are permitted - * to bypass the IOMMU. - */ -#define DPRC_CFG_OPT_IOMMU_BYPASS 0x00000010 - /* AIOP - Indicates that container belongs to AIOP. */ #define DPRC_CFG_OPT_AIOP 0x00000020 @@ -173,12 +168,12 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, * struct dprc_irq_cfg - IRQ configuration * @paddr: Address that must be written to signal a message-based interrupt * @val: Value to write into irq_addr address - * @user_irq_id: A user defined number associated with this IRQ + * @irq_num: A user defined number associated with this IRQ */ struct dprc_irq_cfg { phys_addr_t paddr; u32 val; - int user_irq_id; + int irq_num; }; int dprc_set_irq(struct fsl_mc_io *mc_io, @@ -353,6 +348,14 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, #define DPRC_OBJ_STATE_PLUGGED 0x00000002 /** + * Shareability flag - Object flag indicating no memory shareability. + * the object generates memory accesses that are non coherent with other + * masters; + * user is responsible for proper memory handling through IOMMU configuration. + */ +#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 + +/** * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() * @type: Type of object: NULL terminated string * @id: ID of logical object resource @@ -363,6 +366,7 @@ int dprc_get_obj_count(struct fsl_mc_io *mc_io, * @region_count: Number of mappable regions supported by the object * @state: Object state: combination of DPRC_OBJ_STATE_ states * @label: Object label + * @flags: Object's flags */ struct dprc_obj_desc { char type[16]; @@ -374,6 +378,7 @@ struct dprc_obj_desc { u8 region_count; u32 state; char label[16]; + u16 flags; }; int dprc_get_obj(struct fsl_mc_io *mc_io, diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index ee5f1d2bf..cab1ae90f 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -94,12 +94,14 @@ struct fsl_mc_resource_pool { * from the physical DPRC. * @irq_resources: Pointer to array of IRQ objects for the IRQ pool * @scan_mutex: Serializes bus scanning + * @dprc_attr: DPRC attributes */ struct fsl_mc_bus { struct fsl_mc_device mc_dev; struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; struct fsl_mc_device_irq *irq_resources; struct mutex scan_mutex; /* serializes bus scanning */ + struct dprc_attributes dprc_attr; }; #define to_fsl_mc_bus(_mc_dev) \ |