X-Git-Url: http://bbs.cooldavid.org/git/?p=jme.git;a=blobdiff_plain;f=jme.c;h=b79913e815802b0c70c068991482864226531022;hp=b883dc2b37444bbab642ee4f89c70713b863ffa9;hb=refs%2Fheads%2Fautodown;hpb=93f698ca5feb41915ba04c51b92a8f1e8cba1e1f diff --git a/jme.c b/jme.c index b883dc2..b79913e 100644 --- a/jme.c +++ b/jme.c @@ -50,6 +50,7 @@ static int force_pseudohp = -1; static int no_pseudohp = -1; static int no_extplug = -1; +static int delay_time = 11; module_param(force_pseudohp, int, 0); MODULE_PARM_DESC(force_pseudohp, "Enable pseudo hot-plug feature manually by driver instead of BIOS."); @@ -58,7 +59,10 @@ MODULE_PARM_DESC(no_pseudohp, "Disable pseudo hot-plug feature."); module_param(no_extplug, int, 0); MODULE_PARM_DESC(no_extplug, "Do not use external plug signal for pseudo hot-plug."); - +module_param(delay_time, uint, 0); +MODULE_PARM_DESC(delay_time, + "Seconds to delay before switching lower speed; default = 11 seconds(3 trials)"); + static int jme_mdio_read(struct net_device *netdev, int phy, int reg) { @@ -406,12 +410,14 @@ jme_linkstat_from_phy(struct jme_adapter *jme) return phylink; } +/* setting as RMII mode ??*/ static inline void jme_set_phyfifo_5level(struct jme_adapter *jme) { jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004); } +/* setting MII mode ??*/ static inline void jme_set_phyfifo_8level(struct jme_adapter *jme) { @@ -1298,6 +1304,122 @@ jme_stop_shutdown_timer(struct jme_adapter *jme) jwrite32f(jme, JME_APMC, apmc); } + +static void +jme_set_physpeed_capability(struct jme_adapter *jme,u16 speed) +{ + u32 advert, advert2; + + spin_lock_bh(&jme->phy_lock); + if (speed == SPEED_1000){ + advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + advert2 = (advert2|ADVERTISE_1000HALF|ADVERTISE_1000FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2); + advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); + advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert); + }else if (speed == SPEED_100){ + advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2); + advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); + advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert); + }else{ + advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2); + advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); + advert = advert & ~(ADVERTISE_100HALF|ADVERTISE_100FULL); + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert); + } + spin_unlock_bh(&jme->phy_lock); + return; +} + +/* PHY reg: MII_FCSCOUNTER is read and clear, we have to continuing read until RJ45 is attached, then cache this result. */ +static int +jme_check_ANcomplete(struct jme_adapter *jme) +{ + u32 val; + + val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_FCSCOUNTER); + return ((val&(PHY_SPEC_STATUS_AN_FAIL|PHY_SPEC_STATUS_AN_COMPLETE))==PHY_SPEC_STATUS_AN_COMPLETE) ? true : false; +} + +static int +jme_media_connected(struct jme_adapter *jme) +{ + if (jme->flag_media_connected == true) + return true; + + jme->flag_media_connected = jme_check_ANcomplete(jme); + + return jme->flag_media_connected; +} + +static void +asd_polling_func(unsigned long data) +{ + struct jme_adapter *jme = (struct jme_adapter *)data; + + /* + check condition term by term. + 1. link is up() ==> reset all thing, exit the process. + 2. there is no RJ45 cable attached. ==> do nothing but polling. + 3. RJ45 cable attached. but link is down ==> downspeed if the timeing is over 3.5 second. + */ + if (jme->flag_run_asd == true){ + printk("%s: run polling \n", __FUNCTION__ ); + if (jme_media_connected(jme)){ + jme->mc_count++; + printk("%s: pos1 mc_count=%d flag_media_connected=%d \n", \ + __FUNCTION__, jme->mc_count , jme->flag_media_connected); + if (jme->mc_count == (delay_time*3-5)){ + /* RJ45 is attached but unable to link anyway, it CANT + be resolved by speed, restore the capability */ + jme_set_physpeed_capability(jme,SPEED_1000); + jme->flag_media_connected = false; + jme->mc_count = 0; + }else if (jme->mc_count == (delay_time*2-5)){ + if (jme_check_ANcomplete(jme)) + jme_set_physpeed_capability(jme,SPEED_10); + else{ + jme->flag_media_connected = false; + jme->mc_count = 0; + } + }else if (jme->mc_count == delay_time-5){ + if (jme_check_ANcomplete(jme)) + jme_set_physpeed_capability(jme,SPEED_100); + else{ + jme->flag_media_connected = false; + jme->mc_count = 0; + } + } + } + mod_timer(&jme->asd_timer, jiffies+HZ); + return ; + } + +//out: + printk("%s stop polling \n", __FUNCTION__); + jme->flag_media_connected = false; + jme->mc_count = 0; + return; +} + +static int jme_check_linkup(struct jme_adapter *jme) +{ + u32 phylink; + + if (jme->fpgaver) + phylink = jme_linkstat_from_phy(jme); + else + phylink = jread32(jme, JME_PHY_LINK); + + return (phylink & PHY_LINK_UP)? true : false; +} + static void jme_link_change_tasklet(unsigned long arg) { @@ -1311,7 +1433,32 @@ jme_link_change_tasklet(unsigned long arg) while (atomic_read(&jme->link_changing) != 1) netif_info(jme, intr, jme->dev, "Waiting link change lock\n"); } - + printk("====== change_tasklet()=%d =======\n",jme->flag_run_asd); +// if (jme->chip_main_rev < 4 ){ + if (jme_check_linkup(jme)){ + if (jme->flag_run_asd){ + /* stop asd_polling_timer(); */ + printk("===stop asd_polling_timer()==\n"); + jme->flag_run_asd = false; + del_timer_sync(&jme->asd_timer); + } + } + else{ + if (!jme->flag_run_asd){ + printk("===start asd_polling_timer()==\n"); + /* start asd_polling_timer(); */ + jme_set_physpeed_capability(jme,SPEED_1000); + jme_check_ANcomplete(jme); /* clear PHY 0x13*/ + jme->flag_media_connected = false; + jme->flag_run_asd = true; + jme->mc_count = 0; + jme->asd_timer.expires = jiffies + 4*HZ; + jme->asd_timer.function = &asd_polling_func; + jme->asd_timer.data = (unsigned long)jme; + add_timer(&jme->asd_timer); + } + } +// } if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) goto out; @@ -1325,7 +1472,7 @@ jme_link_change_tasklet(unsigned long arg) tasklet_disable(&jme->rxclean_task); tasklet_disable(&jme->rxempty_task); - if (netif_carrier_ok(netdev)) { + if (netif_carrier_ok(netdev)) { jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); jme_reset_mac_processor(jme); @@ -1539,7 +1686,7 @@ jme_intr_msi(struct jme_adapter *jme, u32 intrstat) * Disable interrupt */ jwrite32f(jme, JME_IENC, INTR_ENABLE); - + if (intrstat & (INTR_LINKCH | INTR_SWINTR)) { /* * Link change event is critical @@ -1787,7 +1934,7 @@ jme_open(struct net_device *netdev) goto err_out; jme_start_irq(jme); - + jme_phy_on(jme); if (test_bit(JME_FLAG_SSET, &jme->flags)) jme_set_settings(netdev, &jme->old_ecmd); @@ -2686,9 +2833,10 @@ jme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) struct jme_adapter *jme = netdev_priv(netdev); struct mii_ioctl_data *mii_data = if_mii(rq); unsigned int duplex_chg; - + u16 val ; + if (cmd == SIOCSMIIREG) { - u16 val = mii_data->val_in; + val = mii_data->val_in; if (!(val & (BMCR_RESET|BMCR_ANENABLE)) && (val & BMCR_SPEED1000)) return -EINVAL; @@ -2697,7 +2845,7 @@ jme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) spin_lock_bh(&jme->phy_lock); rc = generic_mii_ioctl(&jme->mii_if, mii_data, cmd, &duplex_chg); spin_unlock_bh(&jme->phy_lock); - + if (!rc && (cmd == SIOCSMIIREG)) { if (duplex_chg) jme_reset_link(jme); @@ -3033,7 +3181,7 @@ jme_init_one(struct pci_dev *pdev, struct jme_adapter *jme; u16 bmcr, bmsr; u32 apmc; - + /* * set up PCI device basics */ @@ -3123,6 +3271,8 @@ jme_init_one(struct pci_dev *pdev, jme->msg_enable = JME_DEF_MSG_ENABLE; jme->regs = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + + if (!(jme->regs)) { pr_err("Mapping PCI resource region error\n"); rc = -ENOMEM; @@ -3166,7 +3316,8 @@ jme_init_one(struct pci_dev *pdev, tasklet_disable_nosync(&jme->linkch_task); tasklet_disable_nosync(&jme->txclean_task); tasklet_disable_nosync(&jme->rxclean_task); - tasklet_disable_nosync(&jme->rxempty_task); + tasklet_disable_nosync(&jme->rxempty_task); + jme->dpi.cur = PCC_P1; jme->reg_ghc = 0; @@ -3229,7 +3380,6 @@ jme_init_one(struct pci_dev *pdev, jme->mii_if.reg_num_mask = 0x1F; jme->mii_if.mdio_read = jme_mdio_read; jme->mii_if.mdio_write = jme_mdio_write; - jme_clear_pm(jme); jme_set_phyfifo_5level(jme); pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->pcirev); @@ -3247,18 +3397,22 @@ jme_init_one(struct pci_dev *pdev, goto err_out_unmap; } jme_load_macaddr(netdev); - + /* * Tell stack that we are not ready to work until open() */ netif_carrier_off(netdev); - rc = register_netdev(netdev); if (rc) { pr_err("Cannot register net device\n"); goto err_out_unmap; } - + + init_timer(&(jme->asd_timer)); + jme->mc_count = 0; + jme->flag_run_asd = false; + jme->flag_media_connected = false; + netif_info(jme, probe, jme->dev, "%s%s chipver:%x pcirev:%x " "macaddr: %02x:%02x:%02x:%02x:%02x:%02x\n", (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? @@ -3296,6 +3450,7 @@ jme_remove_one(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct jme_adapter *jme = netdev_priv(netdev); + del_timer_sync(&jme->asd_timer); /* Kill if running */ unregister_netdev(netdev); iounmap(jme->regs); pci_set_drvdata(pdev, NULL); @@ -3332,6 +3487,8 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) netif_stop_queue(netdev); jme_stop_irq(jme); +// del_timer_sync(&jme->asd_timer); /* Kill if running */ + tasklet_disable(&jme->txclean_task); tasklet_disable(&jme->rxclean_task); tasklet_disable(&jme->rxempty_task); @@ -3363,6 +3520,8 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) #endif pci_set_power_state(pdev, PCI_D3hot); + jme->mc_count = 0; + jme->flag_media_connected = false; return 0; }