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.");
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)
{
pr_err("phy(%d) write timeout : %d\n", phy, reg);
}
-static int
-jme_phyext_read(struct jme_adapter *jme, int reg)
-{
- jme_mdio_write(jme->dev, jme->mii_if.phy_id,
- JME_PHY_SPEC_ADDR_REG,
- JME_PHY_SPEC_REG_READ | (reg & 0x3FFF));
- return jme_mdio_read(jme->dev, jme->mii_if.phy_id,
- JME_PHY_SPEC_DATA_REG);
-}
-
-static void
-jme_phyext_write(struct jme_adapter *jme, int reg, int val)
-{
- jme_mdio_write(jme->dev, jme->mii_if.phy_id,
- JME_PHY_SPEC_DATA_REG, val);
- jme_mdio_write(jme->dev, jme->mii_if.phy_id,
- JME_PHY_SPEC_ADDR_REG,
- JME_PHY_SPEC_REG_WRITE | (reg & 0x3FFF));
-}
-
-static void
-jme_phyext_memcpy(struct jme_adapter *jme, u32 *p, int reg_nr)
-{
- int i;
- u16 *p16 = (u16 *)p;
-
- for (i = 0 ; i < reg_nr ; ++i)
- p16[i] = jme_phyext_read(jme, i);
-}
-
static inline void
jme_reset_phy_processor(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)
{
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)
{
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;
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);
* Disable interrupt
*/
jwrite32f(jme, JME_IENC, INTR_ENABLE);
-
+
if (intrstat & (INTR_LINKCH | INTR_SWINTR)) {
/*
* Link change event is critical
pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
}
-static inline void
-jme_recal_phy(struct jme_adapter *jme)
-{
- u32 miictl1000, comm2;
-
- miictl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
- miictl1000 &= ~JME_PHY_GCTRL_TESTMASK;
- miictl1000 |= JME_PHY_GCTRL_TESTMODE1;
- jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, miictl1000);
-
- comm2 = jme_phyext_read(jme, JME_PHYEXT_COMM2);
- comm2 &= ~(0x0001u);
- comm2 |= 0x0011u;
- jme_phyext_write(jme, JME_PHYEXT_COMM2, comm2);
-
- mdelay(20);
-
- comm2 = jme_phyext_read(jme, JME_PHYEXT_COMM2);
- comm2 &= ~(0x0013u);
- jme_phyext_write(jme, JME_PHYEXT_COMM2, comm2);
-
- miictl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
- miictl1000 &= ~JME_PHY_GCTRL_TESTMASK;
- jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, miictl1000);
-}
-
-static inline void
-jme_set_phyparm(struct jme_adapter *jme, u32 val)
-{
- u32 comm0, comm1;
-
- comm0 = jme_phyext_read(jme, JME_PHYEXT_COMM0);
- comm1 = jme_phyext_read(jme, JME_PHYEXT_COMM1);
- comm0 &= ~(0xE000u);
- comm0 |= ((val << 13) & 0xE000u);
- comm1 &= ~(0x0001u);
- comm1 |= ((val >> 3) & 0x0001u);
- jme_phyext_write(jme, JME_PHYEXT_COMM0, comm0);
- jme_phyext_write(jme, JME_PHYEXT_COMM1, comm1);
-}
-
-static inline void
-jme_refill_phyparm(struct jme_adapter *jme)
-{
- if (jme->chip_main_rev >= 6 ||
- (jme->chip_main_rev == 5 &&
- (jme->chip_sub_rev == 0 ||
- jme->chip_sub_rev == 1 ||
- jme->chip_sub_rev == 3))) {
- jme_set_phyparm(jme, 0x8);
- } else if (jme->chip_main_rev == 3 &&
- (jme->chip_sub_rev == 1 ||
- jme->chip_sub_rev == 2)) {
- jme_set_phyparm(jme, 0x7);
- } else if (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260 &&
- jme->chip_main_rev == 2) {
- if (jme->chip_sub_rev == 0)
- jme_set_phyparm(jme, 0x3);
- else if (jme->chip_sub_rev == 2)
- jme_set_phyparm(jme, 0x2);
- }
-}
-
static inline void
jme_phy_on(struct jme_adapter *jme)
{
u32 bmcr;
- if (new_phy_power_ctrl(jme->chip_main_rev))
- jme_new_phy_on(jme);
-
bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
bmcr &= ~BMCR_PDOWN;
jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
- jme_recal_phy(jme);
- jme_refill_phyparm(jme);
+ if (new_phy_power_ctrl(jme->chip_main_rev))
+ jme_new_phy_on(jme);
}
static inline void
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);
p32 += 0x100 >> 2;
mdio_memcpy(jme, p32, JME_PHY_REG_NR);
-
- p32 += 0x100 >> 2;
- jme_phyext_memcpy(jme, p32, JME_PHY_SPEC_REG_NR);
}
static int
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;
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);
struct jme_adapter *jme;
u16 bmcr, bmsr;
u32 apmc;
-
+
/*
* set up PCI device basics
*/
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;
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;
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);
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) ?
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);
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);
#endif
pci_set_power_state(pdev, PCI_D3hot);
+ jme->mc_count = 0;
+ jme->flag_media_connected = false;
return 0;
}