* Re: ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x02000020 DMADBG_7=0x00008040
From: Sujith Manoharan @ 2012-03-27 2:17 UTC (permalink / raw)
To: Justin P. Mattock
Cc: Mohammed Shafi, Linux-wireless, Felix Fietkau,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linux-netdev
In-Reply-To: <4F6FA388.9080408-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Justin P. Mattock wrote:
> I would have to say this patch above does get rid of this crash I was
> seeing. as a quick test I simply connect to a WPA network, then connect
> to an open network going back and forth triggers this freeze for me
> after applying this I am able to toggle back and forth without a freeze.
Thanks for verifying.
Sujith
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] net/vlan: withdraw VLAN ID attribute from GVRP on VLAN device stop
From: Ward, David - 0663 - MITLL @ 2012-03-27 1:35 UTC (permalink / raw)
To: David Miller; +Cc: jorge@dti2.net, netdev@vger.kernel.org
In-Reply-To: <20120326.174216.151181141269420661.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 2194 bytes --]
On 03/26/2012 05:42 PM, David Miller wrote:
> From: "Ward, David - 0663 - MITLL"<david.ward@ll.mit.edu>
> Date: Mon, 26 Mar 2012 11:50:16 -0400
>
>> If I create an interface that is initially down, then bring it up, and
>> finally bring it back down, I think it should return to the state it
>> was in initially. So in my opinion, either the GVRP attribute should
>> exist while the interface is down, or it shouldn't.
> You're whole argument breaks down because we definitely don't do this
> for IPv4 addresses, we'll keep receiving traffic for IPv4 addresses
> configured on that interface when received on other interfaces which
> are still up, even when you bring that interface down.
... but that also seems to work if you never bring the interface up. I
can create a dummy interface, set an IP address on it, and immediately
receive traffic on that IP address from another interface, without ever
having brought the dummy interface up. (The behavior after setting the
interface down is the same as before the interface was ever brought up.)
Instead with GVRP, I create an interface and set the GVRP flag on it,
but GVRP does not declare the attribute for that VLAN until you bring
the VLAN interface up the first time. However it doesn't withdraw the
attribute when you bring the VLAN interface down, only when you delete it.
So to approach this differently -- would there be anything wrong with
GVRP declaring the attribute as soon as the GVRP flag is set, even if
the VLAN interface has not come up yet? The user might do this to
deliberately give the switching infrastructure a head start, so that
(for example) the IPv6 DAD packets that are sent as soon as the VLAN
interface comes up make it to all participants on the LAN...right now
you can't do that. You could still choose not to set the GVRP flag on
the interface until you bring it up, similar to what you were saying.
Then each attribute declaration event would have an opposite attribute
withdrawal event. This means if we tried to create an attribute that
already existed and wasn't in the "leaving" state, it would alert us to
a bug.
Thoughts?
David
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4558 bytes --]
^ permalink raw reply
* Wrong use of MAX_JIFFY_OFFSET?
From: Liu Yu @ 2012-03-27 1:25 UTC (permalink / raw)
To: netdev
Hi guys,
I saw a couple of places in current kernel have this kind of code:
> static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
> {
> unsigned long end = jiffies;
>
> if (end >= start)
> return jiffies_to_msecs(end - start);
>
> return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
> }
As you know, jiffies has a type of unsigned long, so if we know which is the
end and
which is the start, then (end - start) can simply figure out how much
jiffies flies,
without worry about the overflow.
Look at the code above, assume that there is just an overflow happening on
jiffies: end=0 and start=~0UL.
Since end < start, then the return value of the function is
jiffies_to_msecs(MAX_JIFFY_OFFSET+2).
But shouldn't the correct value be jiffies_to_msecs(1)?
could someone tell me that am I missing anything?
Thanks,
Yu
^ permalink raw reply
* RE: [PATCH 1/1] net/hyperv: Add flow control based on hi/low watermark
From: Haiyang Zhang @ 2012-03-27 1:17 UTC (permalink / raw)
To: Greg KH
Cc: davem@davemloft.net, netdev@vger.kernel.org,
devel@linuxdriverproject.org, olaf@aepfle.de,
linux-kernel@vger.kernel.org
In-Reply-To: <20120326231017.GA30684@kroah.com>
> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Monday, March 26, 2012 7:10 PM
> To: Haiyang Zhang
> Cc: davem@davemloft.net; netdev@vger.kernel.org;
> devel@linuxdriverproject.org; olaf@aepfle.de; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 1/1] net/hyperv: Add flow control based on hi/low
> watermark
>
> On Mon, Mar 26, 2012 at 03:18:24PM -0700, Haiyang Zhang wrote:
> > In the existing code, we only stop queue when the ringbuffer is full,
> > so the current packet has to be dropped or retried from upper layer.
> >
> > This patch stops the tx queue when available ringbuffer is below the
> > low watermark. So the ringbuffer still has small amount of space
> > available for the current packet. This will reduce the overhead of
> > retries on sending.
> >
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
> > ---
> > drivers/hv/ring_buffer.c | 15 +++++++++++++++
> > drivers/net/hyperv/hyperv_net.h | 3 +++
> > drivers/net/hyperv/netvsc.c | 23 +++++++++++++++++++----
> > drivers/net/hyperv/netvsc_drv.c | 16 +++++++++++++++-
> > include/linux/hyperv.h | 3 +++
> > 5 files changed, 55 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index
> > 8af25a0..8cc3f63 100644
> > --- a/drivers/hv/ring_buffer.c
> > +++ b/drivers/hv/ring_buffer.c
> > @@ -23,6 +23,7 @@
> > */
> > #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> >
> > +#include <linux/module.h>
> > #include <linux/kernel.h>
> > #include <linux/mm.h>
> > #include <linux/hyperv.h>
> > @@ -160,6 +161,20 @@ hv_get_ring_buffersize(struct
> hv_ring_buffer_info
> > *ring_info) }
> >
> > /*
> > + * Get the percentage of available bytes to write in the ring.
> > + * The return value is in range from 0 to 100.
> > + */
> > +u32 hv_ringbuf_avail_percent(struct hv_ring_buffer_info *ring_info) {
> > + u32 avail_read, avail_write;
> > +
> > + hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
> > +
> > + return avail_write * 100 / hv_get_ring_buffersize(ring_info);
> > +}
> > +EXPORT_SYMBOL(hv_ringbuf_avail_percent);
>
> That makes no sense, what happens 1 second later to the buffer? You can't
> expect this result to be valid anymore, right?
It's not necessary to be very precise for the flow control, just a rough
estimate on how full the buffer is enough. We only want to keep a small
amount of buffer to be available, so the outgoing packets don't need to
be retried.
> > --- a/drivers/net/hyperv/netvsc_drv.c
> > +++ b/drivers/net/hyperv/netvsc_drv.c
> > @@ -51,6 +51,16 @@ static int ring_size = 128;
> > module_param(ring_size, int, S_IRUGO); MODULE_PARM_DESC(ring_size,
> > "Ring buffer size (# of pages)");
> >
> > +uint ring_avail_percent_hiwater = 20;
> > +module_param(ring_avail_percent_hiwater, uint, S_IRUGO | S_IWUSR);
> > +MODULE_PARM_DESC(ring_avail_percent_hiwater,
> > + "Ring buffer available percentiles to wake up xmit queue");
> > +
> > +uint ring_avail_percent_lowater = 10;
> > +module_param(ring_avail_percent_lowater, uint, S_IRUGO | S_IWUSR);
> > +MODULE_PARM_DESC(ring_avail_percent_lowater,
> > + "Ring buffer available percentiles to stop xmit queue");
>
> Eeek, no, how in the world is someone supposed to know to set these things?
>
> Please make this work "automatically", otherwise no one will ever get it right.
> Don't make it tunable as a way out of making a decision on how the driver
> should work.
I will remove the tunables. The default values here work fine in our tests.
Thanks,
- Haiyang
^ permalink raw reply
* Business Project
From: Gao Yingxin @ 2012-03-27 1:15 UTC (permalink / raw)
Hello ,
I seek your attention for the confirmation of fund transfer to your
country. I shall provide you with detailed information once i hear from
you.
Best Regards.
Mr.Gao Yingxin
^ permalink raw reply
* [PATCH 4/5] staging: octeon_ethernet: Convert to use device tree.
From: David Daney @ 2012-03-27 0:27 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
Cc: linux-kernel, David Daney, netdev, Greg Kroah-Hartman
In-Reply-To: <1332808075-8333-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
Get MAC address and PHY connection from the device tree. The driver
is converted to a platform driver.
Cc: netdev@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David Daney <david.daney@cavium.com>
---
Should probably go via Ralf's linux-mips.org tree.
drivers/staging/octeon/ethernet-mdio.c | 28 +++---
drivers/staging/octeon/ethernet.c | 153 +++++++++++++++++++-----------
drivers/staging/octeon/octeon-ethernet.h | 3 +
3 files changed, 117 insertions(+), 67 deletions(-)
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index e31949c..f15b31b 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -28,6 +28,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/ratelimit.h>
+#include <linux/of_mdio.h>
#include <net/dst.h>
@@ -161,22 +162,23 @@ static void cvm_oct_adjust_link(struct net_device *dev)
int cvm_oct_phy_setup_device(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
+ struct device_node *phy_node;
- int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
- if (phy_addr != -1) {
- char phy_id[MII_BUS_ID_SIZE + 3];
+ if (!priv->of_node)
+ return 0;
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr);
+ phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
+ if (!phy_node)
+ return 0;
- priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
- PHY_INTERFACE_MODE_GMII);
+ priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
+
+ if (priv->phydev == NULL)
+ return -ENODEV;
+
+ priv->last_link = 0;
+ phy_start_aneg(priv->phydev);
- if (IS_ERR(priv->phydev)) {
- priv->phydev = NULL;
- return -1;
- }
- priv->last_link = 0;
- phy_start_aneg(priv->phydev);
- }
return 0;
}
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 9112cd8..7df97fc 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -24,6 +24,7 @@
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
**********************************************************************/
+#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -31,6 +32,7 @@
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <linux/of_net.h>
#include <net/dst.h>
@@ -112,15 +114,6 @@ int rx_napi_weight = 32;
module_param(rx_napi_weight, int, 0444);
MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");
-/*
- * The offset from mac_addr_base that should be used for the next port
- * that is configured. By convention, if any mgmt ports exist on the
- * chip, they get the first mac addresses, The ports controlled by
- * this driver are numbered sequencially following any mgmt addresses
- * that may exist.
- */
-static unsigned int cvm_oct_mac_addr_offset;
-
/**
* cvm_oct_poll_queue - Workqueue for polling operations.
*/
@@ -175,7 +168,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work)
queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ);
}
-static __init void cvm_oct_configure_common_hw(void)
+static __devinit void cvm_oct_configure_common_hw(void)
{
/* Setup the FPA */
cvmx_fpa_enable();
@@ -395,23 +388,21 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev)
* Returns Zero on success
*/
-static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
+static int cvm_oct_set_mac_filter(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
union cvmx_gmxx_prtx_cfg gmx_cfg;
int interface = INTERFACE(priv->port);
int index = INDEX(priv->port);
- memcpy(dev->dev_addr, addr + 2, 6);
-
if ((interface < 2)
&& (cvmx_helper_interface_get_mode(interface) !=
CVMX_HELPER_INTERFACE_MODE_SPI)) {
int i;
- uint8_t *ptr = addr;
+ uint8_t *ptr = dev->dev_addr;
uint64_t mac = 0;
for (i = 0; i < 6; i++)
- mac = (mac << 8) | (uint64_t) (ptr[i + 2]);
+ mac = (mac << 8) | (uint64_t)ptr[i];
gmx_cfg.u64 =
cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
@@ -420,17 +411,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface),
- ptr[2]);
+ ptr[0]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface),
- ptr[3]);
+ ptr[1]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface),
- ptr[4]);
+ ptr[2]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface),
- ptr[5]);
+ ptr[3]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface),
- ptr[6]);
+ ptr[4]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface),
- ptr[7]);
+ ptr[5]);
cvm_oct_common_set_multicast_list(dev);
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface),
gmx_cfg.u64);
@@ -438,6 +429,15 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
return 0;
}
+static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
+{
+ int r = eth_mac_addr(dev, addr);
+
+ if (r)
+ return r;
+ return cvm_oct_set_mac_filter(dev);
+}
+
/**
* cvm_oct_common_init - per network device initialization
* @dev: Device to initialize
@@ -447,26 +447,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
int cvm_oct_common_init(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
- struct sockaddr sa;
- u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
- ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
- ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
- ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
- ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
- (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);
-
- mac += cvm_oct_mac_addr_offset;
- sa.sa_data[0] = (mac >> 40) & 0xff;
- sa.sa_data[1] = (mac >> 32) & 0xff;
- sa.sa_data[2] = (mac >> 24) & 0xff;
- sa.sa_data[3] = (mac >> 16) & 0xff;
- sa.sa_data[4] = (mac >> 8) & 0xff;
- sa.sa_data[5] = mac & 0xff;
-
- if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
- printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
- " %pM\n", dev->name, sa.sa_data);
- cvm_oct_mac_addr_offset++;
+ const u8 *mac = NULL;
+
+ if (priv->of_node)
+ mac = of_get_mac_address(priv->of_node);
+
+ if (mac && is_valid_ether_addr(mac)) {
+ memcpy(dev->dev_addr, mac, ETH_ALEN);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
+ } else {
+ eth_hw_addr_random(dev);
+ }
/*
* Force the interface to use the POW send if always_use_pow
@@ -487,7 +478,7 @@ int cvm_oct_common_init(struct net_device *dev)
SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
cvm_oct_phy_setup_device(dev);
- dev->netdev_ops->ndo_set_mac_address(dev, &sa);
+ cvm_oct_set_mac_filter(dev);
dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
/*
@@ -594,22 +585,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
extern void octeon_mdiobus_force_mod_depencency(void);
-static int __init cvm_oct_init_module(void)
+static struct device_node * __devinit cvm_oct_of_get_child(const struct device_node *parent,
+ int reg_val)
+{
+ struct device_node *node = NULL;
+ int size;
+ const __be32 *addr;
+
+ for (;;) {
+ node = of_get_next_child(parent, node);
+ if (!node)
+ break;
+ addr = of_get_property(node, "reg", &size);
+ if (addr && (be32_to_cpu(*addr) == reg_val))
+ break;
+ }
+ return node;
+}
+
+static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *pip,
+ int interface, int port)
+{
+ struct device_node *ni, *np;
+
+ ni = cvm_oct_of_get_child(pip, interface);
+ if (!ni)
+ return NULL;
+
+ np = cvm_oct_of_get_child(ni, port);
+ of_node_put(ni);
+
+ return np;
+}
+
+static int __devinit cvm_oct_probe(struct platform_device *pdev)
{
int num_interfaces;
int interface;
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos;
+ struct device_node *pip;
octeon_mdiobus_force_mod_depencency();
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
- if (OCTEON_IS_MODEL(OCTEON_CN52XX))
- cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
- else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
- else
- cvm_oct_mac_addr_offset = 0;
+ pip = pdev->dev.of_node;
+ if (!pip) {
+ pr_err("Error: No 'pip' in /aliases\n");
+ return -EINVAL;
+ }
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
if (cvm_oct_poll_queue == NULL) {
@@ -688,10 +712,11 @@ static int __init cvm_oct_init_module(void)
cvmx_helper_interface_get_mode(interface);
int num_ports = cvmx_helper_ports_on_interface(interface);
int port;
+ int port_index;
- for (port = cvmx_helper_get_ipd_port(interface, 0);
+ for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
port < cvmx_helper_get_ipd_port(interface, num_ports);
- port++) {
+ port_index++, port++) {
struct octeon_ethernet *priv;
struct net_device *dev =
alloc_etherdev(sizeof(struct octeon_ethernet));
@@ -702,6 +727,7 @@ static int __init cvm_oct_init_module(void)
/* Initialize the device private structure. */
priv = netdev_priv(dev);
+ priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);
INIT_DELAYED_WORK(&priv->port_periodic_work,
cvm_oct_periodic_worker);
@@ -786,7 +812,7 @@ static int __init cvm_oct_init_module(void)
return 0;
}
-static void __exit cvm_oct_cleanup_module(void)
+static int __devexit cvm_oct_remove(struct platform_device *pdev)
{
int port;
@@ -834,10 +860,29 @@ static void __exit cvm_oct_cleanup_module(void)
if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
+ return 0;
}
+static struct of_device_id cvm_oct_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-pip",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cvm_oct_match);
+
+static struct platform_driver cvm_oct_driver = {
+ .probe = cvm_oct_probe,
+ .remove = __devexit_p(cvm_oct_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .of_match_table = cvm_oct_match,
+ },
+};
+
+module_platform_driver(cvm_oct_driver);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver.");
-module_init(cvm_oct_init_module);
-module_exit(cvm_oct_cleanup_module);
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index d581925..9360e22 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -31,6 +31,8 @@
#ifndef OCTEON_ETHERNET_H
#define OCTEON_ETHERNET_H
+#include <linux/of.h>
+
/**
* This is the definition of the Ethernet driver's private
* driver state stored in netdev_priv(dev).
@@ -59,6 +61,7 @@ struct octeon_ethernet {
void (*poll) (struct net_device *dev);
struct delayed_work port_periodic_work;
struct work_struct port_work; /* may be unused. */
+ struct device_node *of_node;
};
int cvm_oct_free_work(void *work_queue_entry);
--
1.7.2.3
^ permalink raw reply related
* [PATCH 3/5] netdev: octeon_mgmt: Convert to use device tree.
From: David Daney @ 2012-03-27 0:27 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
Cc: linux-kernel, David Daney, netdev
In-Reply-To: <1332808075-8333-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
The device tree will supply the register bank base addresses, make
register addressing relative to those. PHY connection is now
described by the device tree.
The OCTEON_IRQ_MII{0,1} symbols are also removed as they are now
unused and interfere with the irq_domain used for device tree irq
mapping.
Cc: netdev@vger.kernel.org
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: David Daney <david.daney@cavium.com>
---
Should probably go via Ralf's linux-mips.org tree.
arch/mips/cavium-octeon/octeon-irq.c | 2 -
arch/mips/cavium-octeon/octeon-platform.c | 62 ------
drivers/net/ethernet/octeon/octeon_mgmt.c | 312 +++++++++++++++++++----------
3 files changed, 207 insertions(+), 169 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 7912f96..76f1364 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1181,7 +1181,6 @@ static void __init octeon_irq_init_ciu(void)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
/* CIU_1 */
@@ -1190,7 +1189,6 @@ static void __init octeon_irq_init_ciu(void)
octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
- octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
if (gpio_node) {
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 66cabc2..0938df1 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,68 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon mgmt port Ethernet interface. */
-static int __init octeon_mgmt_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
- int port, num_ports;
-
- struct resource mgmt_port_resource = {
- .flags = IORESOURCE_IRQ,
- .start = -1,
- .end = -1
- };
-
- if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
- return 0;
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX))
- num_ports = 1;
- else
- num_ports = 2;
-
- for (port = 0; port < num_ports; port++) {
- pd = platform_device_alloc("octeon_mgmt", port);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
- /* No DMA restrictions */
- pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
- pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
-
- switch (port) {
- case 0:
- mgmt_port_resource.start = OCTEON_IRQ_MII0;
- break;
- case 1:
- mgmt_port_resource.start = OCTEON_IRQ_MII1;
- break;
- default:
- BUG();
- }
- mgmt_port_resource.end = mgmt_port_resource.start;
-
- ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
-
- if (ret)
- goto fail;
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
- }
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mgmt_device_init);
-
#ifdef CONFIG_USB
static int __init octeon_ehci_device_init(void)
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index cd827ff..c42bbb1 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -6,19 +6,21 @@
* Copyright (C) 2009 Cavium Networks
*/
-#include <linux/capability.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/capability.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if.h>
+#include <linux/spinlock.h>
#include <linux/if_vlan.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/of_net.h>
+#include <linux/init.h>
#include <linux/slab.h>
#include <linux/phy.h>
-#include <linux/spinlock.h>
+#include <linux/io.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-mixx-defs.h>
@@ -58,8 +60,56 @@ union mgmt_port_ring_entry {
} s;
};
+#define MIX_ORING1 0x0
+#define MIX_ORING2 0x8
+#define MIX_IRING1 0x10
+#define MIX_IRING2 0x18
+#define MIX_CTL 0x20
+#define MIX_IRHWM 0x28
+#define MIX_IRCNT 0x30
+#define MIX_ORHWM 0x38
+#define MIX_ORCNT 0x40
+#define MIX_ISR 0x48
+#define MIX_INTENA 0x50
+#define MIX_REMCNT 0x58
+#define MIX_BIST 0x78
+
+#define AGL_GMX_PRT_CFG 0x10
+#define AGL_GMX_RX_FRM_CTL 0x18
+#define AGL_GMX_RX_FRM_MAX 0x30
+#define AGL_GMX_RX_JABBER 0x38
+#define AGL_GMX_RX_STATS_CTL 0x50
+
+#define AGL_GMX_RX_STATS_PKTS_DRP 0xb0
+#define AGL_GMX_RX_STATS_OCTS_DRP 0xb8
+#define AGL_GMX_RX_STATS_PKTS_BAD 0xc0
+
+#define AGL_GMX_RX_ADR_CTL 0x100
+#define AGL_GMX_RX_ADR_CAM_EN 0x108
+#define AGL_GMX_RX_ADR_CAM0 0x180
+#define AGL_GMX_RX_ADR_CAM1 0x188
+#define AGL_GMX_RX_ADR_CAM2 0x190
+#define AGL_GMX_RX_ADR_CAM3 0x198
+#define AGL_GMX_RX_ADR_CAM4 0x1a0
+#define AGL_GMX_RX_ADR_CAM5 0x1a8
+
+#define AGL_GMX_TX_STATS_CTL 0x268
+#define AGL_GMX_TX_CTL 0x270
+#define AGL_GMX_TX_STAT0 0x280
+#define AGL_GMX_TX_STAT1 0x288
+#define AGL_GMX_TX_STAT2 0x290
+#define AGL_GMX_TX_STAT3 0x298
+#define AGL_GMX_TX_STAT4 0x2a0
+#define AGL_GMX_TX_STAT5 0x2a8
+#define AGL_GMX_TX_STAT6 0x2b0
+#define AGL_GMX_TX_STAT7 0x2b8
+#define AGL_GMX_TX_STAT8 0x2c0
+#define AGL_GMX_TX_STAT9 0x2c8
+
struct octeon_mgmt {
struct net_device *netdev;
+ u64 mix;
+ u64 agl;
int port;
int irq;
u64 *tx_ring;
@@ -85,31 +135,34 @@ struct octeon_mgmt {
struct napi_struct napi;
struct tasklet_struct tx_clean_tasklet;
struct phy_device *phydev;
+ struct device_node *phy_np;
+ resource_size_t mix_phys;
+ resource_size_t mix_size;
+ resource_size_t agl_phys;
+ resource_size_t agl_size;
};
static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.ithena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
{
- int port = p->port;
union cvmx_mixx_intena mix_intena;
unsigned long flags;
spin_lock_irqsave(&p->lock, flags);
- mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+ mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.othena = enable ? 1 : 0;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -146,7 +199,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size)
static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
unsigned int size;
@@ -177,24 +229,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
(p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
p->rx_current_fill++;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_IRING2, 1);
}
}
static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
{
- int port = p->port;
union cvmx_mixx_orcnt mix_orcnt;
union mgmt_port_ring_entry re;
struct sk_buff *skb;
int cleaned = 0;
unsigned long flags;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
while (mix_orcnt.s.orcnt) {
spin_lock_irqsave(&p->tx_list.lock, flags);
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
if (mix_orcnt.s.orcnt == 0) {
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -214,7 +265,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
mix_orcnt.s.orcnt = 1;
/* Acknowledge to hardware that we have the buffer. */
- cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64);
+ cvmx_write_csr(p->mix + MIX_ORCNT, mix_orcnt.u64);
p->tx_current_fill--;
spin_unlock_irqrestore(&p->tx_list.lock, flags);
@@ -224,7 +275,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
dev_kfree_skb_any(skb);
cleaned++;
- mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+ mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
}
if (cleaned && netif_queue_stopped(p->netdev))
@@ -241,13 +292,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
u64 drop, bad;
/* These reads also clear the count registers. */
- drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port));
- bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port));
+ drop = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP);
+ bad = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD);
if (drop || bad) {
/* Do an atomic update. */
@@ -261,15 +311,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
unsigned long flags;
union cvmx_agl_gmx_txx_stat0 s0;
union cvmx_agl_gmx_txx_stat1 s1;
/* These reads also clear the count registers. */
- s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port));
- s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port));
+ s0.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT0);
+ s1.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT1);
if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
/* Do an atomic update. */
@@ -308,7 +357,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
{
- int port = p->port;
struct net_device *netdev = p->netdev;
union cvmx_mixx_ircnt mix_ircnt;
union mgmt_port_ring_entry re;
@@ -381,18 +429,17 @@ done:
/* Tell the hardware we processed a packet. */
mix_ircnt.u64 = 0;
mix_ircnt.s.ircnt = 1;
- cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64);
+ cvmx_write_csr(p->mix + MIX_IRCNT, mix_ircnt.u64);
return rc;
}
static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
{
- int port = p->port;
unsigned int work_done = 0;
union cvmx_mixx_ircnt mix_ircnt;
int rc;
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
while (work_done < budget && mix_ircnt.s.ircnt) {
rc = octeon_mgmt_receive_one(p);
@@ -400,7 +447,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
work_done++;
/* Check for more packets. */
- mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+ mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
}
octeon_mgmt_rx_fill_ring(p->netdev);
@@ -434,16 +481,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
union cvmx_agl_gmx_bist agl_gmx_bist;
mix_ctl.u64 = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.busy);
mix_ctl.s.reset = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
- cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
+ cvmx_read_csr(p->mix + MIX_CTL);
cvmx_wait(64);
- mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port));
+ mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST);
if (mix_bist.u64)
dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
(unsigned long long)mix_bist.u64);
@@ -474,7 +521,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
unsigned long flags;
@@ -520,29 +566,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
spin_lock_irqsave(&p->lock, flags);
/* Disable packet I/O. */
- agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prev_packet_enable = agl_gmx_prtx.s.en;
agl_gmx_prtx.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
adr_ctl.u64 = 0;
adr_ctl.s.cam_mode = cam_mode;
adr_ctl.s.mcst = multicast_mode;
adr_ctl.s.bcst = 1; /* Allow broadcast */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask);
/* Restore packet I/O. */
agl_gmx_prtx.s.en = prev_packet_enable;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
spin_unlock_irqrestore(&p->lock, flags);
}
@@ -564,7 +610,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
/*
@@ -580,8 +625,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER,
(size_without_fcs + 7) & 0xfff8);
return 0;
@@ -591,14 +636,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
{
struct net_device *netdev = dev_id;
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_mixx_isr mixx_isr;
- mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port));
+ mixx_isr.u64 = cvmx_read_csr(p->mix + MIX_ISR);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), mixx_isr.u64);
- cvmx_read_csr(CVMX_MIXX_ISR(port));
+ cvmx_write_csr(p->mix + MIX_ISR, mixx_isr.u64);
+ cvmx_read_csr(p->mix + MIX_ISR);
if (mixx_isr.s.irthresh) {
octeon_mgmt_disable_rx_irq(p);
@@ -629,7 +673,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
static void octeon_mgmt_adjust_link(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union cvmx_agl_gmx_prtx_cfg prtx_cfg;
unsigned long flags;
int link_changed = 0;
@@ -640,11 +683,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
link_changed = 1;
if (p->last_duplex != p->phydev->duplex) {
p->last_duplex = p->phydev->duplex;
- prtx_cfg.u64 =
- cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.duplex = p->phydev->duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
- prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
}
} else {
if (p->last_link)
@@ -670,18 +711,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
static int octeon_mgmt_init_phy(struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- char phy_id[MII_BUS_ID_SIZE + 3];
- if (octeon_is_simulation()) {
+ if (octeon_is_simulation() || p->phy_np == NULL) {
/* No PHYs in the simulator. */
netif_carrier_on(netdev);
return 0;
}
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port);
-
- p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ p->phydev = of_phy_connect(netdev, p->phy_np,
+ octeon_mgmt_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
if (IS_ERR(p->phydev)) {
p->phydev = NULL;
@@ -737,14 +776,14 @@ static int octeon_mgmt_open(struct net_device *netdev)
octeon_mgmt_reset_hw(p);
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
/* Bring it out of reset if needed. */
if (mix_ctl.s.reset) {
mix_ctl.s.reset = 0;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do {
- mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+ mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.reset);
}
@@ -755,17 +794,17 @@ static int octeon_mgmt_open(struct net_device *netdev)
oring1.u64 = 0;
oring1.s.obase = p->tx_ring_handle >> 3;
oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
+ cvmx_write_csr(p->mix + MIX_ORING1, oring1.u64);
iring1.u64 = 0;
iring1.s.ibase = p->rx_ring_handle >> 3;
iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
- cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
+ cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64);
/* Disable packet I/O. */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
octeon_mgmt_set_mac_address(netdev, &sa);
@@ -782,7 +821,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
mix_ctl.s.nbtarb = 0; /* Arbitration mode */
/* MII CB-request FIFO programmable high watermark */
mix_ctl.s.mrq_hwm = 1;
- cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+ cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
|| OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
@@ -809,16 +848,16 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Clear statistics. */
/* Clear on read. */
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD, 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0);
- cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STATS_CTL, 1);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT0, 0);
+ cvmx_write_csr(p->agl + AGL_GMX_TX_STAT1, 0);
/* Clear any pending interrupts */
- cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port)));
+ cvmx_write_csr(p->mix + MIX_ISR, cvmx_read_csr(p->mix + MIX_ISR));
if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
netdev)) {
@@ -829,18 +868,18 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Interrupt every single RX packet */
mix_irhwm.u64 = 0;
mix_irhwm.s.irhwm = 0;
- cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64);
+ cvmx_write_csr(p->mix + MIX_IRHWM, mix_irhwm.u64);
/* Interrupt when we have 1 or more packets to clean. */
mix_orhwm.u64 = 0;
mix_orhwm.s.orhwm = 1;
- cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64);
+ cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64);
/* Enable receive and transmit interrupts */
mix_intena.u64 = 0;
mix_intena.s.ithena = 1;
mix_intena.s.othena = 1;
- cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+ cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
/* Enable packet I/O. */
@@ -871,7 +910,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
* frame. GMX checks that the PREAMBLE is sent correctly.
*/
rxx_frm_ctl.s.pre_chk = 1;
- cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
/* Enable the AGL block */
agl_gmx_inf_mode.u64 = 0;
@@ -879,13 +918,13 @@ static int octeon_mgmt_open(struct net_device *netdev)
cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
/* Configure the port duplex and enables */
- prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+ prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.tx_en = 1;
prtx_cfg.s.rx_en = 1;
prtx_cfg.s.en = 1;
p->last_duplex = 1;
prtx_cfg.s.duplex = p->last_duplex;
- cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+ cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
p->last_link = 0;
netif_carrier_off(netdev);
@@ -949,7 +988,6 @@ static int octeon_mgmt_stop(struct net_device *netdev)
static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct octeon_mgmt *p = netdev_priv(netdev);
- int port = p->port;
union mgmt_port_ring_entry re;
unsigned long flags;
int rv = NETDEV_TX_BUSY;
@@ -993,7 +1031,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->stats.tx_bytes += skb->len;
/* Ring the bell. */
- cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+ cvmx_write_csr(p->mix + MIX_ORING2, 1);
rv = NETDEV_TX_OK;
out:
@@ -1071,10 +1109,14 @@ static const struct net_device_ops octeon_mgmt_ops = {
static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
{
- struct resource *res_irq;
struct net_device *netdev;
struct octeon_mgmt *p;
- int i;
+ const __be32 *data;
+ const u8 *mac;
+ struct resource *res_mix;
+ struct resource *res_agl;
+ int len;
+ int result;
netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
if (netdev == NULL)
@@ -1088,14 +1130,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
p->netdev = netdev;
p->dev = &pdev->dev;
- p->port = pdev->id;
+ data = of_get_property(pdev->dev.of_node, "cell-index", &len);
+ if (data && len == sizeof(*data)) {
+ p->port = be32_to_cpup(data);
+ } else {
+ dev_err(&pdev->dev, "no 'cell-index' property\n");
+ result = -ENXIO;
+ goto err;
+ }
+
snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res_irq)
+ result = platform_get_irq(pdev, 0);
+ if (result < 0)
+ goto err;
+
+ p->irq = result;
+
+ res_mix = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res_mix == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
+ goto err;
+ }
+
+ res_agl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_agl == NULL) {
+ dev_err(&pdev->dev, "no 'reg' resource\n");
+ result = -ENXIO;
+ goto err;
+ }
+
+ p->mix_phys = res_mix->start;
+ p->mix_size = resource_size(res_mix);
+ p->agl_phys = res_agl->start;
+ p->agl_size = resource_size(res_agl);
+
+
+ if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size,
+ res_mix->name)) {
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_mix->name);
+ result = -ENXIO;
+ goto err;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, p->agl_phys, p->agl_size,
+ res_agl->name)) {
+ result = -ENXIO;
+ dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
+ res_agl->name);
goto err;
+ }
+
+
+ p->mix = (u64)devm_ioremap(&pdev->dev, p->mix_phys, p->mix_size);
+ p->agl = (u64)devm_ioremap(&pdev->dev, p->agl_phys, p->agl_size);
- p->irq = res_irq->start;
spin_lock_init(&p->lock);
skb_queue_head_init(&p->tx_list);
@@ -1108,24 +1199,26 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
- /* The mgmt ports get the first N MACs. */
- for (i = 0; i < 6; i++)
- netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i];
- netdev->dev_addr[5] += p->port;
+ mac = of_get_mac_address(pdev->dev.of_node);
+
+ if (mac)
+ memcpy(netdev->dev_addr, mac, 6);
- if (p->port >= octeon_bootinfo->mac_addr_count)
- dev_err(&pdev->dev,
- "Error %s: Using MAC outside of the assigned range: %pM\n",
- netdev->name, netdev->dev_addr);
+ p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
- if (register_netdev(netdev))
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ result = register_netdev(netdev);
+ if (result)
goto err;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
+
err:
free_netdev(netdev);
- return -ENOENT;
+ return result;
}
static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
@@ -1137,10 +1230,19 @@ static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
return 0;
}
+static struct of_device_id octeon_mgmt_match[] = {
+ {
+ .compatible = "cavium,octeon-5750-mix",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mgmt_match);
+
static struct platform_driver octeon_mgmt_driver = {
.driver = {
.name = "octeon_mgmt",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mgmt_match,
},
.probe = octeon_mgmt_probe,
.remove = __devexit_p(octeon_mgmt_remove),
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/5] netdev: mdio-octeon.c: Convert to use device tree.
From: David Daney @ 2012-03-27 0:27 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
Cc: linux-kernel, David Daney, netdev
In-Reply-To: <1332808075-8333-1-git-send-email-ddaney.cavm@gmail.com>
From: David Daney <david.daney@cavium.com>
Get the MDIO bus controller addresses from the device tree, small
clean up in use of devm_*
Remove, now unused, platform device setup code.
Cc: netdev@vger.kernel.org
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: David Daney <david.daney@cavium.com>
---
Should probably go via Ralf's linux-mips.org tree.
arch/mips/cavium-octeon/octeon-platform.c | 30 ---------
drivers/net/phy/mdio-octeon.c | 92 ++++++++++++++++++-----------
2 files changed, 58 insertions(+), 64 deletions(-)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index f62a40f..66cabc2 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -168,36 +168,6 @@ out:
}
device_initcall(octeon_rng_device_init);
-/* Octeon SMI/MDIO interface. */
-static int __init octeon_mdiobus_device_init(void)
-{
- struct platform_device *pd;
- int ret = 0;
-
- if (octeon_is_simulation())
- return 0; /* No mdio in the simulator. */
-
- /* The bus number is the platform_device id. */
- pd = platform_device_alloc("mdio-octeon", 0);
- if (!pd) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = platform_device_add(pd);
- if (ret)
- goto fail;
-
- return ret;
-fail:
- platform_device_put(pd);
-
-out:
- return ret;
-
-}
-device_initcall(octeon_mdiobus_device_init);
-
/* Octeon mgmt port Ethernet interface. */
static int __init octeon_mgmt_device_init(void)
{
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index 826d961..d4015aa 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -3,14 +3,17 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2009 Cavium Networks
+ * Copyright (C) 2009,2011 Cavium, Inc.
*/
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
#include <linux/phy.h>
+#include <linux/io.h>
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-smix-defs.h>
@@ -18,9 +21,17 @@
#define DRV_VERSION "1.0"
#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
+#define SMI_CMD 0x0
+#define SMI_WR_DAT 0x8
+#define SMI_RD_DAT 0x10
+#define SMI_CLK 0x18
+#define SMI_EN 0x20
+
struct octeon_mdiobus {
struct mii_bus *mii_bus;
- int unit;
+ u64 register_base;
+ resource_size_t mdio_phys;
+ resource_size_t regsize;
int phy_irq[PHY_MAX_ADDR];
};
@@ -35,15 +46,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
+ __delay(1000);
+ smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT);
} while (smi_rd.s.pending && --timeout);
if (smi_rd.s.val)
@@ -62,21 +73,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
smi_wr.u64 = 0;
smi_wr.s.dat = val;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
+ cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64);
smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum;
- cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+ cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do {
/*
* Wait 1000 clocks so we don't saturate the RSL bus
* doing reads.
*/
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
+ __delay(1000);
+ smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT);
} while (smi_wr.s.pending && --timeout);
if (timeout <= 0)
@@ -88,38 +99,44 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
{
struct octeon_mdiobus *bus;
+ struct resource *res_mem;
union cvmx_smix_en smi_en;
- int i;
int err = -ENOENT;
bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
if (!bus)
return -ENOMEM;
- /* The platform_device id is our unit number. */
- bus->unit = pdev->id;
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res_mem == NULL) {
+ dev_err(&pdev->dev, "found no memory resource\n");
+ err = -ENXIO;
+ goto fail;
+ }
+ bus->mdio_phys = res_mem->start;
+ bus->regsize = resource_size(res_mem);
+ if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
+ res_mem->name)) {
+ dev_err(&pdev->dev, "request_mem_region failed\n");
+ goto fail;
+ }
+ bus->register_base =
+ (u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize);
bus->mii_bus = mdiobus_alloc();
if (!bus->mii_bus)
- goto err;
+ goto fail;
smi_en.u64 = 0;
smi_en.s.en = 1;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
-
- /*
- * Standard Octeon evaluation boards don't support phy
- * interrupts, we need to poll.
- */
- for (i = 0; i < PHY_MAX_ADDR; i++)
- bus->phy_irq[i] = PHY_POLL;
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
bus->mii_bus->priv = bus;
bus->mii_bus->irq = bus->phy_irq;
bus->mii_bus->name = "mdio-octeon";
- snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
- bus->mii_bus->name, bus->unit);
+ snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
bus->mii_bus->parent = &pdev->dev;
bus->mii_bus->read = octeon_mdiobus_read;
@@ -127,20 +144,18 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, bus);
- err = mdiobus_register(bus->mii_bus);
+ err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
if (err)
- goto err_register;
+ goto fail_register;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0;
-err_register:
+fail_register:
mdiobus_free(bus->mii_bus);
-
-err:
- devm_kfree(&pdev->dev, bus);
+fail:
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
return err;
}
@@ -154,14 +169,23 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
mdiobus_unregister(bus->mii_bus);
mdiobus_free(bus->mii_bus);
smi_en.u64 = 0;
- cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
+ cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
return 0;
}
+static struct of_device_id octeon_mdiobus_match[] = {
+ {
+ .compatible = "cavium,octeon-3860-mdio",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
+
static struct platform_driver octeon_mdiobus_driver = {
.driver = {
.name = "mdio-octeon",
.owner = THIS_MODULE,
+ .of_match_table = octeon_mdiobus_match,
},
.probe = octeon_mdiobus_probe,
.remove = __devexit_p(octeon_mdiobus_remove),
--
1.7.2.3
^ permalink raw reply related
* [PATCH 0/5] MIPS: OCTEON: Convert some device to use Device Tree.
From: David Daney @ 2012-03-27 0:27 UTC (permalink / raw)
To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
Cc: linux-kernel, David Daney, netdev, Greg Kroah-Hartman,
David S. Miller, Jean Delvare (PC drivers, core),
Ben Dooks (embedded platforms), Wolfram Sang (embedded platforms),
linux-i2c
From: David Daney <david.daney@cavium.com>
This patch set depends on the previous set to add Device Tree to
OCTEON. That set can be found here:
http://www.linux-mips.org/archives/linux-mips/2012-03/msg00170.html
The patches are for drivers scattered throughout the tree, but there
is an order dependency as well as the dependency mentioned above, so
it may be preferable to merge them all via Ralf's linux-mips.org tree
rather that separately via the various device sub-system maintainers.
The mdio-octeon.c and octeon_mgmt patches were already Acked-by davem.
The i2c has been seen before, but to my knowledge was never acked.
The octeon_ethernet patch is in staging and has also been seen before.
The serial patch is new.
David Daney (5):
i2c: Convert i2c-octeon.c to use device tree.
netdev: mdio-octeon.c: Convert to use device tree.
netdev: octeon_mgmt: Convert to use device tree.
staging: octeon_ethernet: Convert to use device tree.
MIPS: Octeon: Use device tree to register serial ports.
arch/mips/cavium-octeon/octeon-irq.c | 8 -
arch/mips/cavium-octeon/octeon-platform.c | 176 ----------------
arch/mips/cavium-octeon/serial.c | 134 +++++--------
arch/mips/include/asm/octeon/octeon.h | 5 -
drivers/i2c/busses/i2c-octeon.c | 94 +++++----
drivers/net/ethernet/octeon/octeon_mgmt.c | 312 +++++++++++++++++++----------
drivers/net/phy/mdio-octeon.c | 92 ++++++---
drivers/staging/octeon/ethernet-mdio.c | 28 ++--
drivers/staging/octeon/ethernet.c | 153 +++++++++-----
drivers/staging/octeon/octeon-ethernet.h | 3 +
10 files changed, 487 insertions(+), 518 deletions(-)
Cc: netdev@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
Cc: "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
Cc: "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
Cc: linux-i2c@vger.kernel.org
--
1.7.2.3
^ permalink raw reply
* [PATCH 1/2] be2net: Added function to issue mailbox cmd on MQ.
From: Parav Pandit @ 2012-03-27 0:27 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, linux-rdma-u79uwXL29TY76Z2rM5mHXA
Cc: Parav Pandit
In-Reply-To: <1332808033-29985-1-git-send-email-parav.pandit-laKkSmNT4hbQT0dZR+AlfA@public.gmane.org>
From: Parav Pandit <parav.pandit-laKkSmNT4hbQT0dZR+AlfA@public.gmane.org>
- Added generic function to issue mailbox cmd on MQ as export function.
- RoCE driver will use this before it setups its own MQ.
Signed-off-by: Parav Pandit <parav.pandit-laKkSmNT4hbQT0dZR+AlfA@public.gmane.org>
---
drivers/net/ethernet/emulex/benet/be_cmds.c | 39 +++++++++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 398fb5c..393ad05 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -15,6 +15,7 @@
* Costa Mesa, CA 92626
*/
+#include <linux/module.h>
#include "be.h"
#include "be_cmds.h"
@@ -2418,3 +2419,41 @@ err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
+
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
+{
+ struct be_adapter *adapter = netdev_priv(netdev_handle);
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *) wrb_payload;
+ struct be_cmd_req_hdr *req;
+ struct be_cmd_resp_hdr *resp;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+ resp = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
+ hdr->opcode, wrb_payload_size, wrb, NULL);
+ memcpy(req, wrb_payload, wrb_payload_size);
+ be_dws_cpu_to_le(req, wrb_payload_size);
+
+ status = be_mcc_notify_wait(adapter);
+ if (cmd_status)
+ *cmd_status = (status & 0xffff);
+ if (ext_status)
+ *ext_status = 0;
+ memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
+ be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+EXPORT_SYMBOL(be_roce_mcc_cmd);
--
1.6.0.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 0/2] be2net: Added functionality to support RoCE driver
From: Parav Pandit @ 2012-03-27 0:27 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, linux-rdma-u79uwXL29TY76Z2rM5mHXA
Cc: Parav Pandit
From: Parav Pandit <parav.pandit-laKkSmNT4hbQT0dZR+AlfA@public.gmane.org>
This patch is for netdev net-next tree. It is based on previous RFC.
Those review comments are addressed.
This patch adds functionality to support RoCE (RDMA over Ethernet) driver.
- Detecting RoCE supported adapters and creating linked list of them.
- Enabling 5 more MSIX vectors for RoCE functionality.
- Calling registered callback functions of the RoCE driver
whenever new RoCE capable device is added/removed.
- Notifying events to RoCE driver when interface is up or down.
- Provides device specific details to RoCE driver for each roce device.
- Provides low level mailbox command to be issued by RoCE driver
before it can have it own MQ.
Parav Pandit (2):
be2net: Added function to issue mailbox cmd on MQ.
be2net: Added functionality to support RoCE driver
drivers/net/ethernet/emulex/benet/Makefile | 2 +-
drivers/net/ethernet/emulex/benet/be.h | 38 ++++++-
drivers/net/ethernet/emulex/benet/be_cmds.c | 39 ++++++
drivers/net/ethernet/emulex/benet/be_cmds.h | 1 +
drivers/net/ethernet/emulex/benet/be_hw.h | 4 +-
drivers/net/ethernet/emulex/benet/be_main.c | 88 +++++++++++--
drivers/net/ethernet/emulex/benet/be_roce.c | 182 +++++++++++++++++++++++++++
drivers/net/ethernet/emulex/benet/be_roce.h | 75 +++++++++++
8 files changed, 414 insertions(+), 15 deletions(-)
create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.c
create mode 100644 drivers/net/ethernet/emulex/benet/be_roce.h
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Eric Dumazet @ 2012-03-27 0:07 UTC (permalink / raw)
To: Ben Greear; +Cc: David Miller, netdev, gregkh, Paul E. McKenney
In-Reply-To: <4F70FFE0.7070204@candelatech.com>
On Mon, 2012-03-26 at 16:46 -0700, Ben Greear wrote:
> The 3.0.21 kernel doesn't appear to have a rcu_read_lock_return(),
> so I can't use your patch below.
This patch was only to show the point (I also CCed Paul, he might have
some time to think about it, after he clears the inline stuff with
Linus)
As I said, I was referreing to you adding stuff in rcu. ;)
Unfortunately I wont have time in the near future to do so myself.
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Ben Greear @ 2012-03-26 23:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, gregkh, Paul E. McKenney
In-Reply-To: <4F70FFE0.7070204@candelatech.com>
On 03/26/2012 04:46 PM, Ben Greear wrote:
> On 03/26/2012 04:39 PM, Eric Dumazet wrote:
>> Is this problem also appears with current tree ?
>> (This could be a problem with the backport, as it was full of
>> dependencies)
>
> I don't think so..but I will double check in a bit.
3.3.0 (plus a bunch of may non-related patches) appears to
work just fine.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Ben Greear @ 2012-03-26 23:46 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, gregkh, Paul E. McKenney
In-Reply-To: <1332805148.3547.14.camel@edumazet-glaptop>
On 03/26/2012 04:39 PM, Eric Dumazet wrote:
> On Mon, 2012-03-26 at 16:06 -0700, Ben Greear wrote:
>> On 03/26/2012 02:53 PM, Ben Greear wrote:
>>> On 03/26/2012 02:49 PM, David Miller wrote:
>>>>
>>>> Looks like all of those strange undiagnosable reported Dave Jones
>>>> has been feeding us. Something in one part of the kernel leaves
>>>> a lock held, and this shows up as a warning elsewhere.
>>>
>>> Every (initial) bug printout fingers ipv6 and the 'ip' tool on my system.
>>
>> I added a patch to convert rcu_read_lock/unlock to macros so
>> that I could automatically grab the call site (_THIS_IP_)
>> and pass it into the lockdep framework instead of the (useless)
>> _THIS_IP_ in the old rcu_read_lock method which at best seems to
>> only indicate which module the issue relates to...
>
> Hi Ben
>
> Is this problem also appears with current tree ?
> (This could be a problem with the backport, as it was full of
> dependencies)
I don't think so..but I will double check in a bit.
> Also, if you use a patch to better track rcu_read_lock()/unlock(), you
> could add new macros as well to track that a particular unlock() matches
> one given lock(). (maybe returning the rcu_preempt_depth at
> rcu_read_lock() time , but maybe a more absolute ref would be better)
>
> So we could have a warning if an unlock() doesnt match the lock()
>
> inet6_dump_fib () was already a suspect but we could not find why.
The 3.0.21 kernel doesn't appear to have a rcu_read_lock_return(),
so I can't use your patch below.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Eric Dumazet @ 2012-03-26 23:39 UTC (permalink / raw)
To: Ben Greear; +Cc: David Miller, netdev, gregkh, Paul E. McKenney
In-Reply-To: <4F70F688.6050108@candelatech.com>
On Mon, 2012-03-26 at 16:06 -0700, Ben Greear wrote:
> On 03/26/2012 02:53 PM, Ben Greear wrote:
> > On 03/26/2012 02:49 PM, David Miller wrote:
> >>
> >> Looks like all of those strange undiagnosable reported Dave Jones
> >> has been feeding us. Something in one part of the kernel leaves
> >> a lock held, and this shows up as a warning elsewhere.
> >
> > Every (initial) bug printout fingers ipv6 and the 'ip' tool on my system.
>
> I added a patch to convert rcu_read_lock/unlock to macros so
> that I could automatically grab the call site (_THIS_IP_)
> and pass it into the lockdep framework instead of the (useless)
> _THIS_IP_ in the old rcu_read_lock method which at best seems to
> only indicate which module the issue relates to...
Hi Ben
Is this problem also appears with current tree ?
(This could be a problem with the backport, as it was full of
dependencies)
Also, if you use a patch to better track rcu_read_lock()/unlock(), you
could add new macros as well to track that a particular unlock() matches
one given lock(). (maybe returning the rcu_preempt_depth at
rcu_read_lock() time , but maybe a more absolute ref would be better)
So we could have a warning if an unlock() doesnt match the lock()
inet6_dump_fib () was already a suspect but we could not find why.
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 5b27fbc..d1719e3 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -362,6 +362,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
struct hlist_node *node;
struct hlist_head *head;
int res = 0;
+ int depth;
s_h = cb->args[0];
s_e = cb->args[1];
@@ -390,7 +391,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
arg.net = net;
w->args = &arg;
- rcu_read_lock();
+ depth = rcu_read_lock_return();
for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
e = 0;
head = &net->ipv6.fib_table_hash[h];
@@ -405,7 +406,7 @@ next:
}
}
out:
- rcu_read_unlock();
+ rcu_read_unlock_check(depth);
cb->args[1] = e;
cb->args[0] = h;
^ permalink raw reply related
* Re: [PATCH] net: reference the ipv4 sysctl table header
From: Djalal Harouni @ 2012-03-26 23:21 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: David S. Miller, Al Viro, netdev
In-Reply-To: <m1mx73rn7t.fsf@fess.ebiederm.org>
On Mon, Mar 26, 2012 at 03:50:30PM -0700, Eric W. Biederman wrote:
> Djalal Harouni <tixxdz@opendz.org> writes:
>
> > I've been analysing some kmemleak reports of an internal module, and
> > found that there are false positive reports of unreferenced objects.
> >
> > The following patch is just a clean up for one of those false positives,
> > this is for the /proc/sys/net/ipv4 sysctl table.
> > As I've said there are other reports but don't know if it is worth to
> > write patches for them.
>
> So the problem here is that you register a sysctl and don't keep a
> pointer to the returned sysctl_header? So kmemleak complains?
Right.
> I would expect the other sysctl data structures to have such a pointer,
> so I don't know why kmemleak would complain.
>
> Does my recent sysctl rewrite affect when this kmemleak is reported?
Actually yes, after a recent pull (which includes your recent sysctl work),
some of these false positive reports started to appear.
Anyway they seem false positive ones, since keeping a reference to
sysctl_header as in my previous (ugly) patch will quiet the last two ones.
unreferenced object 0xffff88003dc17c70 (size 192):
comm "swapper/0", pid 0, jiffies 4294667341 (age 86.781s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc9b7>] __register_sysctl_paths+0x127/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff811dca93>] register_sysctl_table+0x13/0x20
[<ffffffff820cbe55>] sysctl_init+0x10/0x14
[<ffffffff820d6633>] proc_sys_init+0x2f/0x31
[<ffffffff820d6410>] proc_root_init+0xa5/0xa7
[<ffffffff820b5c39>] start_kernel+0x35c/0x38a
[<ffffffff820b5321>] x86_64_start_reservations+0x131/0x136
[<ffffffff820b5413>] x86_64_start_kernel+0xed/0xf4
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88003d65c000 (size 96):
comm "swapper/0", pid 0, jiffies 4294667341 (age 86.782s)
hex dump (first 32 bytes):
60 86 1c 82 ff ff ff ff 00 00 00 00 01 00 00 00 `...............
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc1f2>] __register_sysctl_table+0x52/0x520
[<ffffffff811dc7ac>] register_leaf_sysctl_tables+0xec/0x1b0
[<ffffffff811dc77c>] register_leaf_sysctl_tables+0xbc/0x1b0
[<ffffffff811dc77c>] register_leaf_sysctl_tables+0xbc/0x1b0
[<ffffffff811dc9e9>] __register_sysctl_paths+0x159/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff811dca93>] register_sysctl_table+0x13/0x20
[<ffffffff820cbe55>] sysctl_init+0x10/0x14
[<ffffffff820d6633>] proc_sys_init+0x2f/0x31
[<ffffffff820d6410>] proc_root_init+0xa5/0xa7
[<ffffffff820b5c39>] start_kernel+0x35c/0x38a
[<ffffffff820b5321>] x86_64_start_reservations+0x131/0x136
[<ffffffff820b5413>] x86_64_start_kernel+0xed/0xf4
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88003d65ddd0 (size 96):
comm "swapper/0", pid 0, jiffies 4294667341 (age 86.782s)
hex dump (first 32 bytes):
00 86 1c 82 ff ff ff ff 00 00 00 00 01 00 00 00 ................
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc1f2>] __register_sysctl_table+0x52/0x520
[<ffffffff811dc7ac>] register_leaf_sysctl_tables+0xec/0x1b0
[<ffffffff811dc77c>] register_leaf_sysctl_tables+0xbc/0x1b0
[<ffffffff811dc9e9>] __register_sysctl_paths+0x159/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff811dca93>] register_sysctl_table+0x13/0x20
[<ffffffff820cbe55>] sysctl_init+0x10/0x14
[<ffffffff820d6633>] proc_sys_init+0x2f/0x31
[<ffffffff820d6410>] proc_root_init+0xa5/0xa7
[<ffffffff820b5c39>] start_kernel+0x35c/0x38a
[<ffffffff820b5321>] x86_64_start_reservations+0x131/0x136
[<ffffffff820b5413>] x86_64_start_kernel+0xed/0xf4
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88003bc41090 (size 96):
comm "swapper/0", pid 1, jiffies 4294669841 (age 84.299s)
hex dump (first 32 bytes):
c0 be ae 82 ff ff ff ff 00 00 00 00 01 00 00 00 ................
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc1f2>] __register_sysctl_table+0x52/0x520
[<ffffffff811dca3d>] __register_sysctl_paths+0x1ad/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff820ef4d6>] sysctl_core_init+0x17/0x38
[<ffffffff810001cd>] do_one_initcall+0x3d/0x170
[<ffffffff820b563c>] kernel_init+0xd9/0x15f
[<ffffffff819e1194>] kernel_thread_helper+0x4/0x10
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88003bc40ee8 (size 96):
comm "swapper/0", pid 1, jiffies 4294669854 (age 84.294s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc9b7>] __register_sysctl_paths+0x127/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff820f0c82>] ip_static_sysctl_init+0x17/0x1b
[<ffffffff820f187f>] inet_init+0xbe/0x2dd
[<ffffffff810001cd>] do_one_initcall+0x3d/0x170
[<ffffffff820b563c>] kernel_init+0xd9/0x15f
[<ffffffff819e1194>] kernel_thread_helper+0x4/0x10
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88003cd27090 (size 96):
comm "swapper/0", pid 1, jiffies 4294669854 (age 84.294s)
hex dump (first 32 bytes):
c0 dc ae 82 ff ff ff ff 00 00 00 00 01 00 00 00 ................
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff819b5d05>] kmemleak_alloc+0x25/0x50
[<ffffffff81154203>] __kmalloc+0x133/0x240
[<ffffffff811dc1f2>] __register_sysctl_table+0x52/0x520
[<ffffffff811dc7ac>] register_leaf_sysctl_tables+0xec/0x1b0
[<ffffffff811dc77c>] register_leaf_sysctl_tables+0xbc/0x1b0
[<ffffffff811dc9e9>] __register_sysctl_paths+0x159/0x1d0
[<ffffffff811dca76>] register_sysctl_paths+0x16/0x20
[<ffffffff820f0c82>] ip_static_sysctl_init+0x17/0x1b
[<ffffffff820f187f>] inet_init+0xbe/0x2dd
[<ffffffff810001cd>] do_one_initcall+0x3d/0x170
[<ffffffff820b563c>] kernel_init+0xd9/0x15f
[<ffffffff819e1194>] kernel_thread_helper+0x4/0x10
[<ffffffffffffffff>] 0xffffffffffffffff
Thanks.
--
tixxdz
http://opendz.org
^ permalink raw reply
* Re: [PATCH 1/1] net/hyperv: Add flow control based on hi/low watermark
From: David Miller @ 2012-03-26 23:12 UTC (permalink / raw)
To: gregkh; +Cc: haiyangz, netdev, devel, olaf, linux-kernel
In-Reply-To: <20120326231017.GA30684@kroah.com>
From: Greg KH <gregkh@linuxfoundation.org>
Date: Mon, 26 Mar 2012 16:10:17 -0700
> David, please do NOT apply this as-is.
BTW, ethtool had controls exactly for stuff like this.
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: David Miller @ 2012-03-26 23:11 UTC (permalink / raw)
To: greearb; +Cc: netdev, eric.dumazet, gregkh
In-Reply-To: <4F70F688.6050108@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Date: Mon, 26 Mar 2012 16:06:48 -0700
> That said, I don't see any issues with the inet6_dump_fib
> method, so maybe my debug attempt is not valid..or lockdep debugging
> has issues of some sort.
This is exactly where Eric and myself hit a dead-end on Dave
Jones's reports.
^ permalink raw reply
* Re: [PATCH 1/1] net/hyperv: Add flow control based on hi/low watermark
From: Greg KH @ 2012-03-26 23:10 UTC (permalink / raw)
To: Haiyang Zhang; +Cc: davem, netdev, devel, olaf, linux-kernel
In-Reply-To: <1332800304-5060-2-git-send-email-haiyangz@microsoft.com>
On Mon, Mar 26, 2012 at 03:18:24PM -0700, Haiyang Zhang wrote:
> In the existing code, we only stop queue when the ringbuffer is full,
> so the current packet has to be dropped or retried from upper layer.
>
> This patch stops the tx queue when available ringbuffer is below
> the low watermark. So the ringbuffer still has small amount of space
> available for the current packet. This will reduce the overhead of
> retries on sending.
>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
> ---
> drivers/hv/ring_buffer.c | 15 +++++++++++++++
> drivers/net/hyperv/hyperv_net.h | 3 +++
> drivers/net/hyperv/netvsc.c | 23 +++++++++++++++++++----
> drivers/net/hyperv/netvsc_drv.c | 16 +++++++++++++++-
> include/linux/hyperv.h | 3 +++
> 5 files changed, 55 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
> index 8af25a0..8cc3f63 100644
> --- a/drivers/hv/ring_buffer.c
> +++ b/drivers/hv/ring_buffer.c
> @@ -23,6 +23,7 @@
> */
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
> +#include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/mm.h>
> #include <linux/hyperv.h>
> @@ -160,6 +161,20 @@ hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
> }
>
> /*
> + * Get the percentage of available bytes to write in the ring.
> + * The return value is in range from 0 to 100.
> + */
> +u32 hv_ringbuf_avail_percent(struct hv_ring_buffer_info *ring_info)
> +{
> + u32 avail_read, avail_write;
> +
> + hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
> +
> + return avail_write * 100 / hv_get_ring_buffersize(ring_info);
> +}
> +EXPORT_SYMBOL(hv_ringbuf_avail_percent);
That makes no sense, what happens 1 second later to the buffer? You
can't expect this result to be valid anymore, right?
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -51,6 +51,16 @@ static int ring_size = 128;
> module_param(ring_size, int, S_IRUGO);
> MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
>
> +uint ring_avail_percent_hiwater = 20;
> +module_param(ring_avail_percent_hiwater, uint, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(ring_avail_percent_hiwater,
> + "Ring buffer available percentiles to wake up xmit queue");
> +
> +uint ring_avail_percent_lowater = 10;
> +module_param(ring_avail_percent_lowater, uint, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(ring_avail_percent_lowater,
> + "Ring buffer available percentiles to stop xmit queue");
Eeek, no, how in the world is someone supposed to know to set these
things?
Please make this work "automatically", otherwise no one will ever get it
right. Don't make it tunable as a way out of making a decision on how
the driver should work.
Ick.
David, please do NOT apply this as-is.
greg k-h
^ permalink raw reply
* Re: RCU lock bug in 3.0.21 (bisected to: 682cb56a, fix NULL dereferences in check_peer_redir)
From: Ben Greear @ 2012-03-26 23:06 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eric.dumazet, gregkh
In-Reply-To: <4F70E560.3020102@candelatech.com>
On 03/26/2012 02:53 PM, Ben Greear wrote:
> On 03/26/2012 02:49 PM, David Miller wrote:
>>
>> Looks like all of those strange undiagnosable reported Dave Jones
>> has been feeding us. Something in one part of the kernel leaves
>> a lock held, and this shows up as a warning elsewhere.
>
> Every (initial) bug printout fingers ipv6 and the 'ip' tool on my system.
I added a patch to convert rcu_read_lock/unlock to macros so
that I could automatically grab the call site (_THIS_IP_)
and pass it into the lockdep framework instead of the (useless)
_THIS_IP_ in the old rcu_read_lock method which at best seems to
only indicate which module the issue relates to...
Here's it's output:
BUG: sleeping function called from invalid context at /home/greearb/git/linux-3.0.dev.y/mm/memory.c:3904
in_atomic(): 0, irqs_disabled(): 0, pid: 4975, name: ip
1 lock held by ip/4975:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa032081a>] inet6_dump_fib+0x6c/0x233 [ipv6]
Pid: 4975, comm: ip Tainted: G C 3.0.20+ #11
Call Trace:
[<ffffffff8103e515>] __might_sleep+0x111/0x115
[<ffffffff810c9e9f>] might_fault+0x2f/0x9e
[<ffffffff81387332>] ? copy_from_user+0x2a/0x2c
[<ffffffff810c9ebe>] ? might_fault+0x4e/0x9e
[<ffffffff8137d5c0>] move_addr_to_user+0x21/0x8e
[<ffffffff8137d7ac>] __sys_recvmsg+0x17f/0x21e
[<ffffffff81063850>] ? up_read+0x1e/0x36
[<ffffffff810fc727>] ? fcheck_files+0xb7/0xee
[<ffffffff810fc85c>] ? fget_light+0x3b/0xbc
[<ffffffff8137df50>] sys_recvmsg+0x3d/0x5b
[<ffffffff8144fcd2>] system_call_fastpath+0x16/0x1b
================================================
[ BUG: lock held when returning to user space! ]
------------------------------------------------
ip/4975 is leaving the kernel with locks still held!
1 lock held by ip/4975:
#0: (rcu_read_lock){.+.+..}, at: [<ffffffffa032081a>] inet6_dump_fib+0x6c/0x233 [ipv6]
(gdb) l *(inet6_dump_fib+0x6c)
0x1181a is in inet6_dump_fib (/home/greearb/git/linux-3.0.dev.y/net/ipv6/ip6_fib.c:395).
390 }
391
392 arg.skb = skb;
393 arg.cb = cb;
394 arg.net = net;
395 w->args = &arg;
396
397 rcu_read_lock();
398 for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
399 e = 0;
(gdb)
That said, I don't see any issues with the inet6_dump_fib
method, so maybe my debug attempt is not valid..or lockdep debugging
has issues of some sort.
Off to do more poking around.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH] net: reference the ipv4 sysctl table header
From: Eric W. Biederman @ 2012-03-26 22:50 UTC (permalink / raw)
To: Djalal Harouni; +Cc: David S. Miller, Al Viro, netdev
In-Reply-To: <20120326222359.GB28123@dztty>
Djalal Harouni <tixxdz@opendz.org> writes:
> I've been analysing some kmemleak reports of an internal module, and
> found that there are false positive reports of unreferenced objects.
>
> The following patch is just a clean up for one of those false positives,
> this is for the /proc/sys/net/ipv4 sysctl table.
> As I've said there are other reports but don't know if it is worth to
> write patches for them.
So the problem here is that you register a sysctl and don't keep a
pointer to the returned sysctl_header? So kmemleak complains?
I would expect the other sysctl data structures to have such a pointer,
so I don't know why kmemleak would complain.
Does my recent sysctl rewrite affect when this kmemleak is reported?
Scratching my head to understand what the complain is.
> ---
> From: Djalal Harouni <tixxdz@opendz.org>
> Subject: [PATCH] net: reference the ipv4 sysctl table header
>
> Reference the ipv4 sysctl table header allocated and returned by
> register_sysctl_paths().
>
> Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
> ---
> include/net/ip.h | 2 +-
> net/ipv4/af_inet.c | 12 ++++++++++--
> net/ipv4/route.c | 10 ++++++++--
> 3 files changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/ip.h b/include/net/ip.h
> index b53d65f..6a12687 100644
> --- a/include/net/ip.h
> +++ b/include/net/ip.h
> @@ -235,7 +235,7 @@ extern int sysctl_ip_dynaddr;
>
> extern void ipfrag_init(void);
>
> -extern void ip_static_sysctl_init(void);
> +extern int ip_static_sysctl_init(void);
>
> static inline bool ip_is_fragment(const struct iphdr *iph)
> {
> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
> index fdf49fd..340d298 100644
> --- a/net/ipv4/af_inet.c
> +++ b/net/ipv4/af_inet.c
> @@ -1666,10 +1666,14 @@ static int __init inet_init(void)
> * Tell SOCKET that we are alive...
> */
>
> - (void)sock_register(&inet_family_ops);
> + rc = sock_register(&inet_family_ops);
> + if (rc)
> + goto out_unregister_ping_prot;
>
> #ifdef CONFIG_SYSCTL
> - ip_static_sysctl_init();
> + rc = ip_static_sysctl_init();
> + if (rc)
> + goto out_unregister_sock;
> #endif
>
> tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem;
> @@ -1751,6 +1755,10 @@ static int __init inet_init(void)
> rc = 0;
> out:
> return rc;
> +out_unregister_sock:
> + sock_unregister(PF_INET);
> +out_unregister_ping_prot:
> + proto_unregister(&ping_prot);
> out_unregister_raw_proto:
> proto_unregister(&raw_prot);
> out_unregister_udp_proto:
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 12ccf88..bc899f2 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -3500,12 +3500,18 @@ int __init ip_rt_init(void)
> }
>
> #ifdef CONFIG_SYSCTL
> +static struct ctl_table_header *ip4_base;
> +
> /*
> * We really need to sanitize the damn ipv4 init order, then all
> * this nonsense will go away.
> */
> -void __init ip_static_sysctl_init(void)
> +int __init ip_static_sysctl_init(void)
> {
> - register_sysctl_paths(ipv4_path, ipv4_skeleton);
> + ip4_base = register_sysctl_paths(ipv4_path, ipv4_skeleton);
> + if (!ip4_base)
> + return -ENOMEM;
> +
> + return 0;
> }
> #endif
^ permalink raw reply
* Re: [PATCH] net: reference the ipv4 sysctl table header
From: Djalal Harouni @ 2012-03-26 22:42 UTC (permalink / raw)
To: David Miller; +Cc: ebiederm, viro, netdev
In-Reply-To: <20120326.182411.41401140080225401.davem@davemloft.net>
On Mon, Mar 26, 2012 at 06:24:11PM -0400, David Miller wrote:
> From: Djalal Harouni <tixxdz@opendz.org>
> Date: Mon, 26 Mar 2012 23:23:59 +0100
>
> > +static struct ctl_table_header *ip4_base;
> > +
> > /*
> > * We really need to sanitize the damn ipv4 init order, then all
> > * this nonsense will go away.
> > */
> > -void __init ip_static_sysctl_init(void)
> > +int __init ip_static_sysctl_init(void)
> > {
> > - register_sysctl_paths(ipv4_path, ipv4_skeleton);
> > + ip4_base = register_sysctl_paths(ipv4_path, ipv4_skeleton);
>
> This is so incredibly stupid, just panic() or similar if this
> returns NULL.
>
> And find another way to annotate this for memleak so we don't need to
> waste an entire pointer, which is never used, in the data section.
Ok, thank you.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
tixxdz
http://opendz.org
^ permalink raw reply
* Re: [PATCH] net: reference the ipv4 sysctl table header
From: David Miller @ 2012-03-26 22:24 UTC (permalink / raw)
To: tixxdz; +Cc: ebiederm, viro, netdev
In-Reply-To: <20120326222359.GB28123@dztty>
From: Djalal Harouni <tixxdz@opendz.org>
Date: Mon, 26 Mar 2012 23:23:59 +0100
> +static struct ctl_table_header *ip4_base;
> +
> /*
> * We really need to sanitize the damn ipv4 init order, then all
> * this nonsense will go away.
> */
> -void __init ip_static_sysctl_init(void)
> +int __init ip_static_sysctl_init(void)
> {
> - register_sysctl_paths(ipv4_path, ipv4_skeleton);
> + ip4_base = register_sysctl_paths(ipv4_path, ipv4_skeleton);
This is so incredibly stupid, just panic() or similar if this
returns NULL.
And find another way to annotate this for memleak so we don't need to
waste an entire pointer, which is never used, in the data section.
^ permalink raw reply
* INVESTMENT IN YOUR COMPANY
From: Tarek Mansour Daw @ 2012-03-26 22:21 UTC (permalink / raw)
[-- Attachment #1: Type: text/plain, Size: 56 bytes --]
Please kindly read the attached letter for more details
[-- Attachment #2: Dear Sir,.txt --]
[-- Type: application/octet-stream, Size: 343 bytes --]
Dear Sir,
My name is Tarek Mansour Daw from Libya, the only son of Mr. Mansour Daw. Please contact me via my email as we will like to invest our family funds in a renewable energy / biodiesel/farming projects. You can contact me via email for more clarifications.
I wait to hear from you.
Thank you.
Tarek Mansour Daw
^ permalink raw reply
* [PATCH] net: reference the ipv4 sysctl table header
From: Djalal Harouni @ 2012-03-26 22:23 UTC (permalink / raw)
To: David S. Miller, Eric W. Biederman, Al Viro; +Cc: netdev
I've been analysing some kmemleak reports of an internal module, and
found that there are false positive reports of unreferenced objects.
The following patch is just a clean up for one of those false positives,
this is for the /proc/sys/net/ipv4 sysctl table.
As I've said there are other reports but don't know if it is worth to
write patches for them.
---
From: Djalal Harouni <tixxdz@opendz.org>
Subject: [PATCH] net: reference the ipv4 sysctl table header
Reference the ipv4 sysctl table header allocated and returned by
register_sysctl_paths().
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
---
include/net/ip.h | 2 +-
net/ipv4/af_inet.c | 12 ++++++++++--
net/ipv4/route.c | 10 ++++++++--
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index b53d65f..6a12687 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -235,7 +235,7 @@ extern int sysctl_ip_dynaddr;
extern void ipfrag_init(void);
-extern void ip_static_sysctl_init(void);
+extern int ip_static_sysctl_init(void);
static inline bool ip_is_fragment(const struct iphdr *iph)
{
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index fdf49fd..340d298 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1666,10 +1666,14 @@ static int __init inet_init(void)
* Tell SOCKET that we are alive...
*/
- (void)sock_register(&inet_family_ops);
+ rc = sock_register(&inet_family_ops);
+ if (rc)
+ goto out_unregister_ping_prot;
#ifdef CONFIG_SYSCTL
- ip_static_sysctl_init();
+ rc = ip_static_sysctl_init();
+ if (rc)
+ goto out_unregister_sock;
#endif
tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem;
@@ -1751,6 +1755,10 @@ static int __init inet_init(void)
rc = 0;
out:
return rc;
+out_unregister_sock:
+ sock_unregister(PF_INET);
+out_unregister_ping_prot:
+ proto_unregister(&ping_prot);
out_unregister_raw_proto:
proto_unregister(&raw_prot);
out_unregister_udp_proto:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 12ccf88..bc899f2 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3500,12 +3500,18 @@ int __init ip_rt_init(void)
}
#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *ip4_base;
+
/*
* We really need to sanitize the damn ipv4 init order, then all
* this nonsense will go away.
*/
-void __init ip_static_sysctl_init(void)
+int __init ip_static_sysctl_init(void)
{
- register_sysctl_paths(ipv4_path, ipv4_skeleton);
+ ip4_base = register_sysctl_paths(ipv4_path, ipv4_skeleton);
+ if (!ip4_base)
+ return -ENOMEM;
+
+ return 0;
}
#endif
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox