Problems after merge to 2.6.18-rc1
Subsystems (3)
Hello,
I just finished a (big) merge with linux-mips 2.6.18-rc1 and my tree and at boot I get:
Linux version 2.6.18-rc1-g2636fd13-dirty (giometti@gundam) (gcc version 3.4.3) #165 Thu Jul 13 18:13:26 CEST 2006 CPU revision is: 02030204
Board WWPC1000 version 1.0
WWPC-setup: uC=off
(PRId 02030204) @ 396MHZ
BCLK switching enabled!
Determined physical RAM map:
memory: 04000000 @ 00000000 (usable)
Early serial console at AU 0x11100000 (options '115200')
Determined physical RAM map:
memory: 04000000 @ 00000000 (usable)
Built 1 zonelists. Total pages: 16384
Kernel command line: wwpc=uc-off console=uart,au,0x11100000,115200 root=/dev/nfs rw nfsroot=192.168.32.254:/homemipsel/distro/debian ip=192.168.32.24:192.168.32.254::255.255.255.0:000:eth0:off
Primary instruction cache 16kB, physically tagged, 4-way, linesize 32 bytes.
Primary data cache 16kB, 4-way, linesize 32 bytes.
Synthesized TLB refill handler (17 instructions).
Synthesized TLB load handler fastpath (34 instructions).
Synthesized TLB store handler fastpath (34 instructions).
Synthesized TLB modify handler fastpath (33 instructions).
PID hash table entries: 1024 (order: 10, 4096 bytes)
calculating r4koff... 00182b80(1584000)
CPU frequency 396.00 MHz
Console: colour dummy device 80x25
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Bad page state in process 'swapper'
page:810092a0 flags:0x00000000 mapping:00000000 mapcount:1 count:0
Trying to fix it up, but a reboot is needed
Backtrace:
Call Trace:
[<8015d91c>] bad_page+0x6c/0xac
[<8015e4c0>] free_hot_cold_page+0x190/0x1ec
[<8046099c>] free_all_bootmem_core+0x1ec/0x228
[<80457110>] mem_init+0x4c/0x218
[<80462a50>] inode_init_early+0x68/0xbc
[<804657d8>] console_init+0x48/0x68
[<80450824>] start_kernel+0x208/0x400
[<8045081c>] start_kernel+0x200/0x400
[<80450134>] unknown_bootoption+0x0/0x310 Bad page state in process 'swapper'
page:810092c0 flags:0x00000000 mapping:00000000 mapcount:1 count:0 Trying to fix it up, but a reboot is needed
...
Suggestions? :)
Thanks,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Hi,
Quoted 10 lines · Rodolfo Giometti
Call Trace:
[<8015d91c>] bad_page+0x6c/0xac
[<8015e4c0>] free_hot_cold_page+0x190/0x1ec
[<8046099c>] free_all_bootmem_core+0x1ec/0x228
[<80457110>] mem_init+0x4c/0x218
[<80462a50>] inode_init_early+0x68/0xbc
[<804657d8>] console_init+0x48/0x68
[<80450824>] start_kernel+0x208/0x400
[<8045081c>] start_kernel+0x200/0x400
[<80450134>] unknown_bootoption+0x0/0x310Well, what might 'unknown_bootoption' be trying to tell you? What boot options did you set?
Daniel
Quoted 15 lines · Rodolfo Giometti
I just finished a (big) merge with linux-mips 2.6.18-rc1 and my tree and at boot I get:
Linux version 2.6.18-rc1-g2636fd13-dirty (giometti@gundam) (gcc version 3.4.3) #165 Thu Jul 13 18:13:26 CEST 2006 CPU revision is: 02030204 Board WWPC1000 version 1.0 WWPC-setup: uC=off (PRId 02030204) @ 396MHZ BCLK switching enabled! Determined physical RAM map: memory: 04000000 @ 00000000 (usable) Early serial console at AU 0x11100000 (options '115200') Determined physical RAM map: memory: 04000000 @ 00000000 (usable) Built 1 zonelists. Total pages: 16384
Two "Determined physycal RAM map:" line here. If both were printed in parse_cmdline_early() (i.e. parse_cmdline_early was called twice), something is seriously broken.
---
Atsushi Nemoto
Quoted 4 lines · Atsushi Nemoto
Two "Determined physycal RAM map:" line here. If both were printed in
parse_cmdline_early()(i.e.parse_cmdline_earlywas called twice), something is seriously broken.
Yes, you was right. I fixed it! :)
However now I have another (strange) problem.
Attached you can find my patch to add power managament to the new version of file "drivers/net/au1000_eth.c" that implements the PHY-layer support.
Please, note the hack after the function mii_probe() called by au1000_lowlevel_probe().
Kernel messages during suspend are:
hostname:~# apm --suspend
Stopping tasks: ===============================|
au1xxx_pm_prepare: state = 3
usbdev1.1_ep81: PM: suspend 0->2, parent 1-0:1.0 already 1
warning! Serial console ttyS0 is not disabled in debug kernel mode
au1xxx_pm_enter: state = 3
au_sleep: reason -3 force 0 wakeup 100 ticks 3000
au_sleep: Zzz...
au_sleep: Yep!
kobject_add failed for 0:1f with -EEXIST, don't try to register things with the same name in the same directory.
Call Trace:
[<80252ca8>] kobject_add+0x17c/0x1e0
[<80252b98>] kobject_add+0x6c/0x1e0
[<80292008>] device_add+0xc0/0x464
[<80291ff4>] device_add+0xac/0x464
[<802a2e64>] mdiobus_register+0x134/0x198
[<802a3ac0>] au1000_lowlevel_probe+0x104/0x4b4
[<802a58a4>] au1000_drv_resume+0x3c/0xc8
[<80138978>] process_timeout+0x0/0x8
[<80298610>] platform_resume+0x34/0x40
[<8029bf7c>] resume_device+0x19c/0x200
[<802528e4>] kobject_get+0x20/0x34
[<8029391c>] __sysdev_resume+0xf0/0xf8
[<80291da4>] get_device+0x20/0x34
[<8029c1c4>] dpm_resume+0x1e4/0x3c0
[<8029c3fc>] device_resume+0x5c/0x174
[<80153848>] enter_state+0x290/0x314
[<80153840>] enter_state+0x288/0x314
[<8010e824>] apm_suspend+0x1c/0xa0
[<80219750>] nfs_getattr+0x88/0xf8
[<80219708>] nfs_getattr+0x40/0xf8
[<8010eca8>] apm_ioctl+0x198/0x22c
[<80110e84>] do_page_fault+0x364/0x3d0
[<80110c24>] do_page_fault+0x104/0x3d0
[<801a0d24>] do_ioctl+0x54/0x90
[<801a0f6c>] vfs_ioctl+0x20c/0x394
[<801b7950>] sync_inodes+0x20/0x54
[<801a1144>] sys_ioctl+0x50/0x9c
[<8010f66c>] stack_done+0x20/0x40
[<8010f66c>] stack_done+0x20/0x40 phy 31 failed to register
au1000_eth_mii: probed
eth0: 0:1f already attached
eth0: Could not attach to PHY
usb usb1: root hub lost power or was reset
Restarting tasks... done
au1xxx_pm_finish: state = 3
hostname:~#
The first strange thing is that this time the kernel messages stop after "au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..." as before the merge! Maybe something as changed in serial console magement?
The second strange thing is that _only_ calling the mii_probe() the resume works correctly, otherwise the CPU loops forever calling the au1000_lowlevel_probe() without showing the printk() messages through the serial console. =:-o
Suggestions?
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Quoted 2 lines · Rodolfo Giometti
Attached you can find my patch to add power managament to the new
Sorry... :)
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
drivers/net/au1000_eth.c +297 -191
@@ -11,6 +11,8 @@* ioctls (SIOCGMIIPHY) * Copyright 2006 Herbert Valerio Riedel <[email protected]> * converted to use linux-2.6.x's PHY framework +* Copyright 2006 Rodolfo Giometti <[email protected]> +* power management, driver registration and module support. * * Author: MontaVista Software, Inc. * [email protected] or [email protected]
@@ -61,6 +63,7 @@ #include <asm/irq.h>#include <asm/io.h> #include <asm/processor.h> +#include <linux/platform_device.h> #include <asm/mach-au1x00/au1000.h> #include <asm/cpu.h> #include "au1000_eth.h"
@@ -83,7 +86,8 @@ MODULE_LICENSE("GPL");// prototypes static void hard_stop (struct net_device *);static void enable_rx_tx (struct net_device *dev); -static struct net_device *au1000_probe (int port_num); +static int au1000_lowlevel_probe (struct net_device *ndev,void *ioaddr,void *macen_addr,int port_num,int skip_prom); +static void au1000_lowlevel_remove (struct net_device *ndev);static int au1000_init (struct net_device *);static int au1000_open (struct net_device *);static int au1000_close (struct net_device *);
@@ -520,59 +524,6 @@ setup_hw_rings(struct au1000_private *au } } -static struct { -u32 base_addr; -u32 macen_addr; -int irq; -struct net_device *dev; -} iflist[2 ] = { -#ifdef CONFIG_SOC_AU1000 - {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT}, - {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1100 - {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1500 - {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT}, - {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1550 - {AU1550_ETH0_BASE ,AU1550_MAC0_ENABLE ,AU1550_MAC0_DMA_INT }, - {AU1550_ETH1_BASE ,AU1550_MAC1_ENABLE ,AU1550_MAC1_DMA_INT } -#endif -}; - -static int num_ifs; - -/* -* Setup the base address and interupt of the Au1xxx ethernet macs -* based on cpu type and whether the interface is enabled in sys_pinfunc -* register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. -*/ -static int __init au1000_init_module (void ) -{ -int ni = (int )((au_readl (SYS_PINFUNC ) & (u32)(SYS_PF_NI2 )) >>4 ); -struct net_device *dev; -int i, found_one =0 ; - - num_ifs =NUM_ETH_INTERFACES - ni; - -for (i =0 ; i < num_ifs; i++) { - dev =au1000_probe (i); - iflist[i].dev = dev; -if (dev) - found_one++; - } -if (!found_one) -return -ENODEV ; -return 0 ; -} - -/* -* ethtool operations -*/ -static int au1000_get_settings (struct net_device *dev,struct ethtool_cmd *cmd) {struct au1000_private *aup = (struct au1000_private *)dev->priv;
@@ -615,48 +566,14 @@ static struct ethtool_ops au1000_ethtool .get_link = ethtool_op_get_link, }; -static struct net_device *au1000_probe (int port_num) +static int +au1000_lowlevel_probe (struct net_device *ndev,void *ioaddr,void *macen_addr,int port_num,int skip_prom) { -static unsigned version_printed =0 ; -struct au1000_private *aup =NULL ; -struct net_device *dev =NULL ; +struct au1000_private *aup = ndev->priv;db_dest_t *pDB, *pDBfree;char *pmac, *argptr;char ethaddr[6 ]; -int irq, i, err; -u32 base, macen; - -if (port_num >=NUM_ETH_INTERFACES ) -return NULL ; - - base =CPHYSADDR (iflist[port_num].base_addr ); - macen =CPHYSADDR (iflist[port_num].macen_addr); - irq = iflist[port_num].irq; - -if (!request_mem_region ( base,MAC_IOSIZE ,"Au1x00 ENET" ) || - !request_mem_region (macen,4 ,"Au1x00 ENET" )) -return NULL ; - -if (version_printed++ ==0 ) -printk ("%s version %s %s\n" ,DRV_NAME ,DRV_VERSION ,DRV_AUTHOR ); - - dev =alloc_etherdev (sizeof (struct au1000_private )); -if (!dev) { -printk (KERN_ERR "%s: alloc_etherdev failed\n" ,DRV_NAME ); -return NULL ; - } - -if ((err =register_netdev (dev)) !=0 ) { -printk (KERN_ERR "%s: Cannot register net device, error %d\n" , -DRV_NAME , err); -free_netdev (dev); -return NULL ; - } - -printk ("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n" , - dev->name, base, irq); - - aup = dev->priv; +int i, ret;/* Allocate the data buffers */ /* Snooping works fine with eth on all au1xxx */
@@ -664,53 +581,62 @@ static struct net_device * au1000_probe( (NUM_TX_BUFFS +NUM_RX_BUFFS ), &aup->dma_addr, 0);if (!aup->vaddr) { -free_netdev (dev); -release_mem_region ( base,MAC_IOSIZE ); -release_mem_region (macen,4 ); -return NULL ; +printk (KERN_ERR "%s: cannot dma_alloc_noncoherent\n" , + ndev->name); + ret = -ENOMEM ; + goto out; }/* aup->mac is the base address of the MAC's registers */ - aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; - + aup->mac = (volatile mac_reg_t *)((unsigned long )ioaddr);/* Setup some variables for quick register address access */ - aup->enable = (volatile u32 *)iflist[port_num].macen_addr; - aup->mac_id = port_num; - au_macs[port_num] = aup; - -if (port_num ==0 ) { -/* Check the environment variables first */ -if (get_ethernet_addr (ethaddr) ==0 ) -memcpy (au1000_mac_addr, ethaddr,sizeof (au1000_mac_addr)); -else { -/* Check command line */ - argptr =prom_getcmdline (); -if ((pmac =strstr (argptr,"ethaddr=" )) ==NULL ) -printk (KERN_INFO "%s: No MAC address found\n" , - dev->name); -/* Use the hard coded MAC addresses */ -else { -str2eaddr (ethaddr, pmac +strlen ("ethaddr=" )); -memcpy (au1000_mac_addr, ethaddr, -sizeof (au1000_mac_addr)); +if (port_num ==0 ) + { +if (!skip_prom) { +/* check env variables first */ +if (!get_ethernet_addr (ethaddr)) { +memcpy (au1000_mac_addr, ethaddr,sizeof (au1000_mac_addr)); + }else { +/* Check command line */ + argptr =prom_getcmdline (); +if ((pmac =strstr (argptr,"ethaddr=" )) ==NULL ) { +printk (KERN_INFO "%s: No mac address found\n" , + ndev->name); +/* use the hard coded mac addresses */ + }else { +str2eaddr (ethaddr, pmac +strlen ("ethaddr=" )); +memcpy (au1000_mac_addr, ethaddr, +sizeof (au1000_mac_addr)); + } } } + aup->enable = (volatile u32 *) ((unsigned long ) macen_addr); +memcpy (ndev->dev_addr, au1000_mac_addr,sizeof (au1000_mac_addr));setup_hw_rings (aup,MAC0_RX_DMA_ADDR ,MAC0_TX_DMA_ADDR ); - }else if (port_num ==1 ) -setup_hw_rings (aup,MAC1_RX_DMA_ADDR ,MAC1_TX_DMA_ADDR ); + aup->mac_id =0 ; + au_macs[0 ] = aup; + } +else +if (port_num ==1 ) + { + aup->enable = (volatile u32 *) ((unsigned long ) macen_addr); +memcpy (ndev->dev_addr, au1000_mac_addr,sizeof (au1000_mac_addr)); + ndev->dev_addr[5 ] +=0x01 ; -/* -* Assign to the Ethernet ports two consecutive MAC addresses -* to match those that are printed on their stickers -*/ -memcpy (dev->dev_addr, au1000_mac_addr,sizeof (au1000_mac_addr)); - dev->dev_addr[5 ] += port_num; +setup_hw_rings (aup,MAC1_RX_DMA_ADDR ,MAC1_TX_DMA_ADDR ); + aup->mac_id =1 ; + au_macs[1 ] = aup; + } +else + { +printk (KERN_ERR "%s: bad ioaddr\n" , ndev->name); + } *aup->enable =0 ; aup->mac_enabled =0 ; - aup->mii_bus.priv = dev; + aup->mii_bus.priv = ndev; aup->mii_bus.read = mdiobus_read; aup->mii_bus.write = mdiobus_write; aup->mii_bus.reset = mdiobus_reset;
@@ -733,8 +659,18 @@ # endif#endif mdiobus_register (&aup->mii_bus); -if (mii_probe (dev) !=0 ) { - goto err_out; +if (mii_probe (ndev) !=0 ) { +/* Hack, hack, hack! +* This is needed during resume... you'll get a "Call Trace" +* error message, but at least the wake up works... +* Feel free to post a patch. :) +* +* Rodolfo Giometti +* */ +if (!skip_prom) { + ret = -EBUSY ; + goto err_out; + } } pDBfree =NULL ;
@@ -752,6 +688,7 @@ #endiffor (i =0 ; i <NUM_RX_DMA ; i++) { pDB =GetFreeDB (aup);if (!pDB) { + ret = -ENOMEM ; goto err_out; } aup->rx_dma_ring[i]->buff_stat = (unsigned )pDB->dma_addr;
@@ -760,6 +697,7 @@ #endiffor (i =0 ; i <NUM_TX_DMA ; i++) { pDB =GetFreeDB (aup);if (!pDB) { + ret = -ENOMEM ; goto err_out; } aup->tx_dma_ring[i]->buff_stat = (unsigned )pDB->dma_addr;
@@ -767,31 +705,23 @@ #endif aup->tx_db_inuse[i] = pDB; } -spin_lock_init (&aup->lock); - dev->base_addr = base; - dev->irq = irq; - dev->open = au1000_open; - dev->hard_start_xmit = au1000_tx; - dev->stop = au1000_close; - dev->get_stats = au1000_get_stats; - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &au1000_ioctl; -SET_ETHTOOL_OPS (dev, &au1000_ethtool_ops); - dev->tx_timeout = au1000_tx_timeout; - dev->watchdog_timeo =ETH_TX_TIMEOUT ; +return 0 ; -/* -* The boot code uses the ethernet controller, so reset it to start -* fresh. au1000_init() expects that the device is in reset state. -*/ -reset_mac (dev); +err_out : +au1000_lowlevel_remove (ndev); +out : +return ret; +} -return dev; +static void +au1000_lowlevel_remove (struct net_device *ndev) +{ +struct au1000_private *aup = ndev->priv; +int i; -err_out:/* here we should have a valid dev plus aup-> register addresses * so we can reset the mac properly.*/ -reset_mac (dev); +reset_mac (ndev);for (i =0 ; i <NUM_RX_DMA ; i++) {if (aup->rx_db_inuse[i])
@@ -801,13 +731,10 @@ err_out:if (aup->tx_db_inuse[i])ReleaseDB (aup, aup->tx_db_inuse[i]); } -dma_free_noncoherent (NULL ,MAX_BUF_SIZE * (NUM_TX_BUFFS +NUM_RX_BUFFS ), - (void *)aup->vaddr, aup->dma_addr); -unregister_netdev (dev); -free_netdev (dev); -release_mem_region ( base,MAC_IOSIZE ); -release_mem_region (macen,4 ); -return NULL ; +dma_free_noncoherent (NULL , +MAX_BUF_SIZE * (NUM_TX_BUFFS +NUM_RX_BUFFS ), + (void *)aup->vaddr, + aup->dma_addr); }/*
@@ -1009,38 +936,15 @@ static int au1000_close(struct net_devicreturn 0 ; } -static void __exit au1000_cleanup_module(void) -{ -int i, j; -struct net_device *dev; -struct au1000_private *aup; - -for (i =0 ; i < num_ifs; i++) { - dev = iflist[i].dev; -if (dev) { - aup = (struct au1000_private *) dev->priv; -unregister_netdev (dev); -for (j =0 ; j <NUM_RX_DMA ; j++) -if (aup->rx_db_inuse[j]) -ReleaseDB (aup, aup->rx_db_inuse[j]); -for (j =0 ; j <NUM_TX_DMA ; j++) -if (aup->tx_db_inuse[j]) -ReleaseDB (aup, aup->tx_db_inuse[j]); -dma_free_noncoherent (NULL ,MAX_BUF_SIZE * - (NUM_TX_BUFFS +NUM_RX_BUFFS ), - (void *)aup->vaddr, aup->dma_addr); -release_mem_region (dev->base_addr,MAC_IOSIZE ); -release_mem_region (CPHYSADDR (iflist[i].macen_addr),4 ); -free_netdev (dev); - } - } -} - -static void update_tx_stats (struct net_device *dev,u32 status) +static inline void +update_tx_stats (struct net_device *dev,u32 status,u32 pkt_len) {struct au1000_private *aup = (struct au1000_private *) dev->priv;struct net_device_stats *ps = &aup->stats; + ps->tx_packets++; + ps->tx_bytes += pkt_len; +if (status &TX_FRAME_ABORTED ) {if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {if (status & (TX_JAB_TIMEOUT |TX_UNDERRUN )) {
@@ -1073,7 +977,7 @@ static void au1000_tx_ack(struct net_dev ptxd = aup->tx_dma_ring[aup->tx_tail];while (ptxd->buff_stat &TX_T_DONE ) { -update_tx_stats (dev, ptxd->status); +update_tx_stats (dev, ptxd->status, ptxd->len &0x3ff ); ptxd->buff_stat &= ~TX_T_DONE ; ptxd->len =0 ;au_sync ();
@@ -1095,7 +999,6 @@ static void au1000_tx_ack(struct net_devstatic int au1000_tx (struct sk_buff *skb,struct net_device *dev) {struct au1000_private *aup = (struct au1000_private *) dev->priv; -struct net_device_stats *ps = &aup->stats;volatile tx_dma_t *ptxd;u32 buff_stat;db_dest_t *pDB;
@@ -1115,7 +1018,7 @@ static int au1000_tx(struct sk_buff *skbreturn 1 ; }else if (buff_stat &TX_T_DONE ) { -update_tx_stats (dev, ptxd->status); +update_tx_stats (dev, ptxd->status, ptxd->len &0x3ff ); ptxd->len =0 ; }
@@ -1135,9 +1038,6 @@ static int au1000_tx(struct sk_buff *skbelse ptxd->len = skb->len; - ps->tx_packets++; - ps->tx_bytes += ptxd->len; - ptxd->buff_stat = pDB->dma_addr |TX_DMA_ENABLE ;au_sync ();dev_kfree_skb (skb);
@@ -1340,5 +1240,211 @@ static struct net_device_stats *au1000_greturn 0 ; } -module_init (au1000_init_module); -module_exit (au1000_cleanup_module); +/* +* Setup the base address and interupt of the Au1xxx ethernet macs +* based on cpu type and whether the interface is enabled in sys_pinfunc +* register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. +*/ +static int au1000_drv_probe (struct device *dev) +{ +struct platform_device *pdev =to_platform_device (dev); +struct net_device *ndev; +struct au1000_private *aup; +struct resource *res; +static unsigned version_printed =0 ; +u32 base_addr_phys; +void *base_addr, *macen_addr; +int irq, ret; + +/* Get the resource info */ + res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"eth-base" ); +if (!res) { + ret = -ENODEV ; + goto out; + } + base_addr_phys = res->start; + base_addr =ioremap (res->start, res->end - res->start); +if (!base_addr) { +printk (KERN_ERR "%s: unable to remap address %lx\n" , +DRV_NAME , (long unsigned int ) res->start); + ret = -EINVAL ; + goto out; + } + res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"eth-mac" ); +if (!res) { + ret = -ENODEV ; + goto out_release_io; + } + macen_addr =ioremap (res->start, res->end - res->start); +if (!macen_addr) { +printk (KERN_ERR "%s: unable to remap address %lx\n" , +DRV_NAME , (long unsigned int ) res->start); + ret = -ENOMEM ; + goto out_release_io; + } + res =platform_get_resource_byname (pdev,IORESOURCE_IRQ ,"eth-irq" ); +if (!res) { + ret = -ENODEV ; + goto out_release_iomac; + } + irq = res->start; + +if (version_printed++ ==0 ) +printk ("%s version %s %s\n" ,DRV_NAME ,DRV_VERSION ,DRV_AUTHOR ); + + ndev =alloc_etherdev (sizeof (struct au1000_private )); +if (!ndev) { +printk (KERN_ERR "%s: alloc etherdev failed\n" ,DRV_NAME ); + ret = -ENOMEM ; + goto out_release_iomac; + } +SET_MODULE_OWNER (ndev); +SET_NETDEV_DEV (ndev, dev); + +/* Force the device name to a know state... */ +sprintf (ndev->name,"au1xxx_eth(%d)" , pdev->id); + ret =au1000_lowlevel_probe (ndev, base_addr, macen_addr, pdev->id,0 ); +if (ret <0 ) { +printk (KERN_ERR "%s: low level probe failed\n" ,DRV_NAME ); + goto out_free_netdev; + } +/* ...and then came back to a more standard name. */ +strcpy (ndev->name,"eth%d" ); + + aup = ndev->priv; + +spin_lock_init (&aup->lock); + ndev->base_addr = base_addr_phys; + ndev->irq = irq; + ndev->open = au1000_open; + ndev->hard_start_xmit = au1000_tx; + ndev->stop = au1000_close; + ndev->get_stats = au1000_get_stats; + ndev->set_multicast_list = &set_rx_mode; + ndev->do_ioctl = &au1000_ioctl; +SET_ETHTOOL_OPS (ndev, &au1000_ethtool_ops); + ndev->tx_timeout = au1000_tx_timeout; + ndev->watchdog_timeo =ETH_TX_TIMEOUT ; + +/* +* The boot code uses the ethernet controller, so reset it to start +* fresh. au1000_init() expects that the device is in reset state. +*/ +reset_mac (ndev); + + ret =register_netdev (ndev); +if (ret) { +printk (KERN_ERR "%s: cannot register net device err %d\n" , +DRV_NAME , ret); + goto out_lowlevel_remove; + } + +printk ("%s: Au1x Ethernet found at 0x%x, irq %d\n" , + ndev->name, base_addr_phys, irq); + +dev_set_drvdata (dev, ndev); + +return 0 ; + +out_lowlevel_remove : +au1000_lowlevel_remove (ndev); +out_free_netdev : +free_netdev (ndev); +out_release_iomac : +iounmap (macen_addr); +out_release_io : +iounmap (base_addr); +out : +printk ("%s: not found (%d).\n" ,DRV_NAME , ret); + +return ret; +} + +static int au1000_drv_remove (struct device *dev) +{ +struct net_device *ndev =dev_get_drvdata (dev); + +dev_set_drvdata (dev,NULL ); + +unregister_netdev (ndev); +au1000_lowlevel_remove (ndev); +free_netdev (ndev); + +return 0 ; +} + +#ifdef CONFIG_PM +static int au1000_drv_suspend (struct device *dev,pm_message_t state) +{ +struct net_device *ndev =dev_get_drvdata (dev); +struct au1000_private *aup; +struct phy_device *phydev; + +if (!ndev) +return 0 ; + + aup = (struct au1000_private *) ndev->priv; + phydev = aup->phy_dev; + +if (netif_running (ndev)) +netif_device_detach (ndev); + +au1000_lowlevel_remove (ndev); + +return 0 ; +} + +static int au1000_drv_resume (struct device *dev) +{ +struct net_device *ndev =dev_get_drvdata (dev); +struct au1000_private *aup; +struct phy_device *phydev; +int ret; + +if (!ndev) +return 0 ; + + aup = (struct au1000_private *) ndev->priv; + phydev = aup->phy_dev; + + ret =au1000_lowlevel_probe (ndev, (void *) aup->mac, (void *) aup->enable, aup->mac_id, ~0 ); +if (ret <0 ) { +printk (KERN_ERR "%s: low level probe failed\n" ,DRV_NAME ); +return ret; + } + +/* au1000_init() expects that the device is in reset state. +*/ +reset_mac (ndev);/* au1000_init() expects the device in reset */ +au1000_init (ndev); + +if (netif_running (ndev)) +netif_device_attach (ndev); + +return 0 ; +} +#endif + +static struct device_driver au1000_driver = { + .name =DRV_NAME , + .bus = &platform_bus_type, + .probe = au1000_drv_probe, + .remove = au1000_drv_remove, +#ifdef CONFIG_PM + .suspend = au1000_drv_suspend, + .resume = au1000_drv_resume, +#endif +}; + +static int __init au1000_eth_init (void ) +{ +return driver_register (&au1000_driver); +} + +static void __exit au1000_eth_cleanup(void) +{ +driver_unregister (&au1000_driver); +} + +module_init (au1000_eth_init); +module_exit (au1000_eth_cleanup);
Quoted 5 lines · Rodolfo Giometti
The first strange thing is that this time the kernel messages stop after "
au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..." as before the merge! Maybe something as changed in serial console magement?
Yes, something as changed... here the patch to remove the problem.
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 6d295c7..10bf859 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -86,7 +86,9 @@ static int suspend_prepare(suspend_state
goto Thaw;
}
+#ifndef CONFIG_DEBUG_KERNEL
suspend_console();
+#endif
if ((error = device_suspend(PMSG_SUSPEND))) {
printk(KERN_ERR "Some devices failed to suspend\n");
goto Finish;I'd like also sending this patch to the Linux main tree, where should I send it? I found nothing useful in MAINTAINERS file... :-o
Ciao,
Rodolfo
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
Quoted 22 lines · Rodolfo Giometti
Quoted 4 lines
The first strange thing is that this time the kernel messages stop after "
au1xxx_pm_prepare: state = 3" and not after "au_sleep: Zzz..." as before the merge! Maybe something as changed in serial console magement?Yes, something as changed... here the patch to remove the problem.
diff --git a/kernel/power/main.c b/kernel/power/main.c index 6d295c7..10bf859 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -86,7 +86,9 @@ static int suspend_prepare(suspend_state goto Thaw; } +#ifndef CONFIG_DEBUG_KERNEL suspend_console(); +#endif if ((error = device_suspend(PMSG_SUSPEND))) { printk(KERN_ERR "Some devices failed to suspend\n"); goto Finish;
Quoted 2 lines
I'd like also sending this patch to the Linux main tree, where should I send it? I found nothing useful in
MAINTAINERSfile... :-o
You missed the last entry in MAINTAINERS ;-) Send such stuff to [email protected].
Ralf
PATCH 1/1 au1000_eth.c power management and driver registration support
In reply to Rodolfo GiomettiHello,
Attached you can find my patch to add power managament and driver registration to the new version of file "drivers/net/au1000_eth.c" that implements the PHY-layer support.
Ciao,
Rodolfo Giometti
Signature · 4 lines
GNU/Linux Solutions e-mail: [email protected] Linux Device Driver [email protected] Embedded Systems [email protected] UNIX programming phone: +39 349 2432127
arch/mips/au1000/common/au1xxx_irqmap.c +2 -2
@@ -117,7 +117,7 @@ #elif defined(CONFIG_SOC_AU1500) { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
@@ -151,7 +151,7 @@ #elif defined(CONFIG_SOC_AU1100) { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},/*{ AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0},*/ { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
arch/mips/au1000/common/platform.c +79 -0
92 lines not on this page · raw message
drivers/net/Kconfig +2 -2
@@ -453,13 +453,13 @@ config MIPS_GT96100ETH Say Y here to support the Ethernet subsystem on your GT96100 card. config MIPS_AU1X00_ENET - bool "MIPS AU1000 Ethernet support" + tristate "MIPS AU1000 Ethernet support" depends on NET_ETHERNET && SOC_AU1X00 select PHYLIB select CRC32 help If you have an Alchemy Semi AU1X00 based system - say Y. Otherwise, say N. + say Y or M. Otherwise, say N. config SGI_IOC3_ETH bool "SGI IOC3 Ethernet"
drivers/net/au1000_eth.c +324 -215
658 lines not on this page · raw message
drivers/net/au1000_eth.h +0 -1
@@ -27,7 +27,6 @@*/ -#define MAC_IOSIZE 0x10000#define NUM_RX_DMA 4/* Au1x00 has 4 rx hardware descriptors */ #define NUM_TX_DMA 4/* Au1x00 has 4 tx hardware descriptors */
include/asm-mips/mach-au1x00/au1000.h +24 -23
95 lines not on this page · raw message