* [PATCH 2/12]: spidernet: compile break.
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
@ 2007-02-16 0:44 ` Linas Vepstas
2007-02-16 0:45 ` [PATCH 3/12] spidernet: autoneg support for Celleb Linas Vepstas
` (10 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:44 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
Subject: [PATCH 2/12]: spidernet: compile break.
As of 2.6.20-git4, the spider_net driver does not compile.
This appears to be due to some archaic usage involving kobjects.
It also fixes a nasty double-free during ifdown of the interface.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
drivers/net/spider_net.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:50:33.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:52:04.000000000 -0600
@@ -1906,8 +1906,7 @@ spider_net_stop(struct net_device *netde
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
- /* free_irq(netdev->irq, netdev);*/
- free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+ free_irq(netdev->irq, netdev);
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_DMA_TX_FEND_VALUE);
@@ -1919,8 +1918,6 @@ spider_net_stop(struct net_device *netde
spider_net_release_tx_chain(card, 1);
spider_net_free_rx_chain_contents(card);
- spider_net_free_rx_chain_contents(card);
-
spider_net_free_chain(card, &card->tx_chain);
spider_net_free_chain(card, &card->rx_chain);
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 3/12] spidernet: autoneg support for Celleb
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
2007-02-16 0:44 ` [PATCH 2/12]: spidernet: compile break Linas Vepstas
@ 2007-02-16 0:45 ` Linas Vepstas
2007-02-16 0:46 ` [PATCH 4/12] spidernet: load firmware when open Linas Vepstas
` (9 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:45 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
Add auto negotiation support for Celleb.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/spider_net.c | 176 ++++++++++++++++++++++++++++++++++++++++++-----
drivers/net/spider_net.h | 10 ++
2 files changed, 170 insertions(+), 16 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.h
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.h 2007-02-15 17:50:33.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.h 2007-02-15 17:53:49.000000000 -0600
@@ -50,6 +50,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)
+#define SPIDER_NET_ANEG_TIMEOUT 2
#define SPIDER_NET_RX_CSUM_DEFAULT 1
@@ -104,6 +106,7 @@ extern char spider_net_driver_name[];
#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 @@ enum spider_net_int2_status {
/* 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
@@ -442,6 +448,8 @@ struct spider_net_card {
struct spider_net_descr_chain rx_chain;
struct spider_net_descr *low_watermark;
+ int aneg_count;
+ struct timer_list aneg_timer;
struct timer_list tx_timer;
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:52:04.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:53:49.000000000 -0600
@@ -166,6 +166,41 @@ spider_net_read_phy(struct net_device *n
}
/**
+ * 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, 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);
+ 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 |= ADVERTISED_10baseT_Half;
+ if (bmsr & BMSR_10FULL)
+ advertise |= ADVERTISED_10baseT_Full;
+ if (bmsr & BMSR_100HALF)
+ advertise |= ADVERTISED_100baseT_Half;
+ if (bmsr & BMSR_100FULL)
+ advertise |= ADVERTISED_100baseT_Full;
+
+ if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_TFULL))
+ advertise |= SUPPORTED_1000baseT_Full;
+ if ((bmsr & BMSR_ESTATEN) && (estat & ESTATUS_1000_THALF))
+ advertise |= SUPPORTED_1000baseT_Half;
+
+ mii_phy_probe(phy, phy->mii_id);
+ phy->def->ops->setup_aneg(phy, advertise);
+
+}
+
+/**
* spider_net_rx_irq_off - switch off rx irq on this spider card
* @card: device structure
*
@@ -1248,6 +1283,33 @@ 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 */
+ 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)
@@ -1500,6 +1562,9 @@ spider_net_interrupt(int irq, void *ptr)
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);
@@ -1624,8 +1689,6 @@ spider_net_enable_card(struct spider_net
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);
@@ -1656,6 +1719,11 @@ spider_net_open(struct net_device *netde
struct spider_net_card *card = netdev_priv(netdev);
int result;
+ /* 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);
+
result = spider_net_init_chain(card, &card->tx_chain);
if (result)
goto alloc_tx_failed;
@@ -1693,17 +1761,88 @@ alloc_skbs_failed:
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:
+ /* 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 failed,
+ * retry from beginning */
+ 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);
+
+ 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_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",
+ phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",
+ phy->autoneg==1 ? "" : "no ");
+
+ return;
+}
+
+/**
* 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)
@@ -1714,21 +1853,21 @@ spider_net_setup_phy(struct spider_net_c
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;
}
@@ -1900,11 +2039,13 @@ spider_net_stop(struct net_device *netde
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);
@@ -2043,6 +2184,11 @@ spider_net_setup_netdev(struct spider_ne
card->tx_timer.data = (unsigned long) card;
netdev->irq = card->pdev->irq;
+ 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->tx_chain.num_desc = tx_descriptors;
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 4/12] spidernet: load firmware when open
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
2007-02-16 0:44 ` [PATCH 2/12]: spidernet: compile break Linas Vepstas
2007-02-16 0:45 ` [PATCH 3/12] spidernet: autoneg support for Celleb Linas Vepstas
@ 2007-02-16 0:46 ` Linas Vepstas
2007-02-16 0:48 ` [PATCH 5/12] spidernet: spidernet: add support for Celleb Linas Vepstas
` (8 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:46 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
This patch moves calling init_firmware() from spider_net_probe() to
spider_net_open() so as to use the driver by built-in.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/spider_net.c | 247 +++++++++++++++++++++++------------------------
1 file changed, 123 insertions(+), 124 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:53:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:54:23.000000000 -0600
@@ -1705,6 +1705,124 @@ spider_net_enable_card(struct spider_net
}
/**
+ * 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
*
@@ -1719,6 +1837,10 @@ spider_net_open(struct net_device *netde
struct spider_net_card *card = netdev_priv(netdev);
int result;
+ 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)
@@ -1762,6 +1884,7 @@ alloc_rx_failed:
spider_net_free_chain(card, &card->tx_chain);
alloc_tx_failed:
del_timer_sync(&card->aneg_timer);
+init_firmware_failed:
return result;
}
@@ -1873,124 +1996,6 @@ spider_net_setup_phy(struct spider_net_c
}
/**
- * 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
*
@@ -2090,8 +2095,6 @@ spider_net_tx_timeout_task(struct work_s
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);
@@ -2363,10 +2366,6 @@ spider_net_probe(struct pci_dev *pdev, c
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] 36+ messages in thread* [PATCH 5/12] spidernet: spidernet: add support for Celleb
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (2 preceding siblings ...)
2007-02-16 0:46 ` [PATCH 4/12] spidernet: load firmware when open Linas Vepstas
@ 2007-02-16 0:48 ` Linas Vepstas
2007-02-16 0:49 ` [PATCH 6/12] spidernet: remove txram full logging Linas Vepstas
` (7 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:48 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
This patch adds or changes some HW specific settings for spider_net on
Celleb.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/Kconfig | 2 +-
drivers/net/spider_net.c | 8 +++++++-
drivers/net/spider_net.h | 6 ++++--
3 files changed, 12 insertions(+), 4 deletions(-)
Index: linux-2.6.20-git4/drivers/net/Kconfig
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/Kconfig 2007-02-15 17:50:33.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/Kconfig 2007-02-15 17:54:57.000000000 -0600
@@ -2243,7 +2243,7 @@ config BNX2
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
Index: linux-2.6.20-git4/drivers/net/spider_net.h
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.h 2007-02-15 17:53:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.h 2007-02-15 17:54:57.000000000 -0600
@@ -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 @@ extern char spider_net_driver_name[];
/* 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
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:54:23.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:54:57.000000000 -0600
@@ -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>
@@ -1605,6 +1606,11 @@ 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);
+
}
/**
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 6/12] spidernet: remove txram full logging
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (3 preceding siblings ...)
2007-02-16 0:48 ` [PATCH 5/12] spidernet: spidernet: add support for Celleb Linas Vepstas
@ 2007-02-16 0:49 ` Linas Vepstas
2007-02-16 0:50 ` [PATCH 7/12] spidernet: move medium variable into card struct Linas Vepstas
` (6 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
This patches removes logging for SPIDER_NET_GTMFLLINT interrupts.
Since the interrupts are not irregular, and they happen frequently
when using 100Mbps network switches.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/spider_net.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:54:57.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:55:19.000000000 -0600
@@ -1422,8 +1422,8 @@ spider_net_handle_error_irq(struct spide
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] 36+ messages in thread* [PATCH 7/12] spidernet: move medium variable into card struct
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (4 preceding siblings ...)
2007-02-16 0:49 ` [PATCH 6/12] spidernet: remove txram full logging Linas Vepstas
@ 2007-02-16 0:50 ` Linas Vepstas
2007-02-16 0:52 ` [PATCH 8/12] Spidernet: separate hardware state from driver state Linas Vepstas
` (5 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
This moves the medium variable into the spidernet card structure.
It renames the GMII_ variables to BCM54XX specific ones.
Signed-off-by: Jens Osterkamp <jens@de.ibm.com>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/spider_net.c | 14 +++++++-------
drivers/net/spider_net.h | 2 ++
2 files changed, 9 insertions(+), 7 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:55:19.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:57:55.000000000 -0600
@@ -1909,26 +1909,26 @@ static void spider_net_link_phy(unsigned
pr_info("%s: link is down trying to bring it up\n", card->netdev->name);
- switch (phy->medium) {
- case GMII_COPPER:
+ switch (card->medium) {
+ case BCM54XX_COPPER:
/* enable fiber with autonegotiation first */
if (phy->def->ops->enable_fiber)
phy->def->ops->enable_fiber(phy, 1);
- phy->medium = GMII_FIBER;
+ card->medium = BCM54XX_FIBER;
break;
- case GMII_FIBER:
+ case BCM54XX_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;
+ card->medium = BCM54XX_UNKNOWN;
break;
- case GMII_UNKNOWN:
+ case BCM54XX_UNKNOWN:
/* copper, fiber with and without failed,
* retry from beginning */
spider_net_setup_aneg(card);
- phy->medium = GMII_COPPER;
+ card->medium = BCM54XX_COPPER;
break;
}
Index: linux-2.6.20-git4/drivers/net/spider_net.h
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.h 2007-02-15 17:54:57.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.h 2007-02-15 17:57:55.000000000 -0600
@@ -444,6 +444,8 @@ struct spider_net_card {
struct pci_dev *pdev;
struct mii_phy phy;
+ int medium;
+
void __iomem *regs;
struct spider_net_descr_chain tx_chain;
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 8/12] Spidernet: separate hardware state from driver state.
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (5 preceding siblings ...)
2007-02-16 0:50 ` [PATCH 7/12] spidernet: move medium variable into card struct Linas Vepstas
@ 2007-02-16 0:52 ` Linas Vepstas
2007-02-16 0:53 ` [PATCH: 9/12]: spidernet: fix racy double-free of skb Linas Vepstas
` (4 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
This patch separates the hardware descriptor state from the
driver descriptor state, per (old) suggestion from Ben Herrenschmidt.
This compiles and boots and seems to work.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
drivers/net/spider_net.c | 150 ++++++++++++++++++++++++++---------------------
drivers/net/spider_net.h | 16 +++--
2 files changed, 95 insertions(+), 71 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.h
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.h 2007-02-15 17:55:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.h 2007-02-15 17:57:00.000000000 -0600
@@ -25,7 +25,7 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H
-#define VERSION "1.6 B"
+#define VERSION "1.6 C"
#include "sungem_phy.h"
@@ -364,8 +364,8 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
#define SPIDER_NET_DESCR_TXDESFLG 0x00800000
-struct spider_net_descr {
- /* as defined by the hardware */
+/* Descriptor, as defined by the hardware */
+struct spider_net_hw_descr {
u32 buf_addr;
u32 buf_size;
u32 next_descr_addr;
@@ -374,13 +374,15 @@ struct spider_net_descr {
u32 valid_size; /* all zeroes for tx */
u32 data_status;
u32 data_error; /* all zeroes for tx */
+} __attribute__((aligned(32)));
- /* used in the driver */
+struct spider_net_descr {
+ struct spider_net_hw_descr *hwdescr;
struct sk_buff *skb;
u32 bus_addr;
struct spider_net_descr *next;
struct spider_net_descr *prev;
-} __attribute__((aligned(32)));
+};
struct spider_net_descr_chain {
spinlock_t lock;
@@ -388,6 +390,7 @@ struct spider_net_descr_chain {
struct spider_net_descr *tail;
struct spider_net_descr *ring;
int num_desc;
+ struct spider_net_hw_descr *hwring;
dma_addr_t dma_addr;
};
@@ -464,6 +467,9 @@ struct spider_net_card {
struct net_device_stats netdev_stats;
struct spider_net_extra_stats spider_stats;
struct spider_net_options options;
+
+ /* Must be last item in struct */
+ struct spider_net_descr darray[0];
};
#define pr_err(fmt,arg...) \
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:55:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:57:00.000000000 -0600
@@ -299,9 +299,9 @@ spider_net_get_mac_address(struct net_de
* returns the status as in the dmac_cmd_status field of the descriptor
*/
static inline int
-spider_net_get_descr_status(struct spider_net_descr *descr)
+spider_net_get_descr_status(struct spider_net_hw_descr *hwdescr)
{
- return descr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
+ return hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
}
/**
@@ -319,12 +319,12 @@ spider_net_free_chain(struct spider_net_
descr = chain->ring;
do {
descr->bus_addr = 0;
- descr->next_descr_addr = 0;
+ descr->hwdescr->next_descr_addr = 0;
descr = descr->next;
} while (descr != chain->ring);
dma_free_coherent(&card->pdev->dev, chain->num_desc,
- chain->ring, chain->dma_addr);
+ chain->hwring, chain->dma_addr);
}
/**
@@ -343,31 +343,34 @@ spider_net_init_chain(struct spider_net_
{
int i;
struct spider_net_descr *descr;
+ struct spider_net_hw_descr *hwdescr;
dma_addr_t buf;
size_t alloc_size;
- alloc_size = chain->num_desc * sizeof (struct spider_net_descr);
+ alloc_size = chain->num_desc * sizeof(struct spider_net_hw_descr);
- chain->ring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
+ chain->hwring = dma_alloc_coherent(&card->pdev->dev, alloc_size,
&chain->dma_addr, GFP_KERNEL);
- if (!chain->ring)
+ if (!chain->hwring)
return -ENOMEM;
- descr = chain->ring;
- memset(descr, 0, alloc_size);
+ memset(chain->ring, 0, chain->num_desc * sizeof(struct spider_net_descr));
/* Set up the hardware pointers in each descriptor */
+ descr = chain->ring;
+ hwdescr = chain->hwring;
buf = chain->dma_addr;
- for (i=0; i < chain->num_desc; i++, descr++) {
- descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+ for (i=0; i < chain->num_desc; i++, descr++, hwdescr++) {
+ hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+ hwdescr->next_descr_addr = 0;
+ descr->hwdescr = hwdescr;
descr->bus_addr = buf;
- descr->next_descr_addr = 0;
descr->next = descr + 1;
descr->prev = descr - 1;
- buf += sizeof(struct spider_net_descr);
+ buf += sizeof(struct spider_net_hw_descr);
}
/* do actual circular list */
(descr-1)->next = chain->ring;
@@ -394,7 +397,7 @@ spider_net_free_rx_chain_contents(struct
do {
if (descr->skb) {
dev_kfree_skb(descr->skb);
- pci_unmap_single(card->pdev, descr->buf_addr,
+ pci_unmap_single(card->pdev, descr->hwdescr->buf_addr,
SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
}
@@ -416,6 +419,7 @@ static int
spider_net_prepare_rx_descr(struct spider_net_card *card,
struct spider_net_descr *descr)
{
+ struct spider_net_hw_descr *hwdescr = descr->hwdescr;
dma_addr_t buf;
int offset;
int bufsize;
@@ -434,11 +438,11 @@ spider_net_prepare_rx_descr(struct spide
card->spider_stats.alloc_rx_skb_error++;
return -ENOMEM;
}
- descr->buf_size = bufsize;
- descr->result_size = 0;
- descr->valid_size = 0;
- descr->data_status = 0;
- descr->data_error = 0;
+ hwdescr->buf_size = bufsize;
+ hwdescr->result_size = 0;
+ hwdescr->valid_size = 0;
+ hwdescr->data_status = 0;
+ hwdescr->data_error = 0;
offset = ((unsigned long)descr->skb->data) &
(SPIDER_NET_RXBUF_ALIGN - 1);
@@ -447,21 +451,21 @@ spider_net_prepare_rx_descr(struct spide
/* iommu-map the skb */
buf = pci_map_single(card->pdev, descr->skb->data,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
- descr->buf_addr = buf;
if (pci_dma_mapping_error(buf)) {
dev_kfree_skb_any(descr->skb);
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
- descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+ hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
- descr->next_descr_addr = 0;
+ hwdescr->buf_addr = buf;
+ hwdescr->next_descr_addr = 0;
wmb();
- descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
+ hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
SPIDER_NET_DMAC_NOINTR_COMPLETE;
wmb();
- descr->prev->next_descr_addr = descr->bus_addr;
+ descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
}
return 0;
@@ -517,7 +521,7 @@ spider_net_refill_rx_chain(struct spider
if (!spin_trylock_irqsave(&chain->lock, flags))
return;
- while (spider_net_get_descr_status(chain->head) ==
+ while (spider_net_get_descr_status(chain->head->hwdescr) ==
SPIDER_NET_DESCR_NOT_IN_USE) {
if (spider_net_prepare_rx_descr(card, chain->head))
break;
@@ -679,6 +683,7 @@ spider_net_prepare_tx_descr(struct spide
struct sk_buff *skb)
{
struct spider_net_descr *descr;
+ struct spider_net_hw_descr *hwdescr;
dma_addr_t buf;
unsigned long flags;
@@ -693,30 +698,32 @@ spider_net_prepare_tx_descr(struct spide
spin_lock_irqsave(&card->tx_chain.lock, flags);
descr = card->tx_chain.head;
+ hwdescr = descr->hwdescr;
card->tx_chain.head = descr->next;
- descr->buf_addr = buf;
- descr->buf_size = skb->len;
- descr->next_descr_addr = 0;
descr->skb = skb;
- descr->data_status = 0;
+ hwdescr->buf_addr = buf;
+ hwdescr->buf_size = skb->len;
+ hwdescr->next_descr_addr = 0;
+ hwdescr->data_status = 0;
- descr->dmac_cmd_status =
+ hwdescr->dmac_cmd_status =
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
spin_unlock_irqrestore(&card->tx_chain.lock, flags);
if (skb->protocol == htons(ETH_P_IP))
switch (skb->nh.iph->protocol) {
case IPPROTO_TCP:
- descr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
+ hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
break;
case IPPROTO_UDP:
- descr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
+ hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
break;
}
/* Chain the bus address, so that the DMA engine finds this descr. */
- descr->prev->next_descr_addr = descr->bus_addr;
+ wmb();
+ descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
card->netdev->trans_start = jiffies; /* set netdev watchdog timer */
return 0;
@@ -725,16 +732,17 @@ spider_net_prepare_tx_descr(struct spide
static int
spider_net_set_low_watermark(struct spider_net_card *card)
{
+ struct spider_net_descr *descr = card->tx_chain.tail;
+ struct spider_net_hw_descr *hwdescr;
unsigned long flags;
int status;
int cnt=0;
int i;
- struct spider_net_descr *descr = card->tx_chain.tail;
/* Measure the length of the queue. Measurement does not
* need to be precise -- does not need a lock. */
while (descr != card->tx_chain.head) {
- status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
+ status = descr->hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
if (status == SPIDER_NET_DESCR_NOT_IN_USE)
break;
descr = descr->next;
@@ -753,10 +761,12 @@ spider_net_set_low_watermark(struct spid
/* Set the new watermark, clear the old watermark */
spin_lock_irqsave(&card->tx_chain.lock, flags);
- descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
- if (card->low_watermark && card->low_watermark != descr)
- card->low_watermark->dmac_cmd_status =
- card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+ descr->hwdescr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
+ if (card->low_watermark && card->low_watermark != descr) {
+ hwdescr = card->low_watermark->hwdescr;
+ hwdescr->dmac_cmd_status =
+ hwdescr->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+ }
card->low_watermark = descr;
spin_unlock_irqrestore(&card->tx_chain.lock, flags);
return cnt;
@@ -779,6 +789,7 @@ spider_net_release_tx_chain(struct spide
{
struct spider_net_descr_chain *chain = &card->tx_chain;
struct spider_net_descr *descr;
+ struct spider_net_hw_descr *hwdescr;
struct sk_buff *skb;
u32 buf_addr;
unsigned long flags;
@@ -787,8 +798,9 @@ spider_net_release_tx_chain(struct spide
while (chain->tail != chain->head) {
spin_lock_irqsave(&chain->lock, flags);
descr = chain->tail;
+ hwdescr = descr->hwdescr;
- status = spider_net_get_descr_status(descr);
+ status = spider_net_get_descr_status(hwdescr);
switch (status) {
case SPIDER_NET_DESCR_COMPLETE:
card->netdev_stats.tx_packets++;
@@ -824,9 +836,9 @@ spider_net_release_tx_chain(struct spide
}
chain->tail = descr->next;
- descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+ hwdescr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
skb = descr->skb;
- buf_addr = descr->buf_addr;
+ buf_addr = hwdescr->buf_addr;
spin_unlock_irqrestore(&chain->lock, flags);
/* unmap the skb */
@@ -862,7 +874,7 @@ spider_net_kick_tx_dma(struct spider_net
descr = card->tx_chain.tail;
for (;;) {
- if (spider_net_get_descr_status(descr) ==
+ if (spider_net_get_descr_status(descr->hwdescr) ==
SPIDER_NET_DESCR_CARDOWNED) {
spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
descr->bus_addr);
@@ -958,17 +970,18 @@ static void
spider_net_pass_skb_up(struct spider_net_descr *descr,
struct spider_net_card *card)
{
+ struct spider_net_hw_descr *hwdescr= descr->hwdescr;
struct sk_buff *skb;
struct net_device *netdev;
u32 data_status, data_error;
- data_status = descr->data_status;
- data_error = descr->data_error;
+ data_status = hwdescr->data_status;
+ data_error = hwdescr->data_error;
netdev = card->netdev;
skb = descr->skb;
skb->dev = netdev;
- skb_put(skb, descr->valid_size);
+ skb_put(skb, hwdescr->valid_size);
/* the card seems to add 2 bytes of junk in front
* of the ethernet frame */
@@ -1044,9 +1057,10 @@ spider_net_decode_one_descr(struct spide
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
+ struct spider_net_hw_descr *hwdescr = descr->hwdescr;
int status;
- status = spider_net_get_descr_status(descr);
+ status = spider_net_get_descr_status(hwdescr);
/* Nothing in the descriptor, or ring must be empty */
if ((status == SPIDER_NET_DESCR_CARDOWNED) ||
@@ -1057,7 +1071,7 @@ spider_net_decode_one_descr(struct spide
chain->tail = descr->next;
/* unmap descriptor */
- pci_unmap_single(card->pdev, descr->buf_addr,
+ pci_unmap_single(card->pdev, hwdescr->buf_addr,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
@@ -1080,27 +1094,26 @@ spider_net_decode_one_descr(struct spide
}
/* The cases we'll throw away the packet immediately */
- if (descr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+ if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
if (netif_msg_rx_err(card))
pr_err("%s: error in received descriptor found, "
"data_status=x%08x, data_error=x%08x\n",
card->netdev->name,
- descr->data_status, descr->data_error);
+ hwdescr->data_status, hwdescr->data_error);
goto bad_desc;
}
- if (descr->dmac_cmd_status & 0xfefe) {
+ if (hwdescr->dmac_cmd_status & 0xfefe) {
pr_err("%s: bad status, cmd_status=x%08x\n",
card->netdev->name,
- descr->dmac_cmd_status);
- pr_err("buf_addr=x%08x\n", descr->buf_addr);
- pr_err("buf_size=x%08x\n", descr->buf_size);
- pr_err("next_descr_addr=x%08x\n", descr->next_descr_addr);
- pr_err("result_size=x%08x\n", descr->result_size);
- pr_err("valid_size=x%08x\n", descr->valid_size);
- pr_err("data_status=x%08x\n", descr->data_status);
- pr_err("data_error=x%08x\n", descr->data_error);
- pr_err("bus_addr=x%08x\n", descr->bus_addr);
+ hwdescr->dmac_cmd_status);
+ pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+ pr_err("buf_size=x%08x\n", hwdescr->buf_size);
+ pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
+ pr_err("result_size=x%08x\n", hwdescr->result_size);
+ pr_err("valid_size=x%08x\n", hwdescr->valid_size);
+ pr_err("data_status=x%08x\n", hwdescr->data_status);
+ pr_err("data_error=x%08x\n", hwdescr->data_error);
pr_err("which=%ld\n", descr - card->rx_chain.ring);
card->spider_stats.rx_desc_error++;
@@ -1109,12 +1122,12 @@ spider_net_decode_one_descr(struct spide
/* Ok, we've got a packet in descr */
spider_net_pass_skb_up(descr, card);
- descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+ hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
return 1;
bad_desc:
dev_kfree_skb_irq(descr->skb);
- descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
+ hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
return 0;
}
@@ -2200,9 +2213,6 @@ spider_net_setup_netdev(struct spider_ne
card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
- card->tx_chain.num_desc = tx_descriptors;
- card->rx_chain.num_desc = rx_descriptors;
-
spider_net_setup_netdev_ops(netdev);
netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
@@ -2250,8 +2260,11 @@ spider_net_alloc_card(void)
{
struct net_device *netdev;
struct spider_net_card *card;
+ size_t alloc_size;
- netdev = alloc_etherdev(sizeof(struct spider_net_card));
+ alloc_size = sizeof(struct spider_net_card) +
+ (tx_descriptors + rx_descriptors) * sizeof(struct spider_net_descr);
+ netdev = alloc_etherdev(alloc_size);
if (!netdev)
return NULL;
@@ -2262,6 +2275,11 @@ spider_net_alloc_card(void)
init_waitqueue_head(&card->waitq);
atomic_set(&card->tx_timeout_task_counter, 0);
+ card->rx_chain.num_desc = rx_descriptors;
+ card->rx_chain.ring = card->darray;
+ card->tx_chain.num_desc = tx_descriptors;
+ card->tx_chain.ring = card->darray + rx_descriptors;
+
return card;
}
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH: 9/12]: spidernet: fix racy double-free of skb
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (6 preceding siblings ...)
2007-02-16 0:52 ` [PATCH 8/12] Spidernet: separate hardware state from driver state Linas Vepstas
@ 2007-02-16 0:53 ` Linas Vepstas
2007-02-16 0:55 ` [PATCH 10/12] spidernet: transmit race Linas Vepstas
` (3 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
It appears that under certain circumstances, a race will result
in a double-free of an skb. This patch null's out the skb pointer
upon the skb free, avoiding the inadvertent deref of bogus data.
The next patch fixes the actual race.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
drivers/net/spider_net.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:58:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 17:58:54.000000000 -0600
@@ -396,10 +396,11 @@ spider_net_free_rx_chain_contents(struct
descr = card->rx_chain.head;
do {
if (descr->skb) {
- dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->hwdescr->buf_addr,
SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
+ dev_kfree_skb(descr->skb);
+ descr->skb = NULL;
}
descr = descr->next;
} while (descr != card->rx_chain.head);
@@ -453,6 +454,7 @@ spider_net_prepare_rx_descr(struct spide
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(buf)) {
dev_kfree_skb_any(descr->skb);
+ descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
@@ -682,6 +684,7 @@ static int
spider_net_prepare_tx_descr(struct spider_net_card *card,
struct sk_buff *skb)
{
+ struct spider_net_descr_chain *chain = &card->tx_chain;
struct spider_net_descr *descr;
struct spider_net_hw_descr *hwdescr;
dma_addr_t buf;
@@ -696,10 +699,15 @@ spider_net_prepare_tx_descr(struct spide
return -ENOMEM;
}
- spin_lock_irqsave(&card->tx_chain.lock, flags);
+ spin_lock_irqsave(&chain->lock, flags);
descr = card->tx_chain.head;
+ if (descr->next == chain->tail->prev) {
+ spin_unlock_irqrestore(&chain->lock, flags);
+ pci_unmap_single(card->pdev, buf, skb->len, PCI_DMA_TODEVICE);
+ return -ENOMEM;
+ }
hwdescr = descr->hwdescr;
- card->tx_chain.head = descr->next;
+ chain->head = descr->next;
descr->skb = skb;
hwdescr->buf_addr = buf;
@@ -709,7 +717,7 @@ spider_net_prepare_tx_descr(struct spide
hwdescr->dmac_cmd_status =
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
- spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+ spin_unlock_irqrestore(&chain->lock, flags);
if (skb->protocol == htons(ETH_P_IP))
switch (skb->nh.iph->protocol) {
@@ -838,6 +846,7 @@ spider_net_release_tx_chain(struct spide
chain->tail = descr->next;
hwdescr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
skb = descr->skb;
+ descr->skb = NULL;
buf_addr = hwdescr->buf_addr;
spin_unlock_irqrestore(&chain->lock, flags);
@@ -903,13 +912,10 @@ spider_net_xmit(struct sk_buff *skb, str
{
int cnt;
struct spider_net_card *card = netdev_priv(netdev);
- struct spider_net_descr_chain *chain = &card->tx_chain;
spider_net_release_tx_chain(card, 0);
- if ((chain->head->next == chain->tail->prev) ||
- (spider_net_prepare_tx_descr(card, skb) != 0)) {
-
+ if (spider_net_prepare_tx_descr(card, skb) != 0) {
card->netdev_stats.tx_dropped++;
netif_stop_queue(netdev);
return NETDEV_TX_BUSY;
@@ -1127,6 +1133,7 @@ spider_net_decode_one_descr(struct spide
bad_desc:
dev_kfree_skb_irq(descr->skb);
+ descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
return 0;
}
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 10/12] spidernet: transmit race
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (7 preceding siblings ...)
2007-02-16 0:53 ` [PATCH: 9/12]: spidernet: fix racy double-free of skb Linas Vepstas
@ 2007-02-16 0:55 ` Linas Vepstas
2007-02-16 0:57 ` [PATCH 11/12] spidernet: janitorial, typos Linas Vepstas
` (2 subsequent siblings)
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:55 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
Multiple threads performing a transmit can race into
the spidernet tx ring cleanup code. This puts the
relevant check under a lock.
Signed-off-by: Linas Vepstas <lins@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
drivers/net/spider_net.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 17:58:54.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 18:00:49.000000000 -0600
@@ -803,8 +803,12 @@ spider_net_release_tx_chain(struct spide
unsigned long flags;
int status;
- while (chain->tail != chain->head) {
+ while (1) {
spin_lock_irqsave(&chain->lock, flags);
+ if (chain->tail == chain->head) {
+ spin_unlock_irqrestore(&chain->lock, flags);
+ return 0;
+ }
descr = chain->tail;
hwdescr = descr->hwdescr;
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 11/12] spidernet: janitorial, typos
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (8 preceding siblings ...)
2007-02-16 0:55 ` [PATCH 10/12] spidernet: transmit race Linas Vepstas
@ 2007-02-16 0:57 ` Linas Vepstas
2007-02-16 0:58 ` [PATCH 12/12]: spidernet: maintainership Linas Vepstas
2007-02-16 14:46 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Arnd Bergmann
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
Janitorial patch. Undo long lines, fix typo in err msg.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
drivers/net/spider_net.c | 13 +++++++------
drivers/net/spider_net.h | 2 +-
2 files changed, 8 insertions(+), 7 deletions(-)
Index: linux-2.6.20-git4/drivers/net/spider_net.c
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.c 2007-02-15 18:00:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.c 2007-02-15 18:01:14.000000000 -0600
@@ -1053,14 +1053,15 @@ static void show_rx_chain(struct spider_
#endif
/**
- * spider_net_decode_one_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an RX descriptor
* @card: card structure
*
- * Returns 1 if a packet has been sent to the stack, otherwise 0
+ * Returns 1 if a packet has been sent to the stack, otherwise 0.
*
- * Processes an rx descriptor by iommu-unmapping the data buffer and passing
- * the packet up to the stack. This function is called in softirq
- * context, e.g. either bottom half from interrupt or NAPI polling context
+ * Processes an RX descriptor by iommu-unmapping the data buffer
+ * and passing the packet up to the stack. This function is called
+ * in softirq context, e.g. either bottom half from interrupt or
+ * NAPI polling context.
*/
static int
spider_net_decode_one_descr(struct spider_net_card *card)
@@ -1097,7 +1098,7 @@ spider_net_decode_one_descr(struct spide
if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
(status != SPIDER_NET_DESCR_FRAME_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: RX descriptor with unkown state %d\n",
+ pr_err("%s: RX descriptor with unknown state %d\n",
card->netdev->name, status);
card->spider_stats.rx_desc_unk_state++;
goto bad_desc;
Index: linux-2.6.20-git4/drivers/net/spider_net.h
===================================================================
--- linux-2.6.20-git4.orig/drivers/net/spider_net.h 2007-02-15 18:00:49.000000000 -0600
+++ linux-2.6.20-git4/drivers/net/spider_net.h 2007-02-15 18:01:14.000000000 -0600
@@ -25,7 +25,7 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H
-#define VERSION "1.6 C"
+#define VERSION "2.0 A"
#include "sungem_phy.h"
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 12/12]: spidernet: maintainership
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (9 preceding siblings ...)
2007-02-16 0:57 ` [PATCH 11/12] spidernet: janitorial, typos Linas Vepstas
@ 2007-02-16 0:58 ` Linas Vepstas
2007-02-16 14:46 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Arnd Bergmann
11 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 0:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: arnd, linuxppc-dev
Provisionally change maintinership.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
Cc: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
----
MAINTAINERS | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: linux-2.6.20-git4/MAINTAINERS
===================================================================
--- linux-2.6.20-git4.orig/MAINTAINERS 2007-02-15 17:27:39.000000000 -0600
+++ linux-2.6.20-git4/MAINTAINERS 2007-02-15 18:01:42.000000000 -0600
@@ -3119,8 +3119,8 @@ L: linux-kernel@vger.kernel.org ?
S: Supported
SPIDERNET NETWORK DRIVER for CELL
-P: Jim Lewis
-M: jim@jklewis.com
+P: Linas Vepstas
+M: linas@austin.ibm.com
L: netdev@vger.kernel.org
S: Supported
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg.
2007-02-16 0:43 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Linas Vepstas
` (10 preceding siblings ...)
2007-02-16 0:58 ` [PATCH 12/12]: spidernet: maintainership Linas Vepstas
@ 2007-02-16 14:46 ` Arnd Bergmann
2007-02-16 16:19 ` Linas Vepstas
11 siblings, 1 reply; 36+ messages in thread
From: Arnd Bergmann @ 2007-02-16 14:46 UTC (permalink / raw)
To: linuxppc-dev
On Friday 16 February 2007 01:43, Linas Vepstas wrote:
> Signed-off-by: Jens Osterkamp <jens@de.ibm.com>
> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
> Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
You only have the Signed-off-by information here and in the other
patches, but no 'From:' line.
I assume that Jeff uses the git-applymbox tool to import
mails, in which case the first line of the patch description
should be 'From: Someone Else <someone@example.com>', unless you
are the author of the patch yourself.
Arnd <><
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg.
2007-02-16 14:46 ` [PATCH 1/12]: sungem_phy: support bcm5461 phy, autoneg Arnd Bergmann
@ 2007-02-16 16:19 ` Linas Vepstas
0 siblings, 0 replies; 36+ messages in thread
From: Linas Vepstas @ 2007-02-16 16:19 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev
On Fri, Feb 16, 2007 at 03:46:31PM +0100, Arnd Bergmann wrote:
> On Friday 16 February 2007 01:43, Linas Vepstas wrote:
> > Signed-off-by: Jens Osterkamp <jens@de.ibm.com>
> > Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
> > Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
>
> You only have the Signed-off-by information here and in the other
> patches, but no 'From:' line.
>
> I assume that Jeff uses the git-applymbox tool to import
> mails, in which case the first line of the patch description
> should be 'From: Someone Else <someone@example.com>', unless you
> are the author of the patch yourself.
Ahh. OK. I was assuming it was the first signed-off-by that counted.
--linas
^ permalink raw reply [flat|nested] 36+ messages in thread