summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/dpa/offline_port.c
diff options
context:
space:
mode:
authorRadu Bulie <radu.bulie@freescale.com>2013-05-08 07:30:20 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-05-10 19:15:02 (GMT)
commita692ce8aa28657c1178a326c5d20dcb594402976 (patch)
tree14740236e0e07f0f5e2d31590089c65bf3d22fb3 /drivers/net/ethernet/freescale/dpa/offline_port.c
parentbaeb009a3c12b4a4227a93236b7adb4e49c93897 (diff)
downloadlinux-fsl-qoriq-a692ce8aa28657c1178a326c5d20dcb594402976.tar.xz
offline_port: Add support for enabling IP Fragmentation in the O/H port driver
In order to enable fragmentation on an offline port, a chosen node should be configured in dt for that specific port with two parameters: manip_extra_space and data_align. In addition external buffer pools must be set for the O/H port in the dts file (e.g: fsl,bman-buffer-pools = <&bp8>;). A bool flag is transmited to dpaa_eth_init_port (used further in FMD wrapper) macro whether or not fragmentation was enabled. For the dpaa_eth module this flag must be set to false.(FMD frag support is only available on O/H ports). Change-Id: Ifb01b2feebab9199cc0f72b611ce212061d0a7e2 Signed-off-by: Radu Bulie <radu.bulie@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/2261 Reviewed-by: Chereji Marian-Cornel-R27762 <marian.chereji@freescale.com> Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com> Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/dpa/offline_port.c')
-rw-r--r--drivers/net/ethernet/freescale/dpa/offline_port.c114
1 files changed, 106 insertions, 8 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/offline_port.c b/drivers/net/ethernet/freescale/dpa/offline_port.c
index af00f85..aa30caa 100644
--- a/drivers/net/ethernet/freescale/dpa/offline_port.c
+++ b/drivers/net/ethernet/freescale/dpa/offline_port.c
@@ -47,6 +47,12 @@
#include "dpaa_eth-common.h"
#define OH_MOD_DESCRIPTION "FSL FMan Offline Parsing port driver"
+/*
+ * Manip extra space and data alignment for fragmentation
+ */
+#define FRAG_MANIP_SPACE 128
+#define FRAG_DATA_ALIGN 64
+
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Bogdan Hamciuc <bogdan.hamciuc@freescale.com>");
@@ -117,23 +123,29 @@ oh_port_probe(struct platform_device *_of_dev)
{
struct device *dpa_oh_dev;
struct device_node *dpa_oh_node;
- int lenp, _errno = 0, fq_idx;
- const phandle *oh_port_handle;
+ int lenp, _errno = 0, fq_idx, n_size, i;
+ const phandle *oh_port_handle, *bpool_handle;
struct platform_device *oh_of_dev;
- struct device_node *oh_node;
+ struct device_node *oh_node, *bpool_node = NULL, *root_node;
struct device *oh_dev;
struct dpa_oh_config_s *oh_config;
uint32_t *oh_all_queues;
uint32_t queues_count;
uint32_t crt_fqid_base;
uint32_t crt_fq_count;
- struct fm_port_params oh_port_tx_params;
+ bool frag_enabled = FALSE;
+ struct fm_port_params oh_port_tx_params;
struct fm_port_pcd_param oh_port_pcd_params;
struct dpa_buffer_layout_s buf_layout;
/* True if the current partition owns the OH port. */
bool init_oh_port;
const struct of_device_id *match;
+ uint32_t crt_ext_pools_count, ext_pool_size;
+ const unsigned int *port_id;
+ const uint32_t *bpool_cfg;
+ const uint32_t *bpid;
+ memset(&oh_port_tx_params, 0, sizeof(oh_port_tx_params));
dpa_oh_dev = &_of_dev->dev;
dpa_oh_node = dpa_oh_dev->of_node;
BUG_ON(dpa_oh_node == NULL);
@@ -175,10 +187,19 @@ oh_port_probe(struct platform_device *_of_dev)
dev_info(dpa_oh_dev, "Found OH node handle compatible with %s.\n",
match->compatible);
+ port_id = of_get_property(oh_node, "cell-index", &lenp);
+
+ if (port_id == NULL) {
+ dev_err(dpa_oh_dev, "No port id found in node %s\n",
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ BUG_ON(lenp % sizeof(*port_id));
oh_of_dev = of_find_device_by_node(oh_node);
BUG_ON(oh_of_dev == NULL);
oh_dev = &oh_of_dev->dev;
- of_node_put(oh_node);
/*
* The OH port must be initialized exactly once.
@@ -199,6 +220,7 @@ oh_port_probe(struct platform_device *_of_dev)
if (!init_oh_port) {
dev_dbg(dpa_oh_dev, "Not owning the shared OH port %s, "
"will not initialize it.\n", oh_node->full_name);
+ of_node_put(oh_node);
return 0;
}
@@ -208,7 +230,8 @@ oh_port_probe(struct platform_device *_of_dev)
dev_err(dpa_oh_dev, "Can't allocate private data for "
"OH node %s referenced from node %s!\n",
oh_node->full_name, dpa_oh_node->full_name);
- return -ENOMEM;
+ _errno = -ENOMEM;
+ goto return_kfree;
}
/*
@@ -280,10 +303,81 @@ oh_port_probe(struct platform_device *_of_dev)
}
oh_set_buffer_layout(oh_config->oh_port, &buf_layout);
+ bpool_handle = of_get_property(dpa_oh_node,
+ "fsl,bman-buffer-pools", &lenp);
+
+ if (bpool_handle == NULL) {
+ dev_info(dpa_oh_dev, "OH port %s has no buffer pool. Fragmentation will not be enabled\n",
+ oh_node->full_name);
+ goto init_port;
+ }
+
+ /* used for reading ext_pool_size*/
+ root_node = of_find_node_by_path("/");
+ if (root_node == NULL) {
+ dev_err(dpa_oh_dev, "of_find_node_by_path(/) failed\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ n_size = of_n_size_cells(root_node);
+ of_node_put(root_node);
+
+ crt_ext_pools_count = lenp / sizeof(phandle);
+ dev_dbg(dpa_oh_dev, "OH port number of pools = %u\n",
+ crt_ext_pools_count);
+
+ oh_port_tx_params.num_pools = crt_ext_pools_count;
+
+ for (i = 0; i < crt_ext_pools_count; i++) {
+ bpool_node = of_find_node_by_phandle(bpool_handle[i]);
+ if (bpool_node == NULL) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool node\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ bpid = of_get_property(bpool_node, "fsl,bpid", &lenp);
+ if ((bpid == NULL) || (lenp != sizeof(*bpid))) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool Id\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ oh_port_tx_params.pool_param[i].id = *bpid;
+ dev_dbg(dpa_oh_dev, "OH port bpool id = %u\n", *bpid);
+
+ bpool_cfg = of_get_property(bpool_node,
+ "fsl,bpool-ethernet-cfg", &lenp);
+ if (bpool_cfg == NULL) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool config params\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ of_read_number(bpool_cfg, n_size);
+ ext_pool_size = of_read_number(bpool_cfg + n_size, n_size);
+ oh_port_tx_params.pool_param[i].size = ext_pool_size;
+ dev_dbg(dpa_oh_dev, "OH port bpool size = %u\n",
+ ext_pool_size);
+ of_node_put(bpool_node);
+
+ }
+
+ if (buf_layout.data_align != FRAG_DATA_ALIGN ||
+ buf_layout.manip_extra_space != FRAG_MANIP_SPACE)
+ goto init_port;
+
+ frag_enabled = TRUE;
+ dev_info(dpa_oh_dev, "IP Fragmentation enabled for OH port %d",
+ *port_id);
+
+init_port:
+ of_node_put(oh_node);
/* Set Tx params */
- memset(&oh_port_tx_params, 0, sizeof(oh_port_tx_params));
dpaa_eth_init_port(tx, oh_config->oh_port, oh_port_tx_params,
- oh_config->error_fqid, oh_config->default_fqid, (&buf_layout));
+ oh_config->error_fqid, oh_config->default_fqid, (&buf_layout),
+ frag_enabled);
/* Set PCD params */
oh_port_pcd_params.cba = oh_alloc_pcd_fqids;
oh_port_pcd_params.cbf = oh_free_pcd_fqids;
@@ -299,6 +393,10 @@ oh_port_probe(struct platform_device *_of_dev)
return 0;
return_kfree:
+ if (bpool_node)
+ of_node_put(bpool_node);
+ if (oh_node)
+ of_node_put(oh_node);
devm_kfree(dpa_oh_dev, oh_config);
return _errno;
}