* spidernet: dynamic phy setup code @ 2007-01-26 13:09 Jens Osterkamp 2007-01-26 17:58 ` Linas Vepstas ` (2 more replies) 0 siblings, 3 replies; 16+ messages in thread From: Jens Osterkamp @ 2007-01-26 13:09 UTC (permalink / raw) To: Ishizaki Kou; +Cc: cbe-oss-dev, linuxppc-dev, netdev, jgarzik, James K Lewis This patch modifies the patch submitted by Kou Ishizaki to make it work on the blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). Unfortunately I dont have access to a Celleb so I cannot test it there. The basic logic behind this is simple : when the interface first comes up it tries to detect the phy. When the phy is detected, it is initially set up to use copper. A timer is set to check the link status in spidernet_link_phy using poll_link. If link check fails more than SPIDER_NET_ANEG_TIMEOUT times, it switches to fiber link with autonegotiation. If that fails more than SPIDER_NET_ANEG_TIMEOUT times, it switches to fiber link with no autonegotiation. If that also fails, it goes back to copper, and so forth. If the link comes up, it prints the link abilites and we are done. The name of the phy found attached to the spider chip is reported to the user. Hardcoded values for the timeout are moved to #defines. I put in a few comments to make the code more readable. Signed-off-by: Jens Osterkamp <jens@de.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Index: linux-2.6/drivers/net/spider_net.c =================================================================== --- linux-2.6.orig/drivers/net/spider_net.c +++ linux-2.6/drivers/net/spider_net.c @@ -1280,19 +1280,23 @@ spider_net_set_mac(struct net_device *ne * spider_net_link_reset * @netdev: net device structure * + * This is called when the PHY_LINK signal is asserted. For the blade this is + * not connected so we should never get here. + * */ static void spider_net_link_reset(struct net_device *netdev) { - struct spider_net_card *card=netdev_priv(netdev); del_timer_sync(&card->aneg_timer); + /* clear interrupt, block further interrupts */ spider_net_write_reg(card, SPIDER_NET_GMACST, spider_net_read_reg(card, SPIDER_NET_GMACST)); spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); + /* reset phy and setup aneg */ mii_phy_probe(&card->phy, card->phy.mii_id); spider_net_setup_aneg(card, is1000); if (card->phy.def->phy_id) @@ -1616,6 +1620,7 @@ spider_net_init_card(struct spider_net_c spider_net_write_reg(card, SPIDER_NET_CKRCTRL, SPIDER_NET_CKRCTRL_RUN_VALUE); + /* trigger ETOMOD signal */ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); @@ -1739,6 +1744,8 @@ spider_net_open(struct net_device *netde if (spider_net_init_firmware(card)) goto init_firmware_failed; + /* start probing with copper */ + card->phy.medium = GMII_COPPER; spider_net_setup_aneg(card, is1000); if (card->phy.def->phy_id) mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); @@ -1805,43 +1812,54 @@ static void spider_net_link_phy(unsigned struct spider_net_card *card = (struct spider_net_card *)data; struct mii_phy *phy = &card->phy; - if (card->aneg_count > 10) { - /* timeout */ - card->aneg_count = 0; - is1000 = !is1000; - goto re_setup; + /* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */ + if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) { + + pr_info("%s: link is down, trying to bring it up\n", card->netdev->name); + + switch(phy->medium) { + case GMII_COPPER: + /* enable fiber with autonegotiation first */ + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 1); + phy->medium = GMII_FIBER; + break; + + case GMII_FIBER: + /* fiber didn't come up, try to disable fiber autoneg */ + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 0); + phy->medium = GMII_UNKNOWN; + break; + + case GMII_UNKNOWN: + /* copper, fiber with and without autoneg failed, + * retry from beginning */ + spider_net_setup_aneg(card, is1000); + phy->medium = GMII_COPPER; + break; + } + + card->aneg_count = 0; + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + return; } + /* link still not up, try again later */ if (!(phy->def->ops->poll_link(phy))) { card->aneg_count++; mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); return; } + /* link came up, get abilities */ phy->def->ops->read_link(phy); - if (phy->speed == 1000 && !is1000) { - is1000 = 1; - goto re_setup; - } else if(phy->speed != 1000 && is1000) { - is1000 = 0; - goto re_setup; - } - - spider_net_write_reg(card, SPIDER_NET_GMACST, - spider_net_read_reg(card, SPIDER_NET_GMACST)); - spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); - - pr_info("Found %s with %i Mbps, %s-duplex.\n", - phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); + pr_info("%s: link is up with %i Mbps, %s-duplex, %sautoneg.\n", + card->netdev->name, phy->speed, phy->duplex==1 ? "Full" : "Half", + phy->autoneg==1 ? "" : "no "); return; - -re_setup: - mii_phy_probe(phy, phy->mii_id); - spider_net_setup_aneg(card, is1000); - card->aneg_count = 0; - mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); } /** @@ -1871,8 +1889,10 @@ spider_net_setup_phy(struct spider_net_c unsigned short id; id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); if (id != 0x0000 && id != 0xffff) { - mii_phy_probe(phy, phy->mii_id); + if (!mii_phy_probe(phy, phy->mii_id)) { + pr_info("Found %s.\n", phy->def->name); break; + } } } Index: linux-2.6/drivers/net/spider_net.h =================================================================== --- linux-2.6.orig/drivers/net/spider_net.h +++ linux-2.6/drivers/net/spider_net.h @@ -51,7 +51,8 @@ extern char spider_net_driver_name[]; #define SPIDER_NET_TX_DESCRIPTORS_MAX 512 #define SPIDER_NET_TX_TIMER (HZ/5) -#define SPIDER_NET_ANEG_TIMER (HZ*2) +#define SPIDER_NET_ANEG_TIMER (HZ) +#define SPIDER_NET_ANEG_TIMEOUT 2 #define SPIDER_NET_RX_CSUM_DEFAULT 1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-01-26 13:09 spidernet: dynamic phy setup code Jens Osterkamp @ 2007-01-26 17:58 ` Linas Vepstas [not found] ` <200701262150.52882.jens@de.ibm.com> 2007-01-26 20:21 ` Benjamin Herrenschmidt 2007-02-01 8:05 ` [Cbe-oss-dev] " Ishizaki Kou 2 siblings, 1 reply; 16+ messages in thread From: Linas Vepstas @ 2007-01-26 17:58 UTC (permalink / raw) To: Jens Osterkamp; +Cc: netdev, cbe-oss-dev, linuxppc-dev, jgarzik, James K Lewis On Fri, Jan 26, 2007 at 02:09:29PM +0100, Jens Osterkamp wrote: > This patch modifies the patch submitted by Kou Ishizaki to make it work on the > blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). > > Index: linux-2.6/drivers/net/spider_net.c > + if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) { > + > + pr_info("%s: link is down, trying to bring it up\n", card->netdev->name); > + > + switch(phy->medium) { > + case GMII_COPPER: > + /* enable fiber with autonegotiation first */ > + if (phy->def->ops->enable_fiber) > + phy->def->ops->enable_fiber(phy, 1); > + phy->medium = GMII_FIBER; > + break; Can you fix this to use tabs for indentation, instead of spaces? Please note, if you do not like tabs of 8 spaces, you can always change this in your editor, e.g "set ts=3" for making a tab be 3 spaces in vi. You would put this in your .exrc or .vimrc file. Patches submitted to the kernel should use tabs, uniformly. --linas ^ permalink raw reply [flat|nested] 16+ messages in thread
[parent not found: <200701262150.52882.jens@de.ibm.com>]
* Re: spidernet: dynamic phy setup code [not found] ` <200701262150.52882.jens@de.ibm.com> @ 2007-01-26 22:15 ` Linas Vepstas 2007-01-26 22:30 ` Jens Osterkamp 0 siblings, 1 reply; 16+ messages in thread From: Linas Vepstas @ 2007-01-26 22:15 UTC (permalink / raw) To: Jens Osterkamp; +Cc: linuxppc-dev On Fri, Jan 26, 2007 at 09:50:52PM +0100, Jens Osterkamp wrote: > Seems like my kmail has eaten the tabs...i am attaching it as a file, Ahhh > does it look ok for you now ? Yes. FWIW, Acked-by: Linas Vepstas <linas@austin.ibm.com> --linas ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-01-26 22:15 ` Linas Vepstas @ 2007-01-26 22:30 ` Jens Osterkamp 0 siblings, 0 replies; 16+ messages in thread From: Jens Osterkamp @ 2007-01-26 22:30 UTC (permalink / raw) To: Linas Vepstas; +Cc: linuxppc-dev [-- Attachment #1: Type: text/plain, Size: 362 bytes --] On Friday 26 January 2007 23:15, Linas Vepstas wrote: > On Fri, Jan 26, 2007 at 09:50:52PM +0100, Jens Osterkamp wrote: > > Seems like my kmail has eaten the tabs...i am attaching it as a file, > > Ahhh > > > does it look ok for you now ? > > Yes. > > FWIW, > > Acked-by: Linas Vepstas <linas@austin.ibm.com> > > --linas Sending it again as attached file Jens [-- Attachment #2: spidernet-on-celleb-update-2.diff --] [-- Type: text/x-diff, Size: 5903 bytes --] Subject: spidernet: dynamic phy setup code This patch modifies the patch submitted by Kou Ishizaki to make it work on the blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). Unfortunately I dont have access to a Celleb so I cannot test it there. The basic logic behind this is simple : when the interface first comes up it tries to detect the phy. When the phy is detected, it is initially set up to use copper. A timer is set to check the link status in spidernet_link_phy using poll_link. If link check fails more than SPIDER_NET_ANEG_TIMEOUT times, it switches to fiber link with autonegotiation. If that fails more than SPIDER_NET_ANEG_TIMEOUT times, it switches to fiber link with no autonegotiation. If that also fails, it goes back to copper, and so forth. If the link comes up, it prints the link abilites and we are done. The name of the phy found attached to the spider chip is reported to the user. Hardcoded values for the timeout are moved to #defines. I put in a few comments to make the code more readable. Signed-off-by: Jens Osterkamp <jens@de.ibm.com> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Index: linux-2.6/drivers/net/spider_net.c =================================================================== --- linux-2.6.orig/drivers/net/spider_net.c +++ linux-2.6/drivers/net/spider_net.c @@ -1280,19 +1280,23 @@ spider_net_set_mac(struct net_device *ne * spider_net_link_reset * @netdev: net device structure * + * This is called when the PHY_LINK signal is asserted. For the blade this is + * not connected so we should never get here. + * */ static void spider_net_link_reset(struct net_device *netdev) { - struct spider_net_card *card=netdev_priv(netdev); del_timer_sync(&card->aneg_timer); + /* clear interrupt, block further interrupts */ spider_net_write_reg(card, SPIDER_NET_GMACST, spider_net_read_reg(card, SPIDER_NET_GMACST)); spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); + /* reset phy and setup aneg */ mii_phy_probe(&card->phy, card->phy.mii_id); spider_net_setup_aneg(card, is1000); if (card->phy.def->phy_id) @@ -1616,6 +1620,7 @@ spider_net_init_card(struct spider_net_c spider_net_write_reg(card, SPIDER_NET_CKRCTRL, SPIDER_NET_CKRCTRL_RUN_VALUE); + /* trigger ETOMOD signal */ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); @@ -1739,6 +1744,8 @@ spider_net_open(struct net_device *netde if (spider_net_init_firmware(card)) goto init_firmware_failed; + /* start probing with copper */ + card->phy.medium = GMII_COPPER; spider_net_setup_aneg(card, is1000); if (card->phy.def->phy_id) mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); @@ -1805,43 +1812,54 @@ static void spider_net_link_phy(unsigned struct spider_net_card *card = (struct spider_net_card *)data; struct mii_phy *phy = &card->phy; - if (card->aneg_count > 10) { - /* timeout */ - card->aneg_count = 0; - is1000 = !is1000; - goto re_setup; + /* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */ + if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) { + + pr_info("%s: link is down, trying to bring it up\n", card->netdev->name); + + switch(phy->medium) { + case GMII_COPPER: + /* enable fiber with autonegotiation first */ + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 1); + phy->medium = GMII_FIBER; + break; + + case GMII_FIBER: + /* fiber didn't come up, try to disable fiber autoneg */ + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 0); + phy->medium = GMII_UNKNOWN; + break; + + case GMII_UNKNOWN: + /* copper, fiber with and without autoneg failed, + * retry from beginning */ + spider_net_setup_aneg(card, is1000); + phy->medium = GMII_COPPER; + break; + } + + card->aneg_count = 0; + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + return; } + /* link still not up, try again later */ if (!(phy->def->ops->poll_link(phy))) { card->aneg_count++; mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); return; } + /* link came up, get abilities */ phy->def->ops->read_link(phy); - if (phy->speed == 1000 && !is1000) { - is1000 = 1; - goto re_setup; - } else if(phy->speed != 1000 && is1000) { - is1000 = 0; - goto re_setup; - } - - spider_net_write_reg(card, SPIDER_NET_GMACST, - spider_net_read_reg(card, SPIDER_NET_GMACST)); - spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); - - pr_info("Found %s with %i Mbps, %s-duplex.\n", - phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); + pr_info("%s: link is up with %i Mbps, %s-duplex, %sautoneg.\n", + card->netdev->name, phy->speed, phy->duplex==1 ? "Full" : "Half", + phy->autoneg==1 ? "" : "no "); return; - -re_setup: - mii_phy_probe(phy, phy->mii_id); - spider_net_setup_aneg(card, is1000); - card->aneg_count = 0; - mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); } /** @@ -1871,8 +1889,10 @@ spider_net_setup_phy(struct spider_net_c unsigned short id; id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); if (id != 0x0000 && id != 0xffff) { - mii_phy_probe(phy, phy->mii_id); + if (!mii_phy_probe(phy, phy->mii_id)) { + pr_info("Found %s.\n", phy->def->name); break; + } } } Index: linux-2.6/drivers/net/spider_net.h =================================================================== --- linux-2.6.orig/drivers/net/spider_net.h +++ linux-2.6/drivers/net/spider_net.h @@ -51,7 +51,8 @@ extern char spider_net_driver_name[]; #define SPIDER_NET_TX_DESCRIPTORS_MAX 512 #define SPIDER_NET_TX_TIMER (HZ/5) -#define SPIDER_NET_ANEG_TIMER (HZ*2) +#define SPIDER_NET_ANEG_TIMER (HZ) +#define SPIDER_NET_ANEG_TIMEOUT 2 #define SPIDER_NET_RX_CSUM_DEFAULT 1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-01-26 13:09 spidernet: dynamic phy setup code Jens Osterkamp 2007-01-26 17:58 ` Linas Vepstas @ 2007-01-26 20:21 ` Benjamin Herrenschmidt 2007-02-01 10:50 ` Jens Osterkamp 2007-02-01 8:05 ` [Cbe-oss-dev] " Ishizaki Kou 2 siblings, 1 reply; 16+ messages in thread From: Benjamin Herrenschmidt @ 2007-01-26 20:21 UTC (permalink / raw) To: Jens Osterkamp; +Cc: netdev, James K Lewis, linuxppc-dev, jgarzik, cbe-oss-dev On Fri, 2007-01-26 at 14:09 +0100, Jens Osterkamp wrote: > This patch modifies the patch submitted by Kou Ishizaki to make it work on the > blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). > Unfortunately I dont have access to a Celleb so I cannot test it there. > > The basic logic behind this is simple : when the interface first comes up > it tries to detect the phy. When the phy is detected, it is initially set up > to use copper. A timer is set to check the link status in spidernet_link_phy > using poll_link. If link check fails more than SPIDER_NET_ANEG_TIMEOUT > times, it switches to fiber link with autonegotiation. If that fails more > than SPIDER_NET_ANEG_TIMEOUT times, it switches to fiber link with no > autonegotiation. If that also fails, it goes back to copper, and so forth. > If the link comes up, it prints the link abilites and we are done. > > The name of the phy found attached to the spider chip is reported to the > user. Hardcoded values for the timeout are moved to #defines. I put in a > few comments to make the code more readable. Can't we have a device-tree property indicating wether to use fiber or copper ? Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-01-26 20:21 ` Benjamin Herrenschmidt @ 2007-02-01 10:50 ` Jens Osterkamp 0 siblings, 0 replies; 16+ messages in thread From: Jens Osterkamp @ 2007-02-01 10:50 UTC (permalink / raw) To: Benjamin Herrenschmidt Cc: netdev, James K Lewis, linuxppc-dev, jgarzik, cbe-oss-dev On Friday 26 January 2007 9:21 pm, Benjamin Herrenschmidt wrote: > Can't we have a device-tree property indicating wether to use fiber or > copper ? Well, yes, I am sure we could, but what would be the benefit of doing so if we can get the same information dynamically ? Jens ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Cbe-oss-dev] spidernet: dynamic phy setup code 2007-01-26 13:09 spidernet: dynamic phy setup code Jens Osterkamp 2007-01-26 17:58 ` Linas Vepstas 2007-01-26 20:21 ` Benjamin Herrenschmidt @ 2007-02-01 8:05 ` Ishizaki Kou 2007-02-01 11:04 ` Jens Osterkamp 2 siblings, 1 reply; 16+ messages in thread From: Ishizaki Kou @ 2007-02-01 8:05 UTC (permalink / raw) To: jens; +Cc: jim, linuxppc-dev, jgarzik, netdev I apologize if you received this mail many times. Jens-san > This patch modifies the patch submitted by Kou Ishizaki to make it work on the > blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). > Unfortunately I dont have access to a Celleb so I cannot test it there. Thanks for arranging our patch to work on Cell Blade. This patch partially works on celleb but remains following several problems. 1. It doesn't recover once an ethernet cable which is connected to a spider_net card is unpluged. 2. It doesn't work when the spider_net card is connected to a 100Mbps ethernet switch. To solve these problems, we need to restore some codes you removed from your patch. (1) >- if (card->aneg_count > 10) { >- /* timeout */ >- card->aneg_count = 0; >- is1000 = !is1000; >- goto re_setup; >- if (phy->speed == 1000 && !is1000) { >- is1000 = 1; >- goto re_setup; >- } else if(phy->speed != 1000 && is1000) { >- is1000 = 0; >- goto re_setup; >- } We need to use different auto-neg initial settings between for 10/100Mbps ethernet switches and for Gbps ethernet switches. Driver don't know which type of network switch is connected to network card, so we try both settings alternately in auto negtiation sequences by using a variable "is1000". Furthermore, we have a problem that poll_link() may succeed even when the auto-neg initial setting is for different network switch type, and the network card does not work on this case. We retry auto-neg with the another initial setting on this case. #We are commented that "is1000" should be in spider_net_card. #We fixed it in another patch. Please refer the following. #http://ozlabs.org/pipermail/linuxppc-dev/2007-January/030203.html But we don't think this is the best solution, and we are still developing our spidernet driver. If you have a good alternative idea, please tell us. (2) >- spider_net_write_reg(card, SPIDER_NET_GMACST, >- spider_net_read_reg(card, SPIDER_NET_GMACST)); >- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); These codes are enabling LINK status interrupt which is disabled at the beginning of auto-neg. Without this operation, auto negotiation works only when a connection detected for the first time, and auto negotiation will not work when an ethernet cable is unpluged or pluged. (3) >- mii_phy_probe(phy, phy->mii_id); It seems that PHY reset is necessary before auto negotiation, after a link once went down. We can't call directly reset routine from driver, so we call mii_phy_probe(). We are still developping the patch as we noted, and we are considering to call mii_phy_probe() from spider_net_setup_aneg(), or to call reset_one_mii_phy() from bcm54xx_setup_aneg(). We think these (1)-(3) are necessary, but we are afraid that you removed them by a reason that they causes some trouble in Cell Blade. If so please tell us. Best regards, Kou Ishizaki ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Cbe-oss-dev] spidernet: dynamic phy setup code 2007-02-01 8:05 ` [Cbe-oss-dev] " Ishizaki Kou @ 2007-02-01 11:04 ` Jens Osterkamp 2007-02-02 10:20 ` Ishizaki Kou ` (5 more replies) 0 siblings, 6 replies; 16+ messages in thread From: Jens Osterkamp @ 2007-02-01 11:04 UTC (permalink / raw) To: Ishizaki Kou; +Cc: jim, linuxppc-dev, jgarzik, netdev Ishizaki-san, > This patch partially works on celleb but remains > following several problems. > 1. It doesn't recover once an ethernet cable which is > connected to a spider_net card is unpluged. My understanding is that you are using the LINK interrupt to detect this. For the blade this is not connected but reenabling it wont hurt, I hope. > 2. It doesn't work when the spider_net card is connected to > a 100Mbps ethernet switch. > > To solve these problems, we need to restore some codes > you removed from your patch. > > (1) > >- if (card->aneg_count > 10) { > >- /* timeout */ > >- card->aneg_count = 0; > >- is1000 = !is1000; > >- goto re_setup; > > >- if (phy->speed == 1000 && !is1000) { > >- is1000 = 1; > >- goto re_setup; > >- } else if(phy->speed != 1000 && is1000) { > >- is1000 = 0; > >- goto re_setup; > >- } > > We need to use different auto-neg initial settings between > for 10/100Mbps ethernet switches and for Gbps ethernet switches. > Driver don't know which type of network switch is connected to > network card, so we try both settings alternately in auto negtiation > sequences by using a variable "is1000". I still dont see why you need different settings for different speed switches. This is getting to a point where access to some hardware would be handy. What exact phy are using anyway ? > Furthermore, we have a problem that poll_link() may succeed even when > the auto-neg initial setting is for different network switch type, > and the network card does not work on this case. We retry auto-neg > with the another initial setting on this case. See above, could you give some more details why this is the case. Or maybe Ben knows more about this ? > #We are commented that "is1000" should be in spider_net_card. > #We fixed it in another patch. Please refer the following. > #http://ozlabs.org/pipermail/linuxppc-dev/2007-January/030203.html > > But we don't think this is the best solution, and we are still > developing > our spidernet driver. If you have a good alternative idea, please tell > us. > > (2) > >- spider_net_write_reg(card, SPIDER_NET_GMACST, > >- spider_net_read_reg(card, SPIDER_NET_GMACST)); > >- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); > > These codes are enabling LINK status interrupt which is disabled > at the beginning of auto-neg. > Without this operation, auto negotiation works only when a connection > detected for the first time, and auto negotiation will not work > when an ethernet cable is unpluged or pluged. I will reenable it and see wether it affects us. The pin is not connected so we should never enter this part of the code. > (3) > >- mii_phy_probe(phy, phy->mii_id); > It seems that PHY reset is necessary before auto negotiation, > after a link once went down. > We can't call directly reset routine from driver, so we call > mii_phy_probe(). > We are still developping the patch as we noted, and we are considering > to call mii_phy_probe() from spider_net_setup_aneg(), or to call > reset_one_mii_phy() from bcm54xx_setup_aneg(). IMHO using mii_phy_probe is the right way to do this. > We think these (1)-(3) are necessary, but we are afraid that you removed > them > by a reason that they causes some trouble in Cell Blade. If so please > tell us. I'll do some investigations and let you know of the results. Jens ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-02-01 11:04 ` Jens Osterkamp @ 2007-02-02 10:20 ` Ishizaki Kou 2007-02-05 0:08 ` Benjamin Herrenschmidt 2007-02-02 10:29 ` [RFC/PATCH 2.6.20-rc6 1/4] spidernet: autoneg support for Celleb Ishizaki Kou ` (4 subsequent siblings) 5 siblings, 1 reply; 16+ messages in thread From: Ishizaki Kou @ 2007-02-02 10:20 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, jgarzik, jim, netdev Jens-san, Thanks for your comments. >Ishizaki-san, > >> This patch partially works on celleb but remains >> following several problems. >> 1. It doesn't recover once an ethernet cable which is >> connected to a spider_net card is unpluged. > >My understanding is that you are using the LINK interrupt to detect this. Yes. We use the LINK interrupt for this purpose. >For the blade this is not connected but reenabling it wont hurt, I hope. > >> 2. It doesn't work when the spider_net card is connected to >> a 100Mbps ethernet switch. >> >> To solve these problems, we need to restore some codes >> you removed from your patch. >> >> (1) >> >- if (card->aneg_count > 10) { >> >- /* timeout */ >> >- card->aneg_count = 0; >> >- is1000 = !is1000; >> >- goto re_setup; >> >> >- if (phy->speed == 1000 && !is1000) { >> >- is1000 = 1; >> >- goto re_setup; >> >- } else if(phy->speed != 1000 && is1000) { >> >- is1000 = 0; >> >- goto re_setup; >> >- } >> >> We need to use different auto-neg initial settings between >> for 10/100Mbps ethernet switches and for Gbps ethernet switches. >> Driver don't know which type of network switch is connected to >> network card, so we try both settings alternately in auto negtiation >> sequences by using a variable "is1000". > >I still dont see why you need different settings for different speed switches. >This is getting to a point where access to some hardware would be handy. >What exact phy are using anyway ? We use bcm5461. There is a possibility that we don't know the appropriate setting which is applicable for both type of switches. >> Furthermore, we have a problem that poll_link() may succeed even when >> the auto-neg initial setting is for different network switch type, >> and the network card does not work on this case. We retry auto-neg >> with the another initial setting on this case. > >See above, could you give some more details why this is the case. Or maybe Ben >knows more about this ? We didn't investigate for the detail, but we met the following phenomena. 1. When auto-neg starts with Gbps setting and ethernet card is connected to a 100Mbps switch, LINK is not detected. 2. When auto-neg starts with 100/10Mbps setting and ethernet card is connected to Gbps switch, LINK is detected (poll_link() succeeds), but the network is not available. >> #We are commented that "is1000" should be in spider_net_card. >> #We fixed it in another patch. Please refer the following. >> #http://ozlabs.org/pipermail/linuxppc-dev/2007-January/030203.html >> >> But we don't think this is the best solution, and we are still >> developing >> our spidernet driver. If you have a good alternative idea, please tell >> us. >> >> (2) >> >- spider_net_write_reg(card, SPIDER_NET_GMACST, >> >- spider_net_read_reg(card, SPIDER_NET_GMACST)); >> >- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); >> >> These codes are enabling LINK status interrupt which is disabled >> at the beginning of auto-neg. >> Without this operation, auto negotiation works only when a connection >> detected for the first time, and auto negotiation will not work >> when an ethernet cable is unpluged or pluged. > >I will reenable it and see wether it affects us. The pin is not connected so >we should never enter this part of the code. > >> (3) >> >- mii_phy_probe(phy, phy->mii_id); >> It seems that PHY reset is necessary before auto negotiation, >> after a link once went down. >> We can't call directly reset routine from driver, so we call >> mii_phy_probe(). >> We are still developping the patch as we noted, and we are considering >> to call mii_phy_probe() from spider_net_setup_aneg(), or to call >> reset_one_mii_phy() from bcm54xx_setup_aneg(). > >IMHO using mii_phy_probe is the right way to do this. OK. We will do so. >> We think these (1)-(3) are necessary, but we are afraid that you removed >> them >> by a reason that they causes some trouble in Cell Blade. If so please >> tell us. > >I'll do some investigations and let you know of the results. Thanks for your cooperation to us. By the way, we have a suggestion. Would you please make your spidernet patch based main-line code(not based on our patch)? Our patch are still changing, so we think it's more convenient for you and us to maintain the code. We will not mind whether it includes our code or not. We will post our recent spidernet patch set based on 2.6.20-rc6. This patch set is merged Jens-san's spidernet patch and works on celleb. We hope this patch set will work on Cell blade. We intend this patch set is just for a test so far(not intended to be taken for main-line immediately). Please try this, if you can. Best regards, Kou Ishizaki ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-02-02 10:20 ` Ishizaki Kou @ 2007-02-05 0:08 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 16+ messages in thread From: Benjamin Herrenschmidt @ 2007-02-05 0:08 UTC (permalink / raw) To: Ishizaki Kou; +Cc: netdev, jgarzik, jim, linuxppc-dev > We use bcm5461. There is a possibility that we don't know the appropriate > setting which is applicable for both type of switches. Have you tested the existing 54xx code in sungem_phy.c ? We use that with 5462 at least in K2 and all sorts of 54xx chips and it works fine... Just setup the right advertisement bits and call setup_aneg in the PHY ops. You don't even need to implement the "forced" fallback code that is in sungem. It's not necessary with most broadcom PHYs as they do that themselves, just setup aneg and poll the link from a timer, that's it. Once you get a link, then setup your GMACMODE based on the link speed. I don't have the datasheet of the 5461 at hand but I doubt it's any different... Like other Broadcom 54xx PHYs, it might need some special initialization code to work around firmware bugs though... > We didn't investigate for the detail, but we met the following phenomena. > 1. When auto-neg starts with Gbps setting and ethernet card is connected to > a 100Mbps switch, LINK is not detected. > 2. When auto-neg starts with 100/10Mbps setting and ethernet card is > connected to Gbps switch, LINK is detected (poll_link() succeeds), but > the network is not available. That is very strange... I would need to review your code in more details or eventually have HW access to run my own experiments, but none of this should happen if things are setup properly. Also avoid relying on the link interrupt, it's a known cause of trouble. Just poll. Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC/PATCH 2.6.20-rc6 1/4] spidernet: autoneg support for Celleb 2007-02-01 11:04 ` Jens Osterkamp 2007-02-02 10:20 ` Ishizaki Kou @ 2007-02-02 10:29 ` Ishizaki Kou 2007-02-02 10:30 ` [RFC/PATCH 2.6.20-rc6 2/4] spidernet: load firmaware when open Ishizaki Kou ` (3 subsequent siblings) 5 siblings, 0 replies; 16+ messages in thread From: Ishizaki Kou @ 2007-02-02 10:29 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, jgarzik, jim, netdev Add auto negotiation support for Celleb. This patch is just for a test. Please try this, if you can. Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp> --- --- org-linux-powerpc-git/drivers/net/spider_net.h 2007-02-02 14:24:26.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.h 2007-02-02 14:24:45.000000000 +0900 @@ -50,6 +50,8 @@ #define SPIDER_NET_TX_DESCRIPTORS_MAX 512 #define SPIDER_NET_TX_TIMER (HZ/5) +#define SPIDER_NET_ANEG_TIMER (HZ) +#define SPIDER_NET_ANEG_TIMEOUT 2 #define SPIDER_NET_RX_CSUM_DEFAULT 1 @@ -104,6 +106,7 @@ #define SPIDER_NET_GMACOPEMD 0x00000100 #define SPIDER_NET_GMACLENLMT 0x00000108 +#define SPIDER_NET_GMACST 0x00000110 #define SPIDER_NET_GMACINTEN 0x00000118 #define SPIDER_NET_GMACPHYCTRL 0x00000120 @@ -333,9 +336,12 @@ /* We rely on flagged descriptor interrupts */ #define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) ) +#define SPIDER_NET_LINKINT ( 1 << SPIDER_NET_GMAC2INT ) + #define SPIDER_NET_ERRINT ( 0xffffffff & \ (~SPIDER_NET_TXINT) & \ - (~SPIDER_NET_RXINT) ) + (~SPIDER_NET_RXINT) & \ + (~SPIDER_NET_LINKINT) ) #define SPIDER_NET_GPREXEC 0x80000000 #define SPIDER_NET_GPRDAT_MASK 0x0000ffff @@ -447,6 +453,10 @@ spinlock_t intmask_lock; struct tasklet_struct rxram_full_tl; + + int aneg_count; + int is1000; + struct timer_list aneg_timer; struct timer_list tx_timer; struct work_struct tx_timeout_task; --- org-linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:24:22.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:26:17.000000000 +0900 @@ -165,6 +165,57 @@ return readvalue; } +/** spider_net_setup_aneg - initial auto-negotiation setup + * @card: device structure + **/ +static void +spider_net_setup_aneg(struct spider_net_card *card) +{ + struct mii_phy *phy = &card->phy; + u32 advertise = 0; + u16 bmcr, bmsr, ctrl1000, stat1000, estat; + + bmcr = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMCR); + bmsr = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); + ctrl1000 = spider_net_read_phy(card->netdev, phy->mii_id, MII_CTRL1000); + stat1000 = spider_net_read_phy(card->netdev, phy->mii_id, MII_STAT1000); + estat = spider_net_read_phy(card->netdev, phy->mii_id, MII_ESTATUS); + + if (bmsr & BMSR_10HALF) + advertise |= ADVERTISE_10HALF; + if (bmsr & BMSR_10FULL) + advertise |= ADVERTISE_10FULL; + if (bmsr & BMSR_100HALF) + advertise |= ADVERTISE_100HALF; + if (bmsr & BMSR_100FULL) + advertise |= ADVERTISE_100FULL; + if (bmsr & BMSR_100BASE4) + advertise |= ADVERTISE_100BASE4; + + mii_phy_probe(phy, phy->mii_id); + + if (card->is1000) { + if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_TFULL)) { + advertise |= ADVERTISE_1000XFULL; + ctrl1000 |= ADVERTISE_1000FULL; + } + if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF)) { + advertise |= ADVERTISE_1000XHALF; + ctrl1000 |= ADVERTISE_1000HALF; + } + + spider_net_write_phy(card->netdev, phy->mii_id, + MII_CTRL1000, ctrl1000); + + + phy->def->ops->setup_aneg(phy, advertise); + } else { + bmcr |= (BMCR_ANRESTART | BMCR_ANENABLE); + spider_net_write_phy(card->netdev, phy->mii_id, + MII_BMCR, bmcr); + } +} + /** * spider_net_rx_irq_off - switch off rx irq on this spider card * @card: device structure @@ -1245,6 +1296,33 @@ } /** + * spider_net_link_reset + * @netdev: net device structure + * + * This is called when the PHY_LINK signal is asserted. For the blade this is + * not connected so we should never get here. + * + */ +static void +spider_net_link_reset(struct net_device *netdev) +{ + + struct spider_net_card *card = netdev_priv(netdev); + + del_timer_sync(&card->aneg_timer); + + /* clear interrupt, block further interrupts */ + spider_net_write_reg(card, SPIDER_NET_GMACST, + spider_net_read_reg(card, SPIDER_NET_GMACST)); + spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); + + /* reset phy and setup aneg */ + spider_net_setup_aneg(card); + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + +} + +/** * spider_net_handle_error_irq - handles errors raised by an interrupt * @card: card structure * @status_reg: interrupt status register 0 (GHIINT0STS) @@ -1497,6 +1575,9 @@ if (status_reg & SPIDER_NET_TXINT) netif_rx_schedule(netdev); + if (status_reg & SPIDER_NET_LINKINT) + spider_net_link_reset(netdev); + if (status_reg & SPIDER_NET_ERRINT ) spider_net_handle_error_irq(card, status_reg); @@ -1621,8 +1702,6 @@ spider_net_write_reg(card, SPIDER_NET_GMACLENLMT, SPIDER_NET_LENLMT_VALUE); - spider_net_write_reg(card, SPIDER_NET_GMACMODE, - SPIDER_NET_MACMODE_VALUE); spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, SPIDER_NET_OPMODE_VALUE); @@ -1655,6 +1734,12 @@ int i, result; result = -ENOMEM; + + /* start probing with copper */ + spider_net_setup_aneg(card); + if (card->phy.def->phy_id) + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + if (spider_net_init_chain(card, &card->tx_chain, card->descr, card->num_tx_desc)) goto alloc_tx_failed; @@ -1699,17 +1784,112 @@ alloc_rx_failed: spider_net_free_chain(card, &card->tx_chain); alloc_tx_failed: + del_timer_sync(&card->aneg_timer); return result; } /** + * spider_net_link_phy + * @data: used for pointer to card structure + * + */ +static void spider_net_link_phy(unsigned long data) +{ + struct spider_net_card *card = (struct spider_net_card *)data; + struct mii_phy *phy = &card->phy; + + /* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */ + if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) { + + pr_info("%s: link is down trying to bring it up\n", card->netdev->name); + + switch (phy->medium) { + case GMII_COPPER: + if (card->is1000) { + /* try autoneg with the setting not for Gbps */ + card->is1000 = 0; + spider_net_setup_aneg(card); + break; + } else { + /* enable fiber with autonegotiation first */ + card->is1000 = 1; + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 1); + phy->medium = GMII_FIBER; + break; + } + + case GMII_FIBER: + /* fiber didn't come up, try to disable fiber autoneg */ + if (phy->def->ops->enable_fiber) + phy->def->ops->enable_fiber(phy, 0); + phy->medium = GMII_UNKNOWN; + break; + + case GMII_UNKNOWN: + /* copper, fiber with and without failed, + * retry from beginning */ + card->is1000 = 1; + spider_net_setup_aneg(card); + phy->medium = GMII_COPPER; + break; + } + + card->aneg_count = 0; + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + return; + } + + /* link still not up, try again later */ + if (!(phy->def->ops->poll_link(phy))) { + card->aneg_count++; + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); + return; + } + + /* link came up, get abilities */ + phy->def->ops->read_link(phy); + + /* link is detected but we need retrying autoneg + * when initial setting was wrong */ + if (phy->speed == 1000 && !(card->is1000)) { + card->is1000 = 1; + goto re_setup; + } else if (phy->speed != 1000 && card->is1000) { + card->is1000 = 0; + goto re_setup; + } + + spider_net_write_reg(card, SPIDER_NET_GMACST, + spider_net_read_reg(card, SPIDER_NET_GMACST)); + spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); + + if (phy->speed == 1000) + spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0x00000001); + else + spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0); + + card->aneg_count = 0; + + pr_info("Found %s with %i Mbps, %s-duplex %sautoneg.\n", + phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half", + phy->autoneg==1 ? "" : "no "); + + return; + +re_setup: + spider_net_setup_aneg(card); + card->aneg_count = 0; + mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER); +} + +/** * spider_net_setup_phy - setup PHY * @card: card structure * * returns 0 on success, <0 on failure * - * spider_net_setup_phy is used as part of spider_net_probe. Sets - * the PHY to 1000 Mbps + * spider_net_setup_phy is used as part of spider_net_probe. **/ static int spider_net_setup_phy(struct spider_net_card *card) @@ -1720,21 +1900,21 @@ SPIDER_NET_DMASEL_VALUE); spider_net_write_reg(card, SPIDER_NET_GPCCTRL, SPIDER_NET_PHY_CTRL_VALUE); - phy->mii_id = 1; + phy->dev = card->netdev; phy->mdio_read = spider_net_read_phy; phy->mdio_write = spider_net_write_phy; - mii_phy_probe(phy, phy->mii_id); - - if (phy->def->ops->setup_forced) - phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL); - - phy->def->ops->enable_fiber(phy); - - phy->def->ops->read_link(phy); - pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, - phy->speed, phy->duplex==1 ? "Full" : "Half"); + for (phy->mii_id = 1; phy->mii_id <= 31; phy->mii_id++) { + unsigned short id; + id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR); + if (id != 0x0000 && id != 0xffff) { + if (!mii_phy_probe(phy, phy->mii_id)) { + pr_info("Found %s.\n", phy->def->name); + break; + } + } + } return 0; } @@ -1907,11 +2087,13 @@ netif_carrier_off(netdev); netif_stop_queue(netdev); del_timer_sync(&card->tx_timer); + del_timer_sync(&card->aneg_timer); /* disable/mask all interrupts */ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); /* free_irq(netdev->irq, netdev);*/ free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev); @@ -2053,6 +2235,12 @@ card->tx_timer.data = (unsigned long) card; netdev->irq = card->pdev->irq; + card->is1000 = 1; + card->aneg_count = 0; + init_timer(&card->aneg_timer); + card->aneg_timer.function = spider_net_link_phy; + card->aneg_timer.data = (unsigned long) card; + card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; card->num_tx_desc = tx_descriptors; ^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC/PATCH 2.6.20-rc6 2/4] spidernet: load firmaware when open 2007-02-01 11:04 ` Jens Osterkamp 2007-02-02 10:20 ` Ishizaki Kou 2007-02-02 10:29 ` [RFC/PATCH 2.6.20-rc6 1/4] spidernet: autoneg support for Celleb Ishizaki Kou @ 2007-02-02 10:30 ` Ishizaki Kou 2007-02-02 10:31 ` [RFC/PATCH 2.6.20-rc6 3/4] spidernet: add support for Celleb Ishizaki Kou ` (2 subsequent siblings) 5 siblings, 0 replies; 16+ messages in thread From: Ishizaki Kou @ 2007-02-02 10:30 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, jgarzik, jim, netdev This patch moves calling init_firmware() from spider_net_probe() to spider_net_open() so as to use the driver by built-in. This patch is just for a test. Please try this, if you can. Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp> --- --- org-linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:29:17.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:29:39.000000000 +0900 @@ -1718,6 +1718,124 @@ } /** + * spider_net_download_firmware - loads firmware into the adapter + * @card: card structure + * @firmware_ptr: pointer to firmware data + * + * spider_net_download_firmware loads the firmware data into the + * adapter. It assumes the length etc. to be allright. + */ +static int +spider_net_download_firmware(struct spider_net_card *card, + const void *firmware_ptr) +{ + int sequencer, i; + const u32 *fw_ptr = firmware_ptr; + + /* stop sequencers */ + spider_net_write_reg(card, SPIDER_NET_GSINIT, + SPIDER_NET_STOP_SEQ_VALUE); + + for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS; + sequencer++) { + spider_net_write_reg(card, + SPIDER_NET_GSnPRGADR + sequencer * 8, 0); + for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) { + spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT + + sequencer * 8, *fw_ptr); + fw_ptr++; + } + } + + if (spider_net_read_reg(card, SPIDER_NET_GSINIT)) + return -EIO; + + spider_net_write_reg(card, SPIDER_NET_GSINIT, + SPIDER_NET_RUN_SEQ_VALUE); + + return 0; +} + +/** + * spider_net_init_firmware - reads in firmware parts + * @card: card structure + * + * Returns 0 on success, <0 on failure + * + * spider_net_init_firmware opens the sequencer firmware and does some basic + * checks. This function opens and releases the firmware structure. A call + * to download the firmware is performed before the release. + * + * Firmware format + * =============== + * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being + * the program for each sequencer. Use the command + * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \ + * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \ + * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin + * + * to generate spider_fw.bin, if you have sequencer programs with something + * like the following contents for each sequencer: + * <ONE LINE COMMENT> + * <FIRST 4-BYTES-WORD FOR SEQUENCER> + * <SECOND 4-BYTES-WORD FOR SEQUENCER> + * ... + * <1024th 4-BYTES-WORD FOR SEQUENCER> + */ +static int +spider_net_init_firmware(struct spider_net_card *card) +{ + struct firmware *firmware = NULL; + struct device_node *dn; + const u8 *fw_prop = NULL; + int err = -ENOENT; + int fw_size; + + if (request_firmware((const struct firmware **)&firmware, + SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { + if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && + netif_msg_probe(card) ) { + pr_err("Incorrect size of spidernet firmware in " \ + "filesystem. Looking in host firmware...\n"); + goto try_host_fw; + } + err = spider_net_download_firmware(card, firmware->data); + + release_firmware(firmware); + if (err) + goto try_host_fw; + + goto done; + } + +try_host_fw: + dn = pci_device_to_OF_node(card->pdev); + if (!dn) + goto out_err; + + fw_prop = get_property(dn, "firmware", &fw_size); + if (!fw_prop) + goto out_err; + + if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && + netif_msg_probe(card) ) { + pr_err("Incorrect size of spidernet firmware in " \ + "host firmware\n"); + goto done; + } + + err = spider_net_download_firmware(card, fw_prop); + +done: + return err; +out_err: + if (netif_msg_probe(card)) + pr_err("Couldn't find spidernet firmware in filesystem " \ + "or host firmware\n"); + return err; +} + +/** * spider_net_open - called upon ifonfig up * @netdev: interface device structure * @@ -1735,6 +1853,10 @@ result = -ENOMEM; + result = spider_net_init_firmware(card); + if (result) + goto init_firmware_failed; + /* start probing with copper */ spider_net_setup_aneg(card); if (card->phy.def->phy_id) @@ -1785,6 +1907,7 @@ spider_net_free_chain(card, &card->tx_chain); alloc_tx_failed: del_timer_sync(&card->aneg_timer); +init_firmware_failed: return result; } @@ -1920,124 +2043,6 @@ } /** - * spider_net_download_firmware - loads firmware into the adapter - * @card: card structure - * @firmware_ptr: pointer to firmware data - * - * spider_net_download_firmware loads the firmware data into the - * adapter. It assumes the length etc. to be allright. - */ -static int -spider_net_download_firmware(struct spider_net_card *card, - const void *firmware_ptr) -{ - int sequencer, i; - const u32 *fw_ptr = firmware_ptr; - - /* stop sequencers */ - spider_net_write_reg(card, SPIDER_NET_GSINIT, - SPIDER_NET_STOP_SEQ_VALUE); - - for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS; - sequencer++) { - spider_net_write_reg(card, - SPIDER_NET_GSnPRGADR + sequencer * 8, 0); - for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) { - spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT + - sequencer * 8, *fw_ptr); - fw_ptr++; - } - } - - if (spider_net_read_reg(card, SPIDER_NET_GSINIT)) - return -EIO; - - spider_net_write_reg(card, SPIDER_NET_GSINIT, - SPIDER_NET_RUN_SEQ_VALUE); - - return 0; -} - -/** - * spider_net_init_firmware - reads in firmware parts - * @card: card structure - * - * Returns 0 on success, <0 on failure - * - * spider_net_init_firmware opens the sequencer firmware and does some basic - * checks. This function opens and releases the firmware structure. A call - * to download the firmware is performed before the release. - * - * Firmware format - * =============== - * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being - * the program for each sequencer. Use the command - * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \ - * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \ - * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin - * - * to generate spider_fw.bin, if you have sequencer programs with something - * like the following contents for each sequencer: - * <ONE LINE COMMENT> - * <FIRST 4-BYTES-WORD FOR SEQUENCER> - * <SECOND 4-BYTES-WORD FOR SEQUENCER> - * ... - * <1024th 4-BYTES-WORD FOR SEQUENCER> - */ -static int -spider_net_init_firmware(struct spider_net_card *card) -{ - struct firmware *firmware = NULL; - struct device_node *dn; - const u8 *fw_prop = NULL; - int err = -ENOENT; - int fw_size; - - if (request_firmware((const struct firmware **)&firmware, - SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { - if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && - netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ - "filesystem. Looking in host firmware...\n"); - goto try_host_fw; - } - err = spider_net_download_firmware(card, firmware->data); - - release_firmware(firmware); - if (err) - goto try_host_fw; - - goto done; - } - -try_host_fw: - dn = pci_device_to_OF_node(card->pdev); - if (!dn) - goto out_err; - - fw_prop = get_property(dn, "firmware", &fw_size); - if (!fw_prop) - goto out_err; - - if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && - netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ - "host firmware\n"); - goto done; - } - - err = spider_net_download_firmware(card, fw_prop); - -done: - return err; -out_err: - if (netif_msg_probe(card)) - pr_err("Couldn't find spidernet firmware in filesystem " \ - "or host firmware\n"); - return err; -} - -/** * spider_net_workaround_rxramfull - work around firmware bug * @card: card structure * @@ -2138,8 +2143,6 @@ if (spider_net_setup_phy(card)) goto out; - if (spider_net_init_firmware(card)) - goto out; spider_net_open(netdev); spider_net_kick_tx_dma(card); @@ -2419,10 +2422,6 @@ if (err) goto out_undo_pci; - err = spider_net_init_firmware(card); - if (err) - goto out_undo_pci; - err = spider_net_setup_netdev(card); if (err) goto out_undo_pci; ^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC/PATCH 2.6.20-rc6 3/4] spidernet: add support for Celleb 2007-02-01 11:04 ` Jens Osterkamp ` (2 preceding siblings ...) 2007-02-02 10:30 ` [RFC/PATCH 2.6.20-rc6 2/4] spidernet: load firmaware when open Ishizaki Kou @ 2007-02-02 10:31 ` Ishizaki Kou 2007-02-02 10:33 ` [RFC/PATCH 2.6.20-rc6 4/4] spidernet: remove txram full logging Ishizaki Kou 2007-02-04 23:44 ` [Cbe-oss-dev] spidernet: dynamic phy setup code Benjamin Herrenschmidt 5 siblings, 0 replies; 16+ messages in thread From: Ishizaki Kou @ 2007-02-02 10:31 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, jgarzik, jim, netdev This patch adds or changes some HW specific settings for spider_net on Celleb. This patch is just for a test. Please try this, if you can. Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp> --- --- org-linux-powerpc-git/drivers/net/Kconfig 2007-02-02 14:34:19.000000000 +0900 +++ linux-powerpc-git/drivers/net/Kconfig 2007-02-02 14:32:18.000000000 +0900 @@ -2256,7 +2256,7 @@ config SPIDER_NET tristate "Spider Gigabit Ethernet driver" - depends on PCI && PPC_IBM_CELL_BLADE + depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) select FW_LOADER help This driver supports the Gigabit Ethernet chips present on the --- org-linux-powerpc-git/drivers/net/spider_net.h 2007-02-02 14:29:13.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.h 2007-02-02 14:32:18.000000000 +0900 @@ -1,7 +1,8 @@ /* - * Network device driver for Cell Processor-Based Blade + * Network device driver for Cell Processor-Based Blade and Celleb platform * * (C) Copyright IBM Corp. 2005 + * (C) Copyright 2006 TOSHIBA CORPORATION * * Authors : Utz Bacher <utz.bacher@de.ibm.com> * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> @@ -184,7 +185,8 @@ /* pause frames: automatic, no upper retransmission count */ /* outside loopback mode: ETOMOD signal dont matter, not connected */ -#define SPIDER_NET_OPMODE_VALUE 0x00000063 +/* ETOMOD signal is brought to PHY reset. bit 2 must be 1 in Celleb */ +#define SPIDER_NET_OPMODE_VALUE 0x00000067 /*#define SPIDER_NET_OPMODE_VALUE 0x001b0062*/ #define SPIDER_NET_LENLMT_VALUE 0x00000908 --- org-linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:31:39.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:32:18.000000000 +0900 @@ -1,7 +1,8 @@ /* - * Network device driver for Cell Processor-Based Blade + * Network device driver for Cell Processor-Based Blade and Celleb platform * * (C) Copyright IBM Corp. 2005 + * (C) Copyright 2006 TOSHIBA CORPORATION * * Authors : Utz Bacher <utz.bacher@de.ibm.com> * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> @@ -1618,6 +1619,11 @@ spider_net_write_reg(card, SPIDER_NET_CKRCTRL, SPIDER_NET_CKRCTRL_RUN_VALUE); + + /* trigger ETOMOD signal */ + spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, + spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); + } /** ^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC/PATCH 2.6.20-rc6 4/4] spidernet: remove txram full logging 2007-02-01 11:04 ` Jens Osterkamp ` (3 preceding siblings ...) 2007-02-02 10:31 ` [RFC/PATCH 2.6.20-rc6 3/4] spidernet: add support for Celleb Ishizaki Kou @ 2007-02-02 10:33 ` Ishizaki Kou 2007-02-04 23:44 ` [Cbe-oss-dev] spidernet: dynamic phy setup code Benjamin Herrenschmidt 5 siblings, 0 replies; 16+ messages in thread From: Ishizaki Kou @ 2007-02-02 10:33 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, jgarzik, jim, netdev This patches removes logging for SPIDER_NET_GTMFLLINT interrupts. Since the interrupts are not irregular, and they happen frequently when using 100Mbps network switches. This patch is just for a test. Please try this if you can. Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp> --- --- org-linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:35:14.000000000 +0900 +++ linux-powerpc-git/drivers/net/spider_net.c 2007-02-02 14:35:49.000000000 +0900 @@ -1435,8 +1435,8 @@ switch (i) { case SPIDER_NET_GTMFLLINT: - if (netif_msg_intr(card) && net_ratelimit()) - pr_err("Spider TX RAM full\n"); + /* TX RAM full may happen on a usual case. + * Logging is not needed. */ show_error = 0; break; case SPIDER_NET_GRFDFLLINT: /* fallthrough */ ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Cbe-oss-dev] spidernet: dynamic phy setup code 2007-02-01 11:04 ` Jens Osterkamp ` (4 preceding siblings ...) 2007-02-02 10:33 ` [RFC/PATCH 2.6.20-rc6 4/4] spidernet: remove txram full logging Ishizaki Kou @ 2007-02-04 23:44 ` Benjamin Herrenschmidt 5 siblings, 0 replies; 16+ messages in thread From: Benjamin Herrenschmidt @ 2007-02-04 23:44 UTC (permalink / raw) To: Jens Osterkamp; +Cc: linuxppc-dev, netdev, jgarzik, jim On Thu, 2007-02-01 at 12:04 +0100, Jens Osterkamp wrote: > Ishizaki-san, > > > This patch partially works on celleb but remains > > following several problems. > > 1. It doesn't recover once an ethernet cable which is > > connected to a spider_net card is unpluged. > > My understanding is that you are using the LINK interrupt to detect this. > For the blade this is not connected but reenabling it wont hurt, I hope. I would suggest just polling from a delayed work or a timer like sungem does. > I still dont see why you need different settings for different speed switches. > This is getting to a point where access to some hardware would be handy. > What exact phy are using anyway ? Yeah, same question... > > Furthermore, we have a problem that poll_link() may succeed even when > > the auto-neg initial setting is for different network switch type, > > and the network card does not work on this case. We retry auto-neg > > with the another initial setting on this case. > > See above, could you give some more details why this is the case. Or maybe Ben > knows more about this ? No, I'm surprised too. Ben. ^ permalink raw reply [flat|nested] 16+ messages in thread
* (no subject) @ 2007-02-01 7:54 kou.ishizaki 2007-02-06 10:42 ` spidernet: dynamic phy setup code Ishizaki Kou 0 siblings, 1 reply; 16+ messages in thread From: kou.ishizaki @ 2007-02-01 7:54 UTC (permalink / raw) To: jens; +Cc: linuxppc-dev, netdev jgarzik@pobox.com, jim@jklewis.com Subject: Re: [Cbe-oss-dev] spidernet: dynamic phy setup code In-Reply-To: <200701261409.29537.jens@de.ibm.com> From: Ishizaki Kou <kouish@swc.toshiba.co.jp> X-Mailer: Mew version 4.2 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Jens-san > This patch modifies the patch submitted by Kou Ishizaki to make it work on the > blade (http://marc.theaimsgroup.com/?l=linux-netdev&m=116593424505539&w=2). > Unfortunately I dont have access to a Celleb so I cannot test it there. Thanks for arranging our patch to work on Cell Blade. This patch partially works on celleb but remains following several problems. 1. It doesn't recover once an ethernet cable which is connected to a spider_net card is unpluged. 2. It doesn't work when the spider_net card is connected to a 100Mbps ethernet switch. To solve these problems, we need to restore some codes you removed from your patch. (1) >- if (card->aneg_count > 10) { >- /* timeout */ >- card->aneg_count = 0; >- is1000 = !is1000; >- goto re_setup; >- if (phy->speed == 1000 && !is1000) { >- is1000 = 1; >- goto re_setup; >- } else if(phy->speed != 1000 && is1000) { >- is1000 = 0; >- goto re_setup; >- } We need to use different auto-neg initial settings between for 10/100Mbps ethernet switches and for Gbps ethernet switches. Driver don't know which type of network switch is connected to network card, so we try both settings alternately in auto negtiation sequences by using a variable "is1000". Furthermore, we have a problem that poll_link() may succeed even when the auto-neg initial setting is for different network switch type, and the network card does not work on this case. We retry auto-neg with the another initial setting on this case. #We are commented that "is1000" should be in spider_net_card. #We fixed it in another patch. Please refer the following. #http://ozlabs.org/pipermail/linuxppc-dev/2007-January/030203.html But we don't think this is the best solution, and we are still developing our spidernet driver. If you have a good alternative idea, please tell us. (2) >- spider_net_write_reg(card, SPIDER_NET_GMACST, >- spider_net_read_reg(card, SPIDER_NET_GMACST)); >- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); These codes are enabling LINK status interrupt which is disabled at the beginning of auto-neg. Without this operation, auto negotiation works only when a connection detected for the first time, and auto negotiation will not work when an ethernet cable is unpluged or pluged. (3) >- mii_phy_probe(phy, phy->mii_id); It seems that PHY reset is necessary before auto negotiation, after a link once went down. We can't call directly reset routine from driver, so we call mii_phy_probe(). We are still developping the patch as we noted, and we are considering to call mii_phy_probe() from spider_net_setup_aneg(), or to call reset_one_mii_phy() from bcm54xx_setup_aneg(). We think these (1)-(3) are necessary, but we are afraid that you removed them by a reason that they causes some trouble in Cell Blade. If so please tell us. Best regards, Kou Ishizaki ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: spidernet: dynamic phy setup code 2007-02-01 7:54 kou.ishizaki @ 2007-02-06 10:42 ` Ishizaki Kou 0 siblings, 0 replies; 16+ messages in thread From: Ishizaki Kou @ 2007-02-06 10:42 UTC (permalink / raw) To: jens, benh; +Cc: linuxppc-dev, netdev Ben-san, Jens-san Thanks for your comments and advices. First, we should apologize to you that some troubles which we informed about spidernet auto-negotiation are caused by our mistake. We used wrong MACRO for "advertise" variable to phy->def->ops->setup_aneg(). We will post the revised patch for spider_net. Following are the current status of troubles we informed. (1) >- if (card->aneg_count > 10) { >- /* timeout */ >- card->aneg_count = 0; >- is1000 = !is1000; >- goto re_setup; >- if (phy->speed == 1000 && !is1000) { >- is1000 = 1; >- goto re_setup; >- } else if(phy->speed != 1000 && is1000) { >- is1000 = 0; >- goto re_setup; >- } > We need to use different auto-neg initial settings between > for 10/100Mbps ethernet switches and for Gbps ethernet switches. > Driver don't know which type of network switch is connected to > network card, so we try both settings alternately in auto negtiation > sequences by using a variable "is1000". > Furthermore, we have a problem that poll_link() may succeed even when > the auto-neg initial setting is for different network switch type, > and the network card does not work on this case. We retry auto-neg > with the another initial setting on this case. Solved. We are now able to use Gbps switches and 10/100Mbps switches with the same advertise setting and we don't need to use is1000. The re_setup is not necessary and they are removed in the revised patch. 2. >> - spider_net_write_reg(card, SPIDER_NET_GMACST, >> - spider_net_read_reg(card, SPIDER_NET_GMACST)); >> - spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4); > > These codes are enabling LINK status interrupt which is disabled > at the beginning of auto-neg. > Without this operation, auto negotiation works only when a connection > detected for the first time, and auto negotiation will not work > when an ethernet cable is unpluged or pluged. Pending(No problem, if they don't cause any trouble on Cell Blades). By the way, why do you suggest to use polling for auto-neg, Ben-san? Is there a merit to use polling, or is there a problem to use interrupt? Sorry, we couldn't find the reason why sungem use polling for auto-neg. They might not be necessary, if we use polling to handle LINK status as Ben-san said. 3 >> - mii_phy_probe(phy, phy->mii_id); > It seems that PHY reset is necessary before auto negotiation, > in the case that ethernet card is disconnected from an ethernet switch > then connected to another ethernet switch. > We can't call directly reset routine from driver, so we call mii_phy_probe(). Pending. After all, we need phy reset. > If you really need to reset it, then change sungem_phy.c to export the > reset function. But I'm surprised you need that. Another option is to > reset the PHY in your PHY's setup_aneg() function. We still wonder which is the best way, and mii_phy_probe() still remains so far. Best regards, Kou Ishizaki ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2007-02-06 10:43 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-01-26 13:09 spidernet: dynamic phy setup code Jens Osterkamp 2007-01-26 17:58 ` Linas Vepstas [not found] ` <200701262150.52882.jens@de.ibm.com> 2007-01-26 22:15 ` Linas Vepstas 2007-01-26 22:30 ` Jens Osterkamp 2007-01-26 20:21 ` Benjamin Herrenschmidt 2007-02-01 10:50 ` Jens Osterkamp 2007-02-01 8:05 ` [Cbe-oss-dev] " Ishizaki Kou 2007-02-01 11:04 ` Jens Osterkamp 2007-02-02 10:20 ` Ishizaki Kou 2007-02-05 0:08 ` Benjamin Herrenschmidt 2007-02-02 10:29 ` [RFC/PATCH 2.6.20-rc6 1/4] spidernet: autoneg support for Celleb Ishizaki Kou 2007-02-02 10:30 ` [RFC/PATCH 2.6.20-rc6 2/4] spidernet: load firmaware when open Ishizaki Kou 2007-02-02 10:31 ` [RFC/PATCH 2.6.20-rc6 3/4] spidernet: add support for Celleb Ishizaki Kou 2007-02-02 10:33 ` [RFC/PATCH 2.6.20-rc6 4/4] spidernet: remove txram full logging Ishizaki Kou 2007-02-04 23:44 ` [Cbe-oss-dev] spidernet: dynamic phy setup code Benjamin Herrenschmidt -- strict thread matches above, loose matches on Subject: below -- 2007-02-01 7:54 kou.ishizaki 2007-02-06 10:42 ` spidernet: dynamic phy setup code Ishizaki Kou
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).