Commit 51df1901 authored by Simon Horman's avatar Simon Horman
Browse files
parents 4a031b0e 23197916
Loading
Loading
Loading
Loading
+78 −23
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@

#define DRV_MODULE_NAME		"tg3"
#define PFX DRV_MODULE_NAME	": "
#define DRV_MODULE_VERSION	"3.93"
#define DRV_MODULE_RELDATE	"May 22, 2008"
#define DRV_MODULE_VERSION	"3.94"
#define DRV_MODULE_RELDATE	"August 14, 2008"

#define TG3_DEF_MAC_MODE	0
#define TG3_DEF_RX_MODE		0
@@ -536,6 +536,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
		return 0;

	switch (locknum) {
		case TG3_APE_LOCK_GRC:
		case TG3_APE_LOCK_MEM:
			break;
		default:
@@ -573,6 +574,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
		return;

	switch (locknum) {
		case TG3_APE_LOCK_GRC:
		case TG3_APE_LOCK_MEM:
			break;
		default:
@@ -1017,16 +1019,44 @@ static void tg3_mdio_fini(struct tg3 *tp)
	}
}

/* tp->lock is held. */
static inline void tg3_generate_fw_event(struct tg3 *tp)
{
	u32 val;

	val = tr32(GRC_RX_CPU_EVENT);
	val |= GRC_RX_CPU_DRIVER_EVENT;
	tw32_f(GRC_RX_CPU_EVENT, val);

	tp->last_event_jiffies = jiffies;
}

#define TG3_FW_EVENT_TIMEOUT_USEC 2500

/* tp->lock is held. */
static void tg3_wait_for_event_ack(struct tg3 *tp)
{
	int i;
	unsigned int delay_cnt;
	long time_remain;

	/* If enough time has passed, no wait is necessary. */
	time_remain = (long)(tp->last_event_jiffies + 1 +
		      usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
		      (long)jiffies;
	if (time_remain < 0)
		return;

	/* Wait for up to 2.5 milliseconds */
	for (i = 0; i < 250000; i++) {
	/* Check if we can shorten the wait time. */
	delay_cnt = jiffies_to_usecs(time_remain);
	if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
		delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
	delay_cnt = (delay_cnt >> 3) + 1;

	for (i = 0; i < delay_cnt; i++) {
		if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
			break;
		udelay(10);
		udelay(8);
	}
}

@@ -1075,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp)
		val = 0;
	tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);

	val = tr32(GRC_RX_CPU_EVENT);
	val |= GRC_RX_CPU_DRIVER_EVENT;
	tw32_f(GRC_RX_CPU_EVENT, val);
	tg3_generate_fw_event(tp);
}

static void tg3_link_report(struct tg3 *tp)
@@ -2124,6 +2152,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))
			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;

		if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
			mac_mode |= tp->mac_mode &
				    (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
			if (mac_mode & MAC_MODE_APE_TX_EN)
				mac_mode |= MAC_MODE_TDE_ENABLE;
		}

		tw32_f(MAC_MODE, mac_mode);
		udelay(100);

@@ -5493,7 +5528,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event)
		return;

	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
	if (apedata != APE_FW_STATUS_READY)
	if (!(apedata & APE_FW_STATUS_READY))
		return;

	/* Wait for up to 1 millisecond for APE to service previous event. */
@@ -5760,6 +5795,8 @@ static int tg3_chip_reset(struct tg3 *tp)

	tg3_mdio_stop(tp);

	tg3_ape_lock(tp, TG3_APE_LOCK_GRC);

	/* No matching tg3_nvram_unlock() after this because
	 * chip reset below will undo the nvram lock.
	 */
@@ -5908,12 +5945,19 @@ static int tg3_chip_reset(struct tg3 *tp)
	} else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
		tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
		tw32_f(MAC_MODE, tp->mac_mode);
	} else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
		tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
		if (tp->mac_mode & MAC_MODE_APE_TX_EN)
			tp->mac_mode |= MAC_MODE_TDE_ENABLE;
		tw32_f(MAC_MODE, tp->mac_mode);
	} else
		tw32_f(MAC_MODE, 0);
	udelay(40);

	tg3_mdio_start(tp);

	tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);

	err = tg3_poll_fw(tp);
	if (err)
		return err;
@@ -5935,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp)
		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
			tp->last_event_jiffies = jiffies;
			if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
		}
@@ -5948,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp)
{
	if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
	   !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
		u32 val;

		/* Wait for RX cpu to ACK the previous event. */
		tg3_wait_for_event_ack(tp);

		tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
		val = tr32(GRC_RX_CPU_EVENT);
		val |= GRC_RX_CPU_DRIVER_EVENT;
		tw32(GRC_RX_CPU_EVENT, val);

		tg3_generate_fw_event(tp);

		/* Wait for RX cpu to ACK this event. */
		tg3_wait_for_event_ack(tp);
@@ -7406,7 +7448,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
		udelay(10);
	}

	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
		tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
	else
		tp->mac_mode = 0;
	tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
@@ -7840,9 +7886,8 @@ static void tg3_timer(unsigned long __opaque)
	 * resets.
	 */
	if (!--tp->asf_counter) {
		if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
			u32 val;

		if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
		    !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
			tg3_wait_for_event_ack(tp);

			tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
@@ -7850,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque)
			tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
			/* 5 seconds timeout */
			tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
			val = tr32(GRC_RX_CPU_EVENT);
			val |= GRC_RX_CPU_DRIVER_EVENT;
			tw32_f(GRC_RX_CPU_EVENT, val);

			tg3_generate_fw_event(tp);
		}
		tp->asf_counter = tp->asf_multiplier;
	}
