diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c | 207 |
1 files changed, 106 insertions, 101 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c index 5f772d3..2ed90c8 100644 --- a/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c +++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c @@ -173,31 +173,27 @@ static struct platform_driver dpa_generic_driver = { .remove = dpa_generic_remove }; -static int get_port_ref(struct device_node dev_node, +static int get_port_ref(struct device_node *dev_node, struct fm_port **port) { - const phandle *dpa_port_ref_node = NULL; - struct platform_device *dpa_port_of_dev = NULL; + struct platform_device *port_of_dev = NULL; struct device *op_dev = NULL; - struct device_node *dpa_port_node = NULL; - int lenp = 0; + struct device_node *port_node = NULL; - dpa_port_ref_node = of_get_property(&dev_node, - "fsl,fman-oh-port", &lenp); - if (dpa_port_ref_node == NULL) + port_node = of_parse_phandle(dev_node, "fsl,fman-oh-port", 0); + if (port_node == NULL) return -EINVAL; - dpa_port_node = of_find_node_by_phandle(*dpa_port_ref_node); - if (dpa_port_node == NULL) - return -EINVAL; + port_of_dev = of_find_device_by_node(port_node); + of_node_put(port_node); - dpa_port_of_dev = of_find_device_by_node(dpa_port_node); - of_node_put(dpa_port_node); - if (dpa_port_of_dev == NULL) + if (port_of_dev == NULL) return -EINVAL; - op_dev = &dpa_port_of_dev->dev; + /* get the reference to oh port from FMD */ + op_dev = &port_of_dev->dev; *port = fm_port_bind(op_dev); + if (*port == NULL) return -EINVAL; @@ -233,31 +229,25 @@ static void dpaa_generic_napi_disable(struct dpa_generic_priv_s *priv) static struct device_node *get_rx_op_port_node(struct platform_device *_of_dev) { struct device *dev = &_of_dev->dev; - struct device_node *dev_node = NULL; - const phandle *ports_handle = NULL; + struct device_node *port_node = NULL; + struct device_node *onic_node = NULL; int num_ports = 0; - int lenp = 0; - ports_handle = of_get_property(dev->of_node, - "fsl,oh-ports", &lenp); - if (ports_handle == NULL) { - dev_err(dev, "Cannot find node fsl,oh-ports property in device tree\n"); - return ERR_PTR(-EINVAL); - } + onic_node = dev->of_node; - num_ports = lenp / sizeof(*ports_handle); - if (num_ports < 1) { - dev_err(dev, "There should be at least one O/H port in device tree\n"); + num_ports = of_count_phandle_with_args(onic_node, "fsl,oh-ports", NULL); + if (num_ports != 2) { + dev_err(dev, "There should be two O/H port handles in the device tree\n"); return ERR_PTR(-EINVAL); } - dev_node = of_find_node_by_phandle(*ports_handle); - if (unlikely(dev_node == NULL)) { - dev_err(dev, "Cannot find node oh port node in device tree\n"); + port_node = of_parse_phandle(onic_node, "fsl,oh-ports", 0); + if (port_node == NULL) { + dev_err(dev, "Cannot find O/H port node in the device tree\n"); return ERR_PTR(-EFAULT); } - return dev_node; + return port_node; } static int __cold dpa_generic_start(struct net_device *netdev) @@ -790,76 +780,106 @@ static struct dpa_fq_cbs_t generic_fq_cbs = { .egress_ern = { .cb = { .ern = dpa_generic_ern } } }; +static struct fqid_cell *__fq_alloc(struct device *dev, + int num_ranges, + const void *fqids_off) +{ + struct fqid_cell *fqids; + int i; + + fqids = kzalloc(sizeof(*fqids) * num_ranges, GFP_KERNEL); + if (fqids == NULL) + return NULL; + + /* convert to CPU endianess */ + for (i = 0; i < num_ranges; i++) { + fqids[i].start = be32_to_cpup(fqids_off + + i * sizeof(*fqids)); + fqids[i].count = be32_to_cpup(fqids_off + + i * sizeof(*fqids) + sizeof(__be32)); + } + + return fqids; +} + static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, struct fm_port *tx_port) { struct device *dev = &_of_dev->dev; - struct device_node *dev_node = NULL; - const struct fqid_cell *fqids; + struct device_node *oh_node = NULL; + struct device_node *onic_node = NULL; + struct fqid_cell *fqids; + const void *fqids_off; struct dpa_fq *fq, *tmp; struct list_head *list; int num_ranges; int i, lenp; - /* RX queues (RX error, RX default) are specified in Rx O/H port node */ - dev_node = get_rx_op_port_node(_of_dev); + onic_node = dev->of_node; + + list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); + if (!list) { + dev_err(dev, "Cannot allocate space for frame queues list\n"); + return ERR_PTR(-ENOMEM); + } + + INIT_LIST_HEAD(list); - fqids = of_get_property(dev_node, "fsl,qman-frame-queues-oh", &lenp); - if (fqids == NULL) { + /* RX queues (RX error, RX default) are specified in Rx O/H port node */ + oh_node = get_rx_op_port_node(_of_dev); + fqids_off = of_get_property(oh_node, "fsl,qman-frame-queues-oh", &lenp); + if (fqids_off == NULL) { dev_err(dev, "Need Rx FQ definition in dts for generic devices\n"); return ERR_PTR(-EINVAL); } + of_node_put(oh_node); - of_node_put(dev_node); num_ranges = lenp / sizeof(*fqids); if (num_ranges != 2) { dev_err(dev, "Need 2 Rx FQ definitions in dts for generic devices\n"); return ERR_PTR(-EINVAL); } - list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); - if (!list) { - dev_err(dev, "devm_kzalloc() failed\n"); - return ERR_PTR(-ENOMEM); - } - - INIT_LIST_HEAD(list); - + fqids = __fq_alloc(dev, num_ranges, fqids_off); if (!dpa_fq_alloc(dev, &fqids[0], list, FQ_TYPE_RX_ERROR) || !dpa_fq_alloc(dev, &fqids[1], list, FQ_TYPE_RX_DEFAULT)) { - dev_err(dev, "_dpa_fq_alloc() failed\n"); + dev_err(dev, "Cannot allocate space for default frame queues\n"); return ERR_PTR(-ENOMEM); } + kfree(fqids); /* TX queues */ - fqids = of_get_property(dev->of_node, - "fsl,qman-frame-queues-tx", &lenp); - if (fqids == NULL) { + fqids_off = of_get_property(onic_node, "fsl,qman-frame-queues-tx", + &lenp); + if (fqids_off == NULL) { dev_err(dev, "Need Tx FQ definition in dts for generic devices\n"); return ERR_PTR(-EINVAL); } num_ranges = lenp / sizeof(*fqids); + fqids = __fq_alloc(dev, num_ranges, fqids_off); for (i = 0; i < num_ranges; i++) { if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_TX)) { dev_err(dev, "_dpa_fq_alloc() failed\n"); return ERR_PTR(-ENOMEM); } } + kfree(fqids); /* optional RX PCD queues */ lenp = 0; - fqids = of_get_property(dev->of_node, + fqids_off = of_get_property(onic_node, "fsl,qman-frame-queues-rx", &lenp); - num_ranges = lenp / sizeof(*fqids); + fqids = __fq_alloc(dev, num_ranges, fqids_off); for (i = 0; i < num_ranges; i++) { if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_RX_PCD)) { dev_err(dev, "_dpa_fq_alloc() failed\n"); return ERR_PTR(-ENOMEM); } } + kfree(fqids); list_for_each_entry_safe(fq, tmp, list, list) { if (fq->fq_type == FQ_TYPE_TX) @@ -897,36 +917,33 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, struct dpa_buffer_layout_s **rx_buf_layout) { struct device *dev = &_of_dev->dev; - const phandle *phandle_prop = NULL; struct fm_port_params params; struct dpa_bp *bp = NULL; int bp_count = 0; - const uint32_t *bpid = NULL; - const uint32_t *bpool_cfg = NULL; + int bpid; + const __be32 *bpool_cfg = NULL; struct device_node *dev_node = NULL; + struct device_node *oh_node = NULL; struct dpa_buffer_layout_s *buf_layout = NULL; int lenp = 0; int na = 0, ns = 0; int err = 0, i = 0; - dev_node = get_rx_op_port_node(_of_dev); + oh_node = get_rx_op_port_node(_of_dev); - phandle_prop = of_get_property(dev_node, - "fsl,bman-buffer-pools", &lenp); - if (!phandle_prop) { - dev_err(dev, "missing fsl,bman-buffer-pools property from device tree\n"); + bp_count = of_count_phandle_with_args(oh_node, + "fsl,bman-buffer-pools", NULL); + if (bp_count <= 0) { + dev_err(dev, "Missing buffer pool handles from onic node from device tree\n"); return -EINVAL; } - bp_count = lenp / sizeof(*phandle_prop); - bp = devm_kzalloc(dev, bp_count * sizeof(*bp), GFP_KERNEL); if (unlikely(bp == NULL)) { dev_err(dev, "devm_kzalloc() failed\n"); return -ENOMEM; } - of_node_put(dev_node); dev_node = of_find_node_by_path("/"); if (unlikely(dev_node == NULL)) { dev_err(dev, "of_find_node_by_path(/) failed\n"); @@ -939,27 +956,20 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, of_node_put(dev_node); for (i = 0; i < bp_count; i++) { - dev_node = of_find_node_by_phandle(phandle_prop[i]); - if (unlikely(dev_node == NULL)) { - dev_err(dev, "of_find_node_by_phandle() failed\n"); + dev_node = of_parse_phandle(oh_node, + "fsl,bman-buffer-pools", i); + if (dev_node == NULL) { + dev_err(dev, "Cannot find buffer pool node in the device tree\n"); return -EFAULT; } - if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) { - dev_err(dev, "!of_device_is_compatible(%s, fsl,bpool)\n", - dev_node->full_name); - err = -EINVAL; - goto _return_of_node_put; - } - - bpid = of_get_property(dev_node, "fsl,bpid", &lenp); - if ((bpid == NULL) || (lenp != sizeof(*bpid))) { - dev_err(dev, "fsl,bpid property not found.\n"); - err = -EINVAL; + err = of_property_read_u32(dev_node, "fsl,bpid", &bpid); + if (err) { + dev_err(dev, "Cannot find buffer pool ID in the buffer pool node in the device tree\n"); goto _return_of_node_put; } - bp[i].bpid = (uint8_t)*bpid; + bp[i].bpid = (uint8_t)bpid; bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg", &lenp); @@ -979,6 +989,8 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, *bp[i].percpu_count); } + of_node_put(oh_node); + buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL); if (!buf_layout) { dev_err(dev, "devm_kzalloc() failed\n"); @@ -1073,46 +1085,39 @@ static int dpa_generic_port_probe(struct platform_device *_of_dev, { struct device *dev = &_of_dev->dev; struct device_node *dev_node = NULL; - const phandle *ports_handle = NULL; + struct device_node *onic_node = NULL; int num_ports = 0; - int lenp = 0; int err = 0; - ports_handle = of_get_property(dev->of_node, - "fsl,oh-ports", &lenp); - if (ports_handle == NULL) { - dev_err(dev, "Cannot find fsl,oh-ports property in device tree\n"); - return -EINVAL; - } + onic_node = dev->of_node; - num_ports = lenp / sizeof(*ports_handle); + num_ports = of_count_phandle_with_args(onic_node, "fsl,oh-ports", NULL); if (num_ports != 2) { - /* for the moment, only two ports are supported */ dev_err(dev, "There should be two OH ports in device tree (one for RX, one for TX\n"); return -EINVAL; } - dev_node = of_find_node_by_phandle(ports_handle[RX]); - if (unlikely(dev_node == NULL)) { - dev_err(dev, "Cannot find OH port node in device tree\n"); - return -EFAULT; + dev_node = of_parse_phandle(onic_node, "fsl,oh-ports", RX); + if (dev_node == NULL) { + dev_err(dev, "Cannot find Rx OH port node in device tree\n"); + return err; } - err = get_port_ref(*dev_node, rx_port); - if (err < 0) { - dev_err(dev, "Cannot read OH port node in device tree\n"); + err = get_port_ref(dev_node, rx_port); + if (err) { + dev_err(dev, "Cannot read Rx OH port node in device tree\n"); return err; } - dev_node = of_find_node_by_phandle(ports_handle[TX]); - if (unlikely(dev_node == NULL)) { - dev_err(dev, "Cannot find OH port node in device tree\n"); + dev_node = of_parse_phandle(onic_node, "fsl,oh-ports", TX); + if (dev_node == NULL) { + dev_err(dev, "Cannot find Tx OH port node in device tree\n"); return -EFAULT; } - err = get_port_ref(*dev_node, tx_port); - if (err < 0) { - dev_err(dev, "Cannot read OH port node in device tree\n"); + err = get_port_ref(dev_node, tx_port); + if (err) { + dev_err(dev, "Cannot read Tx OH port node in device tree\n"); return err; } |