* [net-next 09/12] igb: fix static function warnings reported by sparse
From: Jeff Kirsher @ 2011-10-12 3:38 UTC (permalink / raw)
To: davem; +Cc: Emil Tantilov, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1318390708-12232-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Emil Tantilov <emil.s.tantilov@intel.com>
igb_update/validate_nvm_checksum_with_offset() should be static.
Also removes unneeded protypes for the above functions.
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/igb/e1000_82575.c | 9 +++------
1 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index c0857bd..3771bd2 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -66,10 +66,6 @@ static s32 igb_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw);
static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw);
static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw);
-static s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw,
- u16 offset);
-static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
- u16 offset);
static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw);
static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
static const u16 e1000_82580_rxpbs_table[] =
@@ -1820,7 +1816,8 @@ u16 igb_rxpbs_adjust_82580(u32 data)
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
**/
-s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset)
{
s32 ret_val = 0;
u16 checksum = 0;
@@ -1855,7 +1852,7 @@ out:
* up to the checksum. Then calculates the EEPROM checksum and writes the
* value to the EEPROM.
**/
-s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+static s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
{
s32 ret_val;
u16 checksum = 0;
--
1.7.6.4
^ permalink raw reply related
* [net-next 12/12] igb: Version bump.
From: Jeff Kirsher @ 2011-10-12 3:38 UTC (permalink / raw)
To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1318390708-12232-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Carolyn Wyborny <carolyn.wyborny@intel.com>
This change updates the driver version to 3.2.10.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/igb/igb_main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 6fdf2e0..8ba0889 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -57,8 +57,8 @@
#include "igb.h"
#define MAJ 3
-#define MIN 0
-#define BUILD 6
+#define MIN 2
+#define BUILD 10
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
--
1.7.6.4
^ permalink raw reply related
* Re: [PATCH] bonding: L2L3 xmit doesn't support IPv6
From: Yinglin Sun @ 2011-10-12 3:39 UTC (permalink / raw)
To: Andy Gospodarek; +Cc: Jay Vosburgh, netdev, John Eaglesham
In-Reply-To: <20111012025137.GB20605@gospo.rdu.redhat.com>
On Tue, Oct 11, 2011 at 7:51 PM, Andy Gospodarek <andy@greyhouse.net> wrote:
> On Tue, Oct 11, 2011 at 08:58:59AM -0700, Jay Vosburgh wrote:
>> Andy Gospodarek <andy@greyhouse.net> wrote:
> [...]
>> >
>> >There have been some attempts to add support for ipv6 hashing this in
>> >the past, but none have been committed. The best one I had seen was one
>> >that did some extensive testing one a wide variety of ipv6 traffic and
>> >it showed nice traffic distribution. I'm not sure if it was ever posted
>> >upstream, so I will see if I can dig it up.
>> >
>> >Can you quantify how traffic was distributed with this algorithm?
>>
>> As I recall, the IPv6 issues had to do with the "layer3+4" hash,
>> because the IPv6 TCP or UDP port numbers can be harder to get at than in
>> IPv4 (which typically has a fixed size header). The above is just for
>> layer 2, so it only hits the IPv6 addresses, which don't move around.
>>
>> That said, I believe that many IPv6 addresses are derived from
>> the MAC address, the autoconf addresses in particular, so s6_addr32[3]
>> may not show a lot more variation than just the MAC address. I don't
>> know for sure though, since I haven't tested it.
>>
>> I don't recall seeing the patch you mention, Andy, that checks
>> ipv6 traffic; can you post it?
>>
>
> I found the patch, cleaned it up, and compile tested it against
> net-next. I traded some emails with John Eaglesham (cc'd) earlier this
> year and though he planned to post it, I never followed up.
>
> His comments about this patch were as follows:
>
> "I've attached my patch for IPv6 transmit hashing for the nic bonding
> driver.
>
> "The algorithm I chose is based on 273,913 IPv6 client addresses I
> gathered from webservers and ran through a test program that implemented
> several algorithms. This algorithm provided the most even distribution
> while using the fewest instructions.
>
> "I've tested this on 2.6.39-rc4 and a similar patch to 2.6.18 (from
> RHEL5 5.4.3) and it has performed as expected in both cases.
>
> "Please let me know if you have any comments, otherwise I suppose the
> next step is to propose the patch to LKML."
>
> I would suggest we use this. John or I could write an official
> changelog and post this in it's own thread if it looks good to others.
>
> ---
> drivers/net/bonding/bond_main.c | 30 +++++++++++++++++++++++++-----
> 1 files changed, 25 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 6191e63..335cb67 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -3368,11 +3368,20 @@ static struct notifier_block bond_inetaddr_notifier = {
> static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
> {
> struct ethhdr *data = (struct ethhdr *)skb->data;
> - struct iphdr *iph = ip_hdr(skb);
>
> if (skb->protocol == htons(ETH_P_IP)) {
> + struct iphdr *iph = ip_hdr(skb);
> return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
> (data->h_dest[5] ^ data->h_source[5])) % count;
> + } else if (skb->protocol == htons(ETH_P_IPV6)) {
> + struct ipv6hdr *ipv6h = ipv6_hdr(skb);
> + u32 v6hash = (
> + (ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
> + (ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
> + (ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3])
> + );
> + v6hash = (v6hash >> 16) ^ (v6hash >> 8) ^ v6hash;
> + return (v6hash ^ data->h_dest[5] ^ data->h_source[5]) % count;
> }
>
> return (data->h_dest[5] ^ data->h_source[5]) % count;
> @@ -3386,11 +3395,11 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
> static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
> {
> struct ethhdr *data = (struct ethhdr *)skb->data;
> - struct iphdr *iph = ip_hdr(skb);
> - __be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
> - int layer4_xor = 0;
> + u32 layer4_xor = 0;
>
> if (skb->protocol == htons(ETH_P_IP)) {
> + struct iphdr *iph = ip_hdr(skb);
> + __be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
> if (!ip_is_fragment(iph) &&
> (iph->protocol == IPPROTO_TCP ||
> iph->protocol == IPPROTO_UDP)) {
> @@ -3398,7 +3407,18 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
> }
> return (layer4_xor ^
> ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
> -
> + } else if (skb->protocol == htons(ETH_P_IPV6)) {
> + struct ipv6hdr *ipv6h = ipv6_hdr(skb);
> + __be16 *layer4hdrv6 = (__be16 *)((u8 *)ipv6h + sizeof(*ipv6h));
> + if (ipv6h->nexthdr == IPPROTO_TCP || ipv6h->nexthdr == IPPROTO_UDP) {
Does this work if this is a fragmentation packet? and if
ipv6h->nexthdr is not IPPROTO_TCP/IPPROTO_UDP, it doesn't mean this is
not TCP/UDP packet. We need to go through the extension header chain
and look at the last one. It's likely there are some other extension
headers before L4 header.
Yinglin
> + layer4_xor = (*layer4hdrv6 ^ *(layer4hdrv6 + 1));
> + }
> + layer4_xor ^= (
> + (ipv6h->saddr.s6_addr32[1] ^ ipv6h->daddr.s6_addr32[1]) ^
> + (ipv6h->saddr.s6_addr32[2] ^ ipv6h->daddr.s6_addr32[2]) ^
> + (ipv6h->saddr.s6_addr32[3] ^ ipv6h->daddr.s6_addr32[3])
> + );
> + return ((layer4_xor >> 16) ^ (layer4_xor >> 8) ^ layer4_xor) % count;
> }
>
> return (data->h_dest[5] ^ data->h_source[5]) % count;
> --
> 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
>
^ permalink raw reply
* [PATCH] flexcan: fix flood of irq's after error condition triggered
From: Reuben Dowle @ 2011-10-12 3:41 UTC (permalink / raw)
To: netdev
On my i.MX28 development kit board, I am able to use the flexcan module without problems, until I introduce a bus error by disconnecting the cable. As soon as this is done, the cpu usage goes to 100% percent due to the irq handler being called constantly.
It seems this error can be traced to the irq handler not clearing the irq flags. The flexcan driver is enabling several interrupts, but only clearing one of them.
>From the user manual:
25.6.8 Error and Status Register (HW_CAN_ESR)
This register reflects various error conditions, some general status of the device and it is
the source of four interrupts to the ARM. The reported error conditions are those that
occurred since the last time the ARM read this register. The ARM read action clears bits.
Bits are status bits. Most bits in this register are read-only, except TWRN_INT, RWRN_INT,
BOFF_INT, WAK_INT and ERR_INT, which are interrupt flags that can be cleared by
writing 1 to them (writing 0 has no effect).
This is ambiguous. It says that reading clears the bits, but then says that some of the bits can be cleared by writing 1 to them. In practice it seems that all the ones listed above as being able to be cleared by writing 1 to them MUST be cleared by writing 1 to them.
Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
---
drivers/net/can/flexcan.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 1767811..9bcc2e2 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -553,7 +553,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
reg_iflag1 = readl(®s->iflag1);
reg_esr = readl(®s->esr);
- writel(FLEXCAN_ESR_ERR_INT, ®s->esr); /* ACK err IRQ */
+ writel(reg_esr & (FLEXCAN_ESR_TWRN_INT|FLEXCAN_ESR_RWRN_INT|FLEXCAN_ESR_BOFF_INT|FLEXCAN_ESR_ERR_INT), ®s->esr); /* ACK err IRQ */
/*
* schedule NAPI in case of:
^ permalink raw reply related
* Re: [PATCH] bonding: L2L3 xmit doesn't support IPv6
From: Eric Dumazet @ 2011-10-12 4:06 UTC (permalink / raw)
To: Yinglin Sun; +Cc: Andy Gospodarek, Jay Vosburgh, netdev, John Eaglesham
In-Reply-To: <CAN17JHVsgRqkOgeJ0+vvQe3kN1W0ue0vKHa3uebFHa9oH2ngXA@mail.gmail.com>
Le mardi 11 octobre 2011 à 20:39 -0700, Yinglin Sun a écrit :
> On Tue, Oct 11, 2011 at 7:51 PM, Andy Gospodarek <andy@greyhouse.net> wrote:
> >
> > if (skb->protocol == htons(ETH_P_IP)) {
> > + struct iphdr *iph = ip_hdr(skb);
> > + __be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
> > if (!ip_is_fragment(iph) &&
> > (iph->protocol == IPPROTO_TCP ||
> > iph->protocol == IPPROTO_UDP)) {
> > @@ -3398,7 +3407,18 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
> > }
> > return (layer4_xor ^
> > ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
> > -
> > + } else if (skb->protocol == htons(ETH_P_IPV6)) {
> > + struct ipv6hdr *ipv6h = ipv6_hdr(skb);
> > + __be16 *layer4hdrv6 = (__be16 *)((u8 *)ipv6h + sizeof(*ipv6h));
> > + if (ipv6h->nexthdr == IPPROTO_TCP || ipv6h->nexthdr == IPPROTO_UDP) {
>
> Does this work if this is a fragmentation packet? and if
> ipv6h->nexthdr is not IPPROTO_TCP/IPPROTO_UDP, it doesn't mean this is
> not TCP/UDP packet. We need to go through the extension header chain
> and look at the last one. It's likely there are some other extension
> headers before L4 header.
>
Its a best effort.
If first header is not IPPROTO_TCP/UDP, I am not sure its wise to spend
time in hope to find layer4 info (missing anyway in fragments)
By the way I see no bound checking on SKB head : malicious packet could
make bond_xmit_hash_policy_l34() access unitialized memory.
We have same 'fastpath' in __skb_get_rxhash()
^ permalink raw reply
* Re: [PATCH v3] net-netlink: Add a new attribute to expose TOS values via netlink
From: MuraliRaja Muniraju @ 2011-10-12 4:16 UTC (permalink / raw)
To: Eric Dumazet
Cc: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <1318387734.3686.2.camel@edumazet-laptop>
Eric,
I think it would be useful to expose the values this way.
I shall make the changes to add TCLASS for ipv6 in the description.
Regarding the TIME_WAIT state, I think it would be better of not
exposing the values because there would hardly be anything to transmit
during this time.
Thanks,
Murali
On Tue, Oct 11, 2011 at 7:48 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le mardi 11 octobre 2011 à 18:28 -0700, Muraliraja Muniraju a écrit :
>> From: Murali Raja <muralira@google.com>
>>
>> This patch exposes the tos value for the TCP sockets when the TOS flag
>> is requested in the ext_flags for the inet_diag request. This would mainly be
>> used to expose TOS values for both for TCP and UDP sockets. Currently it is
>> supported for TCP. When netlink support for UDP would be added the support
>> to expose the TOS values would alse be done.
>>
>
> You could mention TCLASS support for IPv6
>
>> Signed-off-by: Murali Raja <muralira@google.com>
>> ---
>> Changelog since v2:
>> - Adding support for IPV6 class and using right API's
>> Changelog since v1:
>> - Removing reserved field
>>
>> include/linux/inet_diag.h | 9 ++++++++-
>> net/ipv4/inet_diag.c | 5 +++++
>> 2 files changed, 13 insertions(+), 1 deletions(-)
>>
>> diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
>> index bc8c490..e36093d 100644
>> --- a/include/linux/inet_diag.h
>> +++ b/include/linux/inet_diag.h
>> @@ -97,9 +97,10 @@ enum {
>> INET_DIAG_INFO,
>> INET_DIAG_VEGASINFO,
>> INET_DIAG_CONG,
>> + INET_DIAG_TOS,
>> };
>>
>> -#define INET_DIAG_MAX INET_DIAG_CONG
>> +#define INET_DIAG_MAX INET_DIAG_TOS
>>
>>
>> /* INET_DIAG_MEM */
>> @@ -120,6 +121,12 @@ struct tcpvegas_info {
>> __u32 tcpv_minrtt;
>> };
>>
>> +/* INET_DIAG_TOS */
>> +
>> +struct inet_diag_tos {
>> + __u8 idiag_tos;
>> +};
>
> Are you sure its still needed ?
>
> I am now wondering what is done in TIME_WAIT state.
>
>
>
--
Thanks,
Murali
^ permalink raw reply
* Re: [PATCH v3] net-netlink: Add a new attribute to expose TOS values via netlink
From: Eric Dumazet @ 2011-10-12 4:31 UTC (permalink / raw)
To: MuraliRaja Muniraju
Cc: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <CAP3iWTQXHwzw-qUYVfT--uNv4pNZnu0ROJnF7B1VLeZBbrfdqw@mail.gmail.com>
Le mardi 11 octobre 2011 à 21:16 -0700, MuraliRaja Muniraju a écrit :
> Eric,
> I think it would be useful to expose the values this way.
> I shall make the changes to add TCLASS for ipv6 in the description.
>
> Regarding the TIME_WAIT state, I think it would be better of not
> exposing the values because there would hardly be anything to transmit
> during this time.
>
My remark had nothing to do with your patch actually :
We dont store TOS/TCLASS on TIME_WAIT sockets, so you cannot report
value in inet_diag.
But we do send packets on behalf of TIME_WAIT sockets ;)
Think about ACK messages. They probably are sent with a 0 TOS/TCLASS
field... I am not sure its a problem or not.
^ permalink raw reply
* Re: ixgbe: fixup hard dependencies on supporting 8 traffic classes
From: Dan Carpenter @ 2011-10-12 6:35 UTC (permalink / raw)
To: john.r.fastabend; +Cc: e1000-devel, netdev
Hello John Fastabend,
This is a semi-automatic email about new static checker warnings.
The patch 32701dc2e616: "ixgbe: fixup hard dependencies on supporting
8 traffic classes" from Sep 27, 2011, leads to the following Smatch
complaint:
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +3366 ixgbe_configure_dcb()
error: we previously assumed 'adapter->ixgbe_ieee_ets' could be null (see line 3357)
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
3356
3357 if (adapter->ixgbe_ieee_ets) {
^^^^^^^^^^^^^^^^^^^^^^^
Null check.
3358 struct ieee_ets *ets = adapter->ixgbe_ieee_ets;
3359 int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
3360
3361 ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
3362 }
3363
3364 if (adapter->ixgbe_ieee_pfc) {
3365 struct ieee_pfc *pfc = adapter->ixgbe_ieee_pfc;
3366 u8 *prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
^^^^^^^^^^^^^^^^^^^^^^^^^
New dereference.
3367
3368 ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en,
regards,
dan carpenter
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: ixgbe: fixup hard dependencies on supporting 8 traffic classes
From: John Fastabend @ 2011-10-12 6:58 UTC (permalink / raw)
To: Dan Carpenter, Kirsher, Jeffrey T
Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org
In-Reply-To: <20111012063555.GA23359@elgon.mountain>
On 10/11/2011 11:35 PM, Dan Carpenter wrote:
> Hello John Fastabend,
>
> This is a semi-automatic email about new static checker warnings.
>
> The patch 32701dc2e616: "ixgbe: fixup hard dependencies on supporting
> 8 traffic classes" from Sep 27, 2011, leads to the following Smatch
> complaint:
>
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +3366 ixgbe_configure_dcb()
> error: we previously assumed 'adapter->ixgbe_ieee_ets' could be null (see line 3357)
>
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> 3356
> 3357 if (adapter->ixgbe_ieee_ets) {
> ^^^^^^^^^^^^^^^^^^^^^^^
> Null check.
>
> 3358 struct ieee_ets *ets = adapter->ixgbe_ieee_ets;
> 3359 int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
> 3360
> 3361 ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
> 3362 }
> 3363
> 3364 if (adapter->ixgbe_ieee_pfc) {
> 3365 struct ieee_pfc *pfc = adapter->ixgbe_ieee_pfc;
> 3366 u8 *prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
> ^^^^^^^^^^^^^^^^^^^^^^^^^
> New dereference.
>
> 3367
> 3368 ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en,
>
> regards,
> dan carpenter
>
Actually both structures ixgbe_ieee_ets and ixgbe_ieee_pfc get initialized
at the same time. So no null dereference will occur. That said this snippit
should be fixed.
I'll send a patch to JeffK. Thanks for the catch Dan.
.John
^ permalink raw reply
* Re: [net-next 1/5] stmmac: add CHAINED descriptor mode support
From: Giuseppe CAVALLARO @ 2011-10-12 6:37 UTC (permalink / raw)
To: David Miller; +Cc: netdev, rayagond
In-Reply-To: <20111011.154203.569015025155780686.davem@davemloft.net>
On 10/11/2011 9:42 PM, David Miller wrote:
> From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
> Date: Tue, 11 Oct 2011 09:30:42 +0200
>
>> From: Rayagond Kokatanur <rayagond@vayavyalabs.com>
>>
>> This patch enhances the STMMAC driver to support CHAINED mode of
>> descriptor (useful also on validation side).
>>
>> STMMAC supports DMA descriptor to operate both in dual buffer(RING)
>> and linked-list(CHAINED) mode. In RING mode (default) each descriptor
>> points to two data buffer pointers whereas in CHAINED mode they point
>> to only one data buffer pointer.
>>
>> In CHAINED mode each descriptor will have pointer to next descriptor in
>> the list, hence creating the explicit chaining in the descriptor itself,
>> whereas such explicit chaining is not possible in RING mode.
>>
>> Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
>> Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>
> These ifdefs added all over the place in the foo.c files are terrible.
>
> Abstract out the differences between RING and CHAINED mode into helper
> inline routines which live in some foo.h header file, that way you won't
> need any ifdefs in the driver foo.c files.
Hello David
I'll rework the patch and send all these updates to the mailing list
again (as V2).
Peppe
> --
> 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
>
^ permalink raw reply
* Re: [RFC PATCH net 1/2] [BUGFIX] bonding: use local function pointer of bond->recv_probe in bond_handle_frame
From: HAYASAKA Mitsuo @ 2011-10-12 7:04 UTC (permalink / raw)
To: Eric Dumazet
Cc: Américo Wang, Jay Vosburgh, Andy Gospodarek, netdev,
linux-kernel, yrl.pp-manager.tt
In-Reply-To: <1318339433.2538.25.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
Hi Eric,
Thank you for your comment.
(2011/10/11 22:23), Eric Dumazet wrote:
> Le mardi 11 octobre 2011 à 22:02 +0900, HAYASAKA Mitsuo a écrit :
>> Hi WANG Cong
>>
>> Thank you for your comments.
>>
>> (2011/10/07 22:24), Américo Wang wrote:
>>> On Fri, Oct 7, 2011 at 8:49 PM, Mitsuo Hayasaka
>>> <mitsuo.hayasaka.hu@hitachi.com> wrote:
>>>> The bond->recv_probe is called in bond_handle_frame() when
>>>> a packet is received, but bond_close() sets it to NULL. So,
>>>> a panic occurs when both functions work in parallel.
>>>>
>>>> Why this happen:
>>>> After null pointer check of bond->recv_probe, an sk_buff is
>>>> duplicated and bond->recv_probe is called in bond_handle_frame.
>>>> So, a panic occurs when bond_close() is called between the
>>>> check and call of bond->recv_probe.
>>>>
>>>> Patch:
>>>> This patch uses a local function pointer of bond->recv_probe
>>>> in bond_handle_frame(). So, it can avoid the null pointer
>>>> dereference.
>>>>
>>>
>>> Hmm, I don't doubt it can fix the problem, I am wondering if
>>> bond->recv_probe should be protected by bond->lock...
>>
>> Indeed, in general any resources should be protected from the asynchronous
>> workers.
>>
>> At first, I thought it should be handled with lock protection, as well.
>> However, I guess that using bond->lock on this kind of hot-path may
>> introduces unnecessary overhead. In addition, this code works well
>> without the strict lock protection. So, I think this change is the
>> right way to fix it.
>
> Maybe, but then ACCESS_ONCE() is needed to prevent compiler to
> 'optimize' the temporary variable.
>
> Or use rcu_dereference() to make the whole thing really safe and self
> documented.
>
I agreed.
I'd like to send the patch with ACCESS_ONCE(), again.
Thanks.
^ permalink raw reply
* about phonet pipe controller
From: Hemant-vilas RAMDASI @ 2011-10-12 7:25 UTC (permalink / raw)
To: remi.denis-courmont@nokia.com; +Cc: Srinidhi KASAGAR, netdev@vger.kernel.org
Hi Remi,
You have mentioned in the
"a015f6f: Phonet: kill the ST-Ericsson pipe controller Kconfig",
that "Support for manually enabling the pipe flow is removed as it
did not work properly, does not fit well with the socket API, and
I am not aware of any use at the moment.."
On STE U8500 modem, you must first create pipe in disabled state, then do
local link configuration (does't work when pipe is enabled) & then enable pipe.
Because of this connect() cannot be used anymore and it needs to be modified to
reintroduce pipe-controller functionality again.
Do you have any suggestions?
Regards,
Hemant Ramdasi
^ permalink raw reply
* Re: about phonet pipe controller
From: Rémi Denis-Courmont @ 2011-10-12 7:58 UTC (permalink / raw)
To: ext Hemant-vilas RAMDASI; +Cc: Srinidhi KASAGAR, netdev@vger.kernel.org
In-Reply-To: <81C3A93C17462B4BBD7E272753C105791EAACAE76F@EXDCVYMBSTM005.EQ1STM.local>
Le Mercredi 12 Octobre 2011 09:25:01 ext Hemant-vilas RAMDASI a écrit :
> You have mentioned in the
> "a015f6f: Phonet: kill the ST-Ericsson pipe controller Kconfig",
> that "Support for manually enabling the pipe flow is removed as it
> did not work properly, does not fit well with the socket API, and
> I am not aware of any use at the moment.."
>
> On STE U8500 modem, you must first create pipe in disabled state, then do
> local link configuration (does't work when pipe is enabled) & then enable
> pipe.
The Kconfig option broke support for existing hardware (Nokia N900 as a USB
gadget) and userspace (namely the oFono ISI driver). We cannot expect
distributions to provide two different kernel builds for different flavors of ISI
modems.
> Because of this connect() cannot be used anymore and it needs to be modified
> to reintroduce pipe-controller functionality again.
As far as I can tell, that code NEVER worked properly. Not only the use of a
build-time option is inappropriate, but the code did not deal with a number of
new corner cases that it introduced.
> Do you have any suggestions?
I'm sorry but I don't really get where you're trying to get. The code had more
bugs than I could fix by myself, especially when I don't have the hardware and
the specification.
--
Rémi Denis-Courmont
http://www.remlab.net/
^ permalink raw reply
* [patch net-2.6] tg3: negate USE_PHYLIB flag check
From: Jiri Pirko @ 2011-10-12 9:00 UTC (permalink / raw)
To: netdev; +Cc: davem, eric.dumazet, mcarlson, mchan
USE_PHYLIB flag in tg3_remove_one() is being checked incorrectly. This
results tg3_phy_fini->phy_disconnect is never called and when tg3 module
is removed.
In my case this resulted in panics in phy_state_machine calling function
phydev->adjust_link.
So correct this check.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/tg3.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 4a1374d..c11a2b8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -15577,7 +15577,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
cancel_work_sync(&tp->reset_task);
- if (!tg3_flag(tp, USE_PHYLIB)) {
+ if (tg3_flag(tp, USE_PHYLIB)) {
tg3_phy_fini(tp);
tg3_mdio_fini(tp);
}
--
1.7.6.2
^ permalink raw reply related
* [PATCH] dev: use ifindex hash for dev_seq_ops
From: Mihai Maruseac @ 2011-10-12 9:49 UTC (permalink / raw)
To: davem
Cc: eric.dumazet, mirq-linux, therbert, jpirko, netdev, linux-kernel,
dbaluta, Mihai Maruseac
In-Reply-To: <1318000849-2531-1-git-send-email-mmaruseac@ixiacom.com>
Instead of using the dev->next chain and trying to resync at each call to
dev_seq_start, use the ifindex, keeping the last index in seq->private field.
Tests revealed the following results for ifconfig > /dev/null
* 1000 interfaces:
* 0.114s without patch
* 0.089s with patch
* 3000 interfaces:
* 0.489s without patch
* 0.110s with patch
* 5000 interfaces:
* 1.363s without patch
* 0.250s with patch
* 128000 interfaces (other setup):
* ~100s without patch
* ~30s with patch
---
net/core/dev.c | 53 ++++++++++++++++++++++++++++++++---------------------
1 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 70ecb86..3ca0df8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4041,6 +4041,35 @@ static int dev_ifconf(struct net *net, char __user *arg)
}
#ifdef CONFIG_PROC_FS
+
+struct dev_iter_state {
+ struct seq_net_private p;
+ int ifindex;
+};
+
+static inline struct net_device* next_dev(struct seq_file *seq, loff_t *pos)
+{
+ struct dev_iter_state *state = seq->private;
+ struct net *net = seq_file_net(seq);
+ struct net_device *dev = NULL;
+ loff_t off;
+
+ ++*pos;
+ dev = dev_get_by_index_rcu(net, state->ifindex);
+ state->ifindex++;
+ if (likely(dev))
+ return dev;
+
+ off = 1;
+ for_each_netdev_rcu(net, dev)
+ if (off++ == *pos) {
+ state->ifindex = dev->ifindex + 1;
+ return dev;
+ }
+
+ return NULL;
+}
+
/*
* This is invoked by the /proc filesystem handler to display a device
* in detail.
@@ -4048,33 +4077,15 @@ static int dev_ifconf(struct net *net, char __user *arg)
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{
- struct net *net = seq_file_net(seq);
- loff_t off;
- struct net_device *dev;
-
rcu_read_lock();
if (!*pos)
return SEQ_START_TOKEN;
-
- off = 1;
- for_each_netdev_rcu(net, dev)
- if (off++ == *pos)
- return dev;
-
- return NULL;
+ return next_dev(seq, pos);
}
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct net_device *dev = v;
-
- if (v == SEQ_START_TOKEN)
- dev = first_net_device_rcu(seq_file_net(seq));
- else
- dev = next_net_device_rcu(dev);
-
- ++*pos;
- return dev;
+ return next_dev(seq, pos);
}
void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4173,7 +4184,7 @@ static const struct seq_operations dev_seq_ops = {
static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &dev_seq_ops,
- sizeof(struct seq_net_private));
+ sizeof(struct dev_iter_state));
}
static const struct file_operations dev_seq_fops = {
--
1.7.4.1
^ permalink raw reply related
* [PATCH] dev: use ifindex hash for dev_seq_ops
From: Mihai Maruseac @ 2011-10-12 9:57 UTC (permalink / raw)
To: davem
Cc: eric.dumazet, mirq-linux, therbert, jpirko, netdev, linux-kernel,
dbaluta, Mihai Maruseac
In-Reply-To: <1318000849-2531-1-git-send-email-mmaruseac@ixiacom.com>
Instead of using the dev->next chain and trying to resync at each call to
dev_seq_start, use the ifindex, keeping the last index in seq->private field.
Tests revealed the following results for ifconfig > /dev/null
* 1000 interfaces:
* 0.114s without patch
* 0.089s with patch
* 3000 interfaces:
* 0.489s without patch
* 0.110s with patch
* 5000 interfaces:
* 1.363s without patch
* 0.250s with patch
* 128000 interfaces (other setup):
* ~100s without patch
* ~30s with patch
Signed-off-by: Mihai Maruseac <mmaruseac@ixiacom.com>
---
net/core/dev.c | 53 ++++++++++++++++++++++++++++++++---------------------
1 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 70ecb86..3ca0df8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4041,6 +4041,35 @@ static int dev_ifconf(struct net *net, char __user *arg)
}
#ifdef CONFIG_PROC_FS
+
+struct dev_iter_state {
+ struct seq_net_private p;
+ int ifindex;
+};
+
+static inline struct net_device *next_dev(struct seq_file *seq, loff_t *pos)
+{
+ struct dev_iter_state *state = seq->private;
+ struct net *net = seq_file_net(seq);
+ struct net_device *dev = NULL;
+ loff_t off;
+
+ ++*pos;
+ dev = dev_get_by_index_rcu(net, state->ifindex);
+ state->ifindex++;
+ if (likely(dev))
+ return dev;
+
+ off = 1;
+ for_each_netdev_rcu(net, dev)
+ if (off++ == *pos) {
+ state->ifindex = dev->ifindex + 1;
+ return dev;
+ }
+
+ return NULL;
+}
+
/*
* This is invoked by the /proc filesystem handler to display a device
* in detail.
@@ -4048,33 +4077,15 @@ static int dev_ifconf(struct net *net, char __user *arg)
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{
- struct net *net = seq_file_net(seq);
- loff_t off;
- struct net_device *dev;
-
rcu_read_lock();
if (!*pos)
return SEQ_START_TOKEN;
-
- off = 1;
- for_each_netdev_rcu(net, dev)
- if (off++ == *pos)
- return dev;
-
- return NULL;
+ return next_dev(seq, pos);
}
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct net_device *dev = v;
-
- if (v == SEQ_START_TOKEN)
- dev = first_net_device_rcu(seq_file_net(seq));
- else
- dev = next_net_device_rcu(dev);
-
- ++*pos;
- return dev;
+ return next_dev(seq, pos);
}
void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4173,7 +4184,7 @@ static const struct seq_operations dev_seq_ops = {
static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &dev_seq_ops,
- sizeof(struct seq_net_private));
+ sizeof(struct dev_iter_state));
}
static const struct file_operations dev_seq_fops = {
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] dev: use ifindex hash for dev_seq_ops
From: Mihai Maruseac @ 2011-10-12 9:59 UTC (permalink / raw)
To: Mihai Maruseac
Cc: dbaluta, mmaruseac, davem@davemloft.net, eric.dumazet@gmail.com,
mirq-linux@rere.qmqm.pl, therbert@google.com, jpirko@redhat.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1318413446-22258-1-git-send-email-mmaruseac@ixiacom.com>
On Wed, 2011-10-12 at 02:57 -0700, Mihai Maruseac wrote:
> Instead of using the dev->next chain and trying to resync at each call to
> dev_seq_start, use the ifindex, keeping the last index in seq->private field.
Please consider only my last patch email, the first one was missing
Signed-off-by line.
Thanks,
Mihai
^ permalink raw reply
* Re: [PATCH] dev: use name hash for dev_seq_ops.
From: Mihai Maruseac @ 2011-10-12 10:08 UTC (permalink / raw)
To: Stephen Hemminger
Cc: dbaluta, mmaruseac, Mihai Maruseac, davem@davemloft.net,
eric.dumazet@gmail.com, mirq-linux@rere.qmqm.pl,
therbert@google.com, jpirko@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20111010225536.6ca5c042@nehalam.linuxnetplumber.net>
On Mon, 2011-10-10 at 22:55 -0700, Stephen Hemminger wrote:
> If ifindex has been deleted, the code should fall back to delivering
> the next offset. That means for the rare case it would have the old
> behavior of linear searching. There is similar code already to
> deal with /proc/net/route; it continues from the last address.
We rewrote the patch to use the ifindex. Since we are at the beginning,
the patch was sent in another thread. We'll learn how to properly send
the mail.
--
Thanks,
Mihai
^ permalink raw reply
* RE: about phonet pipe controller
From: Hemant-vilas RAMDASI @ 2011-10-12 10:58 UTC (permalink / raw)
To: Rémi Denis-Courmont; +Cc: Srinidhi KASAGAR, netdev@vger.kernel.org
In-Reply-To: <3025840.a3oI7lSnik@leon.remlab.net>
Hi,
> -----Original Message-----
> From: Rémi Denis-Courmont [mailto:remi.denis-courmont@nokia.com]
> Sent: Wednesday, October 12, 2011 1:28 PM
> To: Hemant-vilas RAMDASI
> Cc: Srinidhi KASAGAR; netdev@vger.kernel.org
> Subject: Re: about phonet pipe controller
>
> Le Mercredi 12 Octobre 2011 09:25:01 ext Hemant-vilas RAMDASI a écrit :
> > You have mentioned in the
> > "a015f6f: Phonet: kill the ST-Ericsson pipe controller Kconfig",
> > that "Support for manually enabling the pipe flow is removed as it
> > did not work properly, does not fit well with the socket API, and
> > I am not aware of any use at the moment.."
> >
> > On STE U8500 modem, you must first create pipe in disabled state,
> then do
> > local link configuration (does't work when pipe is enabled) & then
> enable
> > pipe.
>
> The Kconfig option broke support for existing hardware (Nokia N900 as a
> USB
> gadget) and userspace (namely the oFono ISI driver). We cannot expect
> distributions to provide two different kernel builds for different
> flavors of ISI
> modems.
>
> > Because of this connect() cannot be used anymore and it needs to be
> modified
> > to reintroduce pipe-controller functionality again.
>
> As far as I can tell, that code NEVER worked properly. Not only the use
> of a
> build-time option is inappropriate, but the code did not deal with a
> number of
> new corner cases that it introduced.
>
Yes, I agree that build-time option is not required..But what are those corner cases?
> > Do you have any suggestions?
>
> I'm sorry but I don't really get where you're trying to get. The code
> had more
> bugs than I could fix by myself, especially when I don't have the
> hardware and
> the specification.
>
As far as I know, connect() API was not there initially. It was implemented as part
of pipe-controller after your feedback.
We would like to modify connect to create pipe in disabled mode and enable it in
setsockopt call.
Basically the problem with current implementation is that there is no way today for
anyone to disable/enable pipe.
Regards,
Hemant
^ permalink raw reply
* Re: about phonet pipe controller
From: Rémi Denis-Courmont @ 2011-10-12 11:08 UTC (permalink / raw)
To: netdev@vger.kernel.org
In-Reply-To: <81C3A93C17462B4BBD7E272753C105791EAACAEA43@EXDCVYMBSTM005.EQ1STM.local>
Le Mercredi 12 Octobre 2011 12:58:08 ext Hemant-vilas RAMDASI a écrit :
> Yes, I agree that build-time option is not required..But what are those
> corner cases?
This is old stuff. I don't remember the details, nor did I investigate the
whole thing. But the code seemed to assume that userspace are fully trusted,
the remote Phonet nodes also. That does not work.
Protocol-level race conditions, API level race conditions, crashed remote
peers, crashing user space processes, invalid API use, etc. All that needs to
be dealt with safely. This is kernel code!
--
Rémi Denis-Courmont
http://www.remlab.net/
^ permalink raw reply
* [PATCH] smsc911x: Add support for SMSC LAN89218
From: Phil Edworthy @ 2011-10-12 12:29 UTC (permalink / raw)
To: netdev; +Cc: Steve Glendinning, Phil Edworthy
LAN89218 is register compatible with LAN911x.
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
drivers/net/smsc911x.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index b9016a3..c90ddb6 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -26,6 +26,7 @@
* LAN9215, LAN9216, LAN9217, LAN9218
* LAN9210, LAN9211
* LAN9220, LAN9221
+ * LAN89218
*
*/
@@ -1983,6 +1984,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
case 0x01170000:
case 0x01160000:
case 0x01150000:
+ case 0x218A0000:
/* LAN911[5678] family */
pdata->generation = pdata->idrev & 0x0000FFFF;
break;
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH v2] netconsole: enable netconsole can make net_device refcnt incorrent
From: Flavio Leitner @ 2011-10-12 13:23 UTC (permalink / raw)
To: Gao feng; +Cc: netdev, davem, eric.dumazet
In-Reply-To: <1318385291-15483-1-git-send-email-gaofeng@cn.fujitsu.com>
On Wed, 12 Oct 2011 10:08:11 +0800
Gao feng <gaofeng@cn.fujitsu.com> wrote:
> There is no check if netconsole is enabled current.
> so when exec echo 1 > enabled;
> the reference of net_device will increment always.
>
> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
> ---
> drivers/net/netconsole.c | 5 +++++
> 1 files changed, 5 insertions(+), 0 deletions(-)
Looks better, thanks!
Acked-by: Flavio Leitner <fbl@redhat.com>
fbl
^ permalink raw reply
* Re: bridge: HSR support
From: David Lamparter @ 2011-10-12 13:28 UTC (permalink / raw)
To: Arvid Brodin; +Cc: netdev, Stephen Hemminger, Lennert Buytenhek
In-Reply-To: <4E94D67A.9060207@enea.com>
On Wed, Oct 12, 2011 at 01:51:22AM +0200, Arvid Brodin wrote:
> Stephen Hemminger wrote:
> >> I want to add support for HSR ("High-availability Seamless Redundancy",
> >> IEC-62439-3) to the bridge code. With HSR, all connected units have two network
> >> ports and are connected in a ring. All new Ethernet packets are sent on both
> >> ports (or passed through if the current unit is not the originating unit).
> >> The same packet is never passed twice.
How does the bridge decide whether a packet is arriving the second time?
Is the ring pre-resolved to stop things or does this happen per-packet?
-David
^ permalink raw reply
* [net-next 0/5] stmmac: update to Oct 2011 version (V2)
From: Giuseppe CAVALLARO @ 2011-10-12 13:38 UTC (permalink / raw)
To: netdev; +Cc: davem, Giuseppe Cavallaro
This patches update the driver adding the chained
descriptor mode and some new useful fixes.
Chained / Ring modes have been reworked after D. Miller
advice and removing the ifdef selection within the C
code.
Giuseppe Cavallaro (4):
stmmac: add CHAINED descriptor mode support
stmmac: allow mtu bigger than 1500 in case of normal desc.
stmmac: protect tx process with lock
stmmac: update the driver version and doc
Srinivas Kandagatla (1):
stmmac: Stop advertising 1000Base capabilties for non GMII iface
(v2).
Documentation/networking/stmmac.txt | 11 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 18 +
drivers/net/ethernet/stmicro/stmmac/common.h | 19 +
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 51 ---
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 42 --
drivers/net/ethernet/stmicro/stmmac/ring_mode.h | 450 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 148 +++----
8 files changed, 564 insertions(+), 178 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/ring_mode.h
--
1.7.4.4
^ permalink raw reply
* [net-next 1/5] stmmac: add CHAINED descriptor mode support (V2)
From: Giuseppe CAVALLARO @ 2011-10-12 13:38 UTC (permalink / raw)
To: netdev; +Cc: davem, Giuseppe Cavallaro, Rayagond Kokatanur
In-Reply-To: <1318426688-9419-1-git-send-email-peppe.cavallaro@st.com>
This patch enhances the STMMAC driver to support CHAINED mode of
descriptor (useful also on validation side).
STMMAC supports DMA descriptor to operate both in dual buffer(RING)
and linked-list(CHAINED) mode. In RING mode (default) each descriptor
points to two data buffer pointers whereas in CHAINED mode they point
to only one data buffer pointer.
In CHAINED mode each descriptor will have pointer to next descriptor in
the list, hence creating the explicit chaining in the descriptor itself,
whereas such explicit chaining is not possible in RING mode.
First version of this work has been done by Rayagond; I've reworked
the whole support and added a new header file to implement the
helper routines specialised for chained/ring modes (as D. Miller
suggested).
Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 18 +
drivers/net/ethernet/stmicro/stmmac/common.h | 19 +
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 51 ---
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 42 --
drivers/net/ethernet/stmicro/stmmac/ring_mode.h | 450 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 121 ++----
6 files changed, 531 insertions(+), 170 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/ring_mode.h
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 8cd9dde..ac6f190 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -63,4 +63,22 @@ config STMMAC_RTC_TIMER
endchoice
+choice
+ prompt "Select the DMA TX/RX descriptor operating modes"
+ depends on STMMAC_ETH
+ ---help---
+ This driver supports DMA descriptor to operate both in dual buffer
+ (RING) and linked-list(CHAINED) mode. In RING mode each descriptor
+ points to two data buffer pointers whereas in CHAINED mode they
+ points to only one data buffer pointer.
+
+config STMMAC_RING
+ bool "Enable Descriptor Ring Mode"
+
+config STMMAC_CHAINED
+ bool "Enable Descriptor Chained Mode"
+
+endchoice
+
+
endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 22c61b2..90ba81a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -152,6 +152,7 @@ struct dma_features {
#define BUF_SIZE_8KiB 8192
#define BUF_SIZE_4KiB 4096
#define BUF_SIZE_2KiB 2048
+#define DMA_BUFFER_SIZE BUF_SIZE_2KiB
/* Power Down and WOL */
#define PMT_NOT_SUPPORTED 0
@@ -261,6 +262,7 @@ struct mac_device_info {
const struct stmmac_ops *mac;
const struct stmmac_desc_ops *desc;
const struct stmmac_dma_ops *dma;
+ const struct stmmac_ring_mode_ops *ring;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
unsigned int synopsys_uid;
@@ -274,3 +276,20 @@ extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low);
extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
+
+extern void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic);
+extern void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag);
+extern void enh_desc_release_tx_desc(struct dma_desc *p);
+extern void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size);
+extern void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic);
+extern void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag);
+extern void ndesc_release_tx_desc(struct dma_desc *p);
+extern void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size);
+extern void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic);
+
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index e5dfb6a..f378b3b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -226,35 +226,6 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
return ret;
}
-static void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
- int disable_rx_ic)
-{
- int i;
- for (i = 0; i < ring_size; i++) {
- p->des01.erx.own = 1;
- p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
- /* To support jumbo frames */
- p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
- if (i == ring_size - 1)
- p->des01.erx.end_ring = 1;
- if (disable_rx_ic)
- p->des01.erx.disable_ic = 1;
- p++;
- }
-}
-
-static void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
-{
- int i;
-
- for (i = 0; i < ring_size; i++) {
- p->des01.etx.own = 0;
- if (i == ring_size - 1)
- p->des01.etx.end_ring = 1;
- p++;
- }
-}
-
static int enh_desc_get_tx_owner(struct dma_desc *p)
{
return p->des01.etx.own;
@@ -280,28 +251,6 @@ static int enh_desc_get_tx_ls(struct dma_desc *p)
return p->des01.etx.last_segment;
}
-static void enh_desc_release_tx_desc(struct dma_desc *p)
-{
- int ter = p->des01.etx.end_ring;
-
- memset(p, 0, offsetof(struct dma_desc, des2));
- p->des01.etx.end_ring = ter;
-}
-
-static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
- int csum_flag)
-{
- p->des01.etx.first_segment = is_fs;
- if (unlikely(len > BUF_SIZE_4KiB)) {
- p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
- p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
- } else {
- p->des01.etx.buffer1_size = len;
- }
- if (likely(csum_flag))
- p->des01.etx.checksum_insertion = cic_full;
-}
-
static void enh_desc_clear_tx_ic(struct dma_desc *p)
{
p->des01.etx.interrupt = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 029c2a2..1cd985f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -119,32 +119,6 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
return ret;
}
-static void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
- int disable_rx_ic)
-{
- int i;
- for (i = 0; i < ring_size; i++) {
- p->des01.rx.own = 1;
- p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
- if (i == ring_size - 1)
- p->des01.rx.end_ring = 1;
- if (disable_rx_ic)
- p->des01.rx.disable_ic = 1;
- p++;
- }
-}
-
-static void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
-{
- int i;
- for (i = 0; i < ring_size; i++) {
- p->des01.tx.own = 0;
- if (i == ring_size - 1)
- p->des01.tx.end_ring = 1;
- p++;
- }
-}
-
static int ndesc_get_tx_owner(struct dma_desc *p)
{
return p->des01.tx.own;
@@ -170,22 +144,6 @@ static int ndesc_get_tx_ls(struct dma_desc *p)
return p->des01.tx.last_segment;
}
-static void ndesc_release_tx_desc(struct dma_desc *p)
-{
- int ter = p->des01.tx.end_ring;
-
- memset(p, 0, offsetof(struct dma_desc, des2));
- /* set termination field */
- p->des01.tx.end_ring = ter;
-}
-
-static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
- int csum_flag)
-{
- p->des01.tx.first_segment = is_fs;
- p->des01.tx.buffer1_size = len;
-}
-
static void ndesc_clear_tx_ic(struct dma_desc *p)
{
p->des01.tx.interrupt = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.h b/drivers/net/ethernet/stmicro/stmmac/ring_mode.h
new file mode 100644
index 0000000..32fe688
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.h
@@ -0,0 +1,450 @@
+/*******************************************************************************
+ Header File to describe the DMA descriptor ring/chain(s)
+
+ Copyright(C) 2011 STMicroelectronics Ltd
+
+ It defines all the functions used to handle the normal/enhanced
+ descriptors in case of the DMA is configured to work in chained or
+ in ring mode.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#if defined(CONFIG_STMMAC_RING)
+
+static unsigned int stmmac_jumbo_frm(struct stmmac_priv *priv,
+ struct sk_buff *skb, int csum_insertion)
+{
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int buf_max_size, len;
+
+ if (priv->plat->enh_desc)
+ buf_max_size = BUF_SIZE_8KiB;
+ else
+ buf_max_size = BUF_SIZE_2KiB;
+
+ len = nopaged_len - buf_max_size;
+
+ if (nopaged_len > BUF_SIZE_8KiB) {
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ buf_max_size, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, buf_max_size,
+ csum_insertion);
+
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ desc->des2 = dma_map_single(priv->device,
+ skb->data + buf_max_size,
+ len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ } else {
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->des3 = desc->des2 + BUF_SIZE_4KiB;
+ priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
+ csum_insertion);
+ }
+
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frame(struct stmmac_priv *priv,
+ struct sk_buff *skb,
+ int csum, struct dma_desc *desc)
+{
+ unsigned int ret = 0;
+
+ if (unlikely(skb->len >= BUF_SIZE_4KiB)) {
+ unsigned int entry = stmmac_jumbo_frm(priv, skb, csum);
+ desc = priv->dma_tx + entry;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+ /* Fill DES3 in case of RING mode */
+ if (bfsize >= BUF_SIZE_8KiB)
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+/* In ring mode we need to fill the desc3 because it is used
+ * as buffer */
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+ if (unlikely(des3_as_data_buf))
+ p->des3 = p->des2 + BUF_SIZE_8KiB;
+}
+
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+ if (unlikely(p->des3))
+ p->des3 = 0;
+}
+
+static int stmmac_set_bfsize(int mtu, int bufsize)
+{
+ int ret = bufsize;
+
+ if (unlikely(mtu >= BUF_SIZE_8KiB))
+ ret = BUF_SIZE_16KiB;
+ else if (unlikely(mtu >= BUF_SIZE_4KiB))
+ ret = BUF_SIZE_8KiB;
+ else if (unlikely(mtu >= BUF_SIZE_2KiB))
+ ret = BUF_SIZE_4KiB;
+ else if (unlikely(mtu >= DMA_BUFFER_SIZE))
+ ret = BUF_SIZE_2KiB;
+ else
+ ret = DMA_BUFFER_SIZE;
+
+ return ret;
+}
+
+/* Normal/enhanced descriptor functions for RING mode */
+
+inline void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.erx.own = 1;
+ p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
+ /* To support jumbo frames */
+ p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1;
+ if (i == (ring_size - 1))
+ p->des01.erx.end_ring = 1;
+ if (disable_rx_ic)
+ p->des01.erx.disable_ic = 1;
+ p++;
+ }
+}
+
+inline void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+ int i;
+
+ for (i = 0; i < ring_size; i++) {
+ p->des01.etx.own = 0;
+ if (i == (ring_size - 1))
+ p->des01.etx.end_ring = 1;
+ p++;
+ }
+}
+
+inline void enh_desc_release_tx_desc(struct dma_desc *p)
+{
+ int ter = p->des01.etx.end_ring;
+
+ memset(p, 0, offsetof(struct dma_desc, des2));
+ p->des01.etx.end_ring = ter;
+}
+
+inline void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag)
+{
+ p->des01.etx.first_segment = is_fs;
+
+ if (unlikely(len > BUF_SIZE_4KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_4KiB;
+ p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB;
+ } else
+ p->des01.etx.buffer1_size = len;
+
+ if (likely(csum_flag))
+ p->des01.etx.checksum_insertion = cic_full;
+}
+
+inline void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.rx.own = 1;
+ p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
+ if (i == (ring_size - 1))
+ p->des01.rx.end_ring = 1;
+ if (disable_rx_ic)
+ p->des01.rx.disable_ic = 1;
+ p++;
+ }
+}
+
+inline void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.tx.own = 0;
+ if (i == (ring_size - 1))
+ p->des01.tx.end_ring = 1;
+ p++;
+ }
+}
+
+inline void ndesc_release_tx_desc(struct dma_desc *p)
+{
+ int ter = p->des01.tx.end_ring;
+
+ memset(p, 0, offsetof(struct dma_desc, des2));
+ /* set termination field */
+ p->des01.tx.end_ring = ter;
+}
+
+inline void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag)
+{
+ p->des01.tx.first_segment = is_fs;
+
+ if (unlikely(len > BUF_SIZE_2KiB)) {
+ p->des01.etx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.etx.buffer2_size = len - p->des01.etx.buffer1_size;
+ } else
+ p->des01.tx.buffer1_size = len;
+}
+
+#else
+
+/* Chained mode functions */
+
+static unsigned int stmmac_jumbo_frm(struct stmmac_priv *priv,
+ struct sk_buff *skb, int csum_insertion)
+{
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int entry = priv->cur_tx % txsize;
+ struct dma_desc *desc = priv->dma_tx + entry;
+ unsigned int nopaged_len = skb_headlen(skb);
+ unsigned int buf_max_size;
+ unsigned int i = 1, len;
+
+ if (priv->plat->enh_desc)
+ buf_max_size = BUF_SIZE_8KiB;
+ else
+ buf_max_size = BUF_SIZE_2KiB;
+
+ len = nopaged_len - buf_max_size;
+
+ desc->des2 = dma_map_single(priv->device, skb->data,
+ buf_max_size, DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 1, buf_max_size, csum_insertion);
+
+ while (len != 0) {
+ entry = (++priv->cur_tx) % txsize;
+ desc = priv->dma_tx + entry;
+
+ if (len > buf_max_size) {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data +
+ buf_max_size * i),
+ buf_max_size,
+ DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, buf_max_size,
+ csum_insertion);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len -= buf_max_size;
+ i++;
+ } else {
+ desc->des2 = dma_map_single(priv->device,
+ (skb->data +
+ buf_max_size * i), len,
+ DMA_TO_DEVICE);
+ priv->hw->desc->prepare_tx_desc(desc, 0, len,
+ csum_insertion);
+ priv->hw->desc->set_tx_owner(desc);
+ priv->tx_skbuff[entry] = NULL;
+ len = 0;
+ }
+ }
+ return entry;
+}
+
+static unsigned int stmmac_is_jumbo_frame(struct stmmac_priv *priv,
+ struct sk_buff *skb,
+ int csum, struct dma_desc *desc)
+{
+ unsigned int ret = 0;
+
+ if ((priv->plat->enh_desc && unlikely(skb->len > BUF_SIZE_8KiB)) ||
+ (!priv->plat->enh_desc && unlikely(skb->len > BUF_SIZE_2KiB))) {
+ unsigned int entry = stmmac_jumbo_frm(priv, skb, csum);
+ desc = priv->dma_tx + entry;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
+{
+}
+
+static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
+{
+}
+
+static void stmmac_clean_desc3(struct dma_desc *p)
+{
+}
+
+/* In chained mode des3 points to the next element in the ring.
+ * The latest element has to point to the head.
+ */
+static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size)
+{
+ int i;
+ struct dma_desc *p = des;
+ dma_addr_t dma_phy = phy_addr;
+
+ for (i = 0; i < (size - 1); i++) {
+ dma_phy += sizeof(struct dma_desc);
+ p->des3 = (unsigned int)dma_phy;
+ p++;
+ }
+ p->des3 = (unsigned int)phy_addr;
+}
+
+static int stmmac_set_bfsize(int mtu, int bufsize)
+{
+ int ret = bufsize;
+
+ if (unlikely(mtu >= BUF_SIZE_4KiB))
+ ret = BUF_SIZE_8KiB;
+ else if (unlikely(mtu >= BUF_SIZE_2KiB))
+ ret = BUF_SIZE_4KiB;
+ else if (unlikely(mtu >= DMA_BUFFER_SIZE))
+ ret = BUF_SIZE_2KiB;
+ else
+ ret = DMA_BUFFER_SIZE;
+
+ return ret;
+}
+
+/* Normal/enhanced descriptor functions for RING mode */
+
+inline void enh_desc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.erx.own = 1;
+ p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
+ /* To support jumbo frames */
+ p->des01.erx.second_address_chained = 1;
+ if (disable_rx_ic)
+ p->des01.erx.disable_ic = 1;
+ p++;
+ }
+}
+
+inline void enh_desc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+ int i;
+
+ for (i = 0; i < ring_size; i++) {
+ p->des01.etx.own = 0;
+ p->des01.etx.second_address_chained = 1;
+ p++;
+ }
+}
+
+inline void enh_desc_release_tx_desc(struct dma_desc *p)
+{
+ memset(p, 0, offsetof(struct dma_desc, des2));
+ p->des01.etx.second_address_chained = 1;
+}
+
+inline void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag)
+{
+ p->des01.etx.first_segment = is_fs;
+ p->des01.etx.buffer1_size = len;
+
+ if (likely(csum_flag))
+ p->des01.etx.checksum_insertion = cic_full;
+}
+
+inline void ndesc_init_rx_desc(struct dma_desc *p, unsigned int ring_size,
+ int disable_rx_ic)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.rx.own = 1;
+ p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
+ p->des01.rx.buffer2_size = BUF_SIZE_2KiB - 1;
+ if (i == (ring_size - 1))
+ p->des01.rx.end_ring = 1;
+ if (disable_rx_ic)
+ p->des01.rx.disable_ic = 1;
+ p++;
+ }
+}
+
+inline void ndesc_init_tx_desc(struct dma_desc *p, unsigned int ring_size)
+{
+ int i;
+ for (i = 0; i < ring_size; i++) {
+ p->des01.tx.own = 0;
+ if (i == (ring_size - 1))
+ p->des01.tx.end_ring = 1;
+ p++;
+ }
+}
+
+inline void ndesc_release_tx_desc(struct dma_desc *p)
+{
+ memset(p, 0, offsetof(struct dma_desc, des2));
+ p->des01.tx.second_address_chained = 1;
+}
+
+inline void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
+ int csum_flag)
+{
+ p->des01.tx.first_segment = is_fs;
+ p->des01.tx.buffer1_size = len;
+}
+#endif
+
+struct stmmac_ring_mode_ops {
+ unsigned int (*is_jumbo_frame) (struct stmmac_priv *priv,
+ struct sk_buff *skb,
+ int csum, struct dma_desc *desc);
+ void (*refill_desc3) (int bfsize, struct dma_desc *p);
+ void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
+ void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
+ unsigned int size);
+ void (*clean_desc3) (struct dma_desc *p);
+ int (*set_bfsize) (int mtu, int bufsize);
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c0ee6b6..ba7af2c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2,7 +2,7 @@
This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
ST Ethernet IPs are built around a Synopsys IP Core.
- Copyright (C) 2007-2009 STMicroelectronics Ltd
+ Copyright(C) 2007-2011 STMicroelectronics Ltd
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -47,11 +47,12 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
-#include "stmmac.h"
#ifdef CONFIG_STMMAC_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#endif
+#include "stmmac.h"
+#include "ring_mode.h"
#define STMMAC_RESOURCE_NAME "stmmaceth"
@@ -131,7 +132,6 @@ module_param(tmrate, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)");
#endif
-#define DMA_BUFFER_SIZE BUF_SIZE_2KiB
static int buf_sz = DMA_BUFFER_SIZE;
module_param(buf_sz, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(buf_sz, "DMA buffer size");
@@ -142,6 +142,16 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+/* Functions used for chained/ring modes */
+static const struct stmmac_ring_mode_ops ring_mode_ops = {
+ .is_jumbo_frame = stmmac_is_jumbo_frame,
+ .refill_desc3 = stmmac_refill_desc3,
+ .init_desc3 = stmmac_init_desc3,
+ .init_dma_chain = stmmac_init_dma_chain,
+ .clean_desc3 = stmmac_clean_desc3,
+ .set_bfsize = stmmac_set_bfsize,
+};
+
/**
* stmmac_verify_args - verify the driver parameters.
* Description: it verifies if some wrong parameter is passed to the driver.
@@ -385,7 +395,8 @@ static void display_ring(struct dma_desc *p, int size)
* init_dma_desc_rings - init the RX/TX descriptor rings
* @dev: net device structure
* Description: this function initializes the DMA RX/TX descriptors
- * and allocates the socket buffers.
+ * and allocates the socket buffers. It suppors the chained and ring
+ * modes.
*/
static void init_dma_desc_rings(struct net_device *dev)
{
@@ -394,31 +405,22 @@ static void init_dma_desc_rings(struct net_device *dev)
struct sk_buff *skb;
unsigned int txsize = priv->dma_tx_size;
unsigned int rxsize = priv->dma_rx_size;
- unsigned int bfsize = priv->dma_buf_sz;
- int buff2_needed = 0, dis_ic = 0;
+ unsigned int bfsize;
+ int dis_ic = 0;
+ int des3_as_data_buf = 0;
- /* Set the Buffer size according to the MTU;
- * indeed, in case of jumbo we need to bump-up the buffer sizes.
- */
- if (unlikely(dev->mtu >= BUF_SIZE_8KiB))
- bfsize = BUF_SIZE_16KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_4KiB))
- bfsize = BUF_SIZE_8KiB;
- else if (unlikely(dev->mtu >= BUF_SIZE_2KiB))
- bfsize = BUF_SIZE_4KiB;
- else if (unlikely(dev->mtu >= DMA_BUFFER_SIZE))
- bfsize = BUF_SIZE_2KiB;
- else
- bfsize = DMA_BUFFER_SIZE;
+ /* Set the max buffer size according to the DESC mode used
+ * and the MTU. */
+ bfsize = priv->hw->ring->set_bfsize(dev->mtu, priv->dma_buf_sz);
+
+ if (bfsize == BUF_SIZE_16KiB)
+ des3_as_data_buf = 1;
#ifdef CONFIG_STMMAC_TIMER
/* Disable interrupts on completion for the reception if timer is on */
if (likely(priv->tm->enable))
dis_ic = 1;
#endif
- /* If the MTU exceeds 8k so use the second buffer in the chain */
- if (bfsize >= BUF_SIZE_8KiB)
- buff2_needed = 1;
DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
txsize, rxsize, bfsize);
@@ -446,7 +448,7 @@ static void init_dma_desc_rings(struct net_device *dev)
return;
}
- DBG(probe, INFO, "stmmac (%s) DMA desc rings: virt addr (Rx %p, "
+ DBG(probe, INFO, "stmmac (%s) DMA desc: virt addr (Rx %p, "
"Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
dev->name, priv->dma_rx, priv->dma_tx,
(unsigned int)priv->dma_rx_phy, (unsigned int)priv->dma_tx_phy);
@@ -468,8 +470,9 @@ static void init_dma_desc_rings(struct net_device *dev)
bfsize, DMA_FROM_DEVICE);
p->des2 = priv->rx_skbuff_dma[i];
- if (unlikely(buff2_needed))
- p->des3 = p->des2 + BUF_SIZE_8KiB;
+
+ priv->hw->ring->init_desc3(des3_as_data_buf, p);
+
DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]);
}
@@ -483,6 +486,12 @@ static void init_dma_desc_rings(struct net_device *dev)
priv->tx_skbuff[i] = NULL;
priv->dma_tx[i].des2 = 0;
}
+
+ /* In case of Chained mode this sets the des3 to the next
+ * element in the chain */
+ priv->hw->ring->init_dma_chain(priv->dma_rx, priv->dma_rx_phy, rxsize);
+ priv->hw->ring->init_dma_chain(priv->dma_tx, priv->dma_tx_phy, txsize);
+
priv->dirty_tx = 0;
priv->cur_tx = 0;
@@ -611,8 +620,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
dma_unmap_single(priv->device, p->des2,
priv->hw->desc->get_tx_len(p),
DMA_TO_DEVICE);
- if (unlikely(p->des3))
- p->des3 = 0;
+ priv->hw->ring->clean_desc3(p);
if (likely(skb != NULL)) {
/*
@@ -1005,47 +1013,6 @@ static int stmmac_release(struct net_device *dev)
return 0;
}
-static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb,
- struct net_device *dev,
- int csum_insertion)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- unsigned int nopaged_len = skb_headlen(skb);
- unsigned int txsize = priv->dma_tx_size;
- unsigned int entry = priv->cur_tx % txsize;
- struct dma_desc *desc = priv->dma_tx + entry;
-
- if (nopaged_len > BUF_SIZE_8KiB) {
-
- int buf2_size = nopaged_len - BUF_SIZE_8KiB;
-
- desc->des2 = dma_map_single(priv->device, skb->data,
- BUF_SIZE_8KiB, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB,
- csum_insertion);
-
- entry = (++priv->cur_tx) % txsize;
- desc = priv->dma_tx + entry;
-
- desc->des2 = dma_map_single(priv->device,
- skb->data + BUF_SIZE_8KiB,
- buf2_size, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size,
- csum_insertion);
- priv->hw->desc->set_tx_owner(desc);
- priv->tx_skbuff[entry] = NULL;
- } else {
- desc->des2 = dma_map_single(priv->device, skb->data,
- nopaged_len, DMA_TO_DEVICE);
- desc->des3 = desc->des2 + BUF_SIZE_4KiB;
- priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
- csum_insertion);
- }
- return entry;
-}
-
/**
* stmmac_xmit:
* @skb : the socket buffer
@@ -1094,10 +1061,10 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len, skb_headlen(skb), nfrags, skb->ip_summed);
#endif
priv->tx_skbuff[entry] = skb;
- if (unlikely(skb->len >= BUF_SIZE_4KiB)) {
- entry = stmmac_handle_jumbo_frames(skb, dev, csum_insertion);
- desc = priv->dma_tx + entry;
- } else {
+
+ /* Manage Jumbo frames depending on the descriptor mode
+ * actually used (chained or ring). */
+ if (!priv->hw->ring->is_jumbo_frame(priv, skb, csum_insertion, desc)) {
unsigned int nopaged_len = skb_headlen(skb);
desc->des2 = dma_map_single(priv->device, skb->data,
nopaged_len, DMA_TO_DEVICE);
@@ -1187,11 +1154,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
DMA_FROM_DEVICE);
(p + entry)->des2 = priv->rx_skbuff_dma[entry];
- if (unlikely(priv->plat->has_gmac)) {
- if (bfsize >= BUF_SIZE_8KiB)
- (p + entry)->des3 =
- (p + entry)->des2 + BUF_SIZE_8KiB;
- }
+
+ if (unlikely(priv->plat->has_gmac))
+ priv->hw->ring->refill_desc3(bfsize, p + entry);
+
RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
}
wmb();
@@ -1767,6 +1733,7 @@ static int stmmac_mac_device_setup(struct net_device *dev)
device->desc = &ndesc_ops;
priv->hw = device;
+ priv->hw->ring = &ring_mode_ops;
if (device_can_wakeup(priv->device)) {
priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
--
1.7.4.4
^ 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