@@ -8422,6 +8466,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val)
	return ret;
}

static inline u64 get_estat64(tg3_stat64_t *val)
{
       return ((u64)val->high << 32) | ((u64)val->low);
}

static unsigned long calc_crc_errors(struct tg3 *tp)
{
	struct tg3_hw_stats *hw_stats = tp->hw_stats;
@@ -8450,7 +8499,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)

#define ESTAT_ADD(member) \
	estats->member =	old_estats->member + \
				get_stat64(&hw_stats->member)
				get_estat64(&hw_stats->member)

static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
{
@@ -12416,6 +12465,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
				       tp->misc_host_ctrl);
	}

	/* Preserve the APE MAC_MODE bits */
	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
		tp->mac_mode = tr32(MAC_MODE) |
			       MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
	else
		tp->mac_mode = TG3_DEF_MAC_MODE;

	/* these are limited to 10/100 only */
	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
	     (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -13275,7 +13331,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
	tp->pdev = pdev;
	tp->dev = dev;
	tp->pm_cap = pm_cap;
	tp->mac_mode = TG3_DEF_MAC_MODE;
	tp->rx_mode = TG3_DEF_RX_MODE;
	tp->tx_mode = TG3_DEF_TX_MODE;

+6 −0
Original line number Diff line number Diff line
@@ -325,6 +325,8 @@
#define  MAC_MODE_TDE_ENABLE		 0x00200000
#define  MAC_MODE_RDE_ENABLE		 0x00400000
#define  MAC_MODE_FHDE_ENABLE		 0x00800000
#define  MAC_MODE_APE_RX_EN		 0x08000000
#define  MAC_MODE_APE_TX_EN		 0x10000000
#define MAC_STATUS			0x00000404
#define  MAC_STATUS_PCS_SYNCED		 0x00000001
#define  MAC_STATUS_SIGNAL_DET		 0x00000002
@@ -1889,6 +1891,7 @@
#define  APE_EVENT_STATUS_EVENT_PENDING	 0x80000000

/* APE convenience enumerations. */
#define TG3_APE_LOCK_GRC                1
#define TG3_APE_LOCK_MEM                4

#define TG3_EEPROM_SB_F1R2_MBA_OFF	0x10
@@ -2429,7 +2432,10 @@ struct tg3 {
	struct tg3_ethtool_stats	estats;
	struct tg3_ethtool_stats	estats_prev;

	union {
	unsigned long			phy_crc_errors;
	unsigned long			last_event_jiffies;
	};

	u32				rx_offset;
	u32				tg3_flags;
+2 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
						 struct net_device *dev,
						 int strict);

extern int			ipv6_dev_get_saddr(struct net_device *dev, 
extern int			ipv6_dev_get_saddr(struct net *net,
					       struct net_device *dev,
					       const struct in6_addr *daddr,
					       unsigned int srcprefs,
					       struct in6_addr *saddr);
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ struct rt6_rtnl_dump_arg
{
	struct sk_buff *skb;
	struct netlink_callback *cb;
	struct net *net;
};

extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
+70 −6
Original line number Diff line number Diff line
@@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
	return 0;
}

static void rt_secret_reschedule(int old)
{
	struct net *net;
	int new = ip_rt_secret_interval;
	int diff = new - old;

	if (!diff)
		return;

	rtnl_lock();
	for_each_net(net) {
		int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);

		if (!new)
			continue;

		if (deleted) {
			long time = net->ipv4.rt_secret_timer.expires - jiffies;

			if (time <= 0 || (time += diff) <= 0)
				time = 0;

			net->ipv4.rt_secret_timer.expires = time;
		} else
			net->ipv4.rt_secret_timer.expires = new;

		net->ipv4.rt_secret_timer.expires += jiffies;
		add_timer(&net->ipv4.rt_secret_timer);
	}
	rtnl_unlock();
}

static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
					  struct file *filp,
					  void __user *buffer, size_t *lenp,
					  loff_t *ppos)
{
	int old = ip_rt_secret_interval;
	int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos);

	rt_secret_reschedule(old);

	return ret;
}

static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
						   int __user *name,
						   int nlen,
						   void __user *oldval,
						   size_t __user *oldlenp,
						   void __user *newval,
						   size_t newlen)
{
	int old = ip_rt_secret_interval;
	int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval,
				 newlen);

	rt_secret_reschedule(old);

	return ret;
}

static ctl_table ipv4_route_table[] = {
	{
		.ctl_name	= NET_IPV4_ROUTE_GC_THRESH,
@@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = {
		.data		= &ip_rt_secret_interval,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_jiffies,
		.strategy	= &sysctl_jiffies,
		.proc_handler	= &ipv4_sysctl_rt_secret_interval,
		.strategy	= &ipv4_sysctl_rt_secret_interval_strategy,
	},
	{ .ctl_name = 0 }
};
@@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net)
	net->ipv4.rt_secret_timer.data = (unsigned long)net;
	init_timer_deferrable(&net->ipv4.rt_secret_timer);

	if (ip_rt_secret_interval) {
		net->ipv4.rt_secret_timer.expires =
			jiffies + net_random() % ip_rt_secret_interval +
			ip_rt_secret_interval;
		add_timer(&net->ipv4.rt_secret_timer);
	}
	return 0;
}

Loading