diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2009-02-12 00:03:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 02:13:25 -0500 |
commit | 38c845c7648ee354fd1d2fb8a7fbc352f2d3dcc3 (patch) | |
tree | aa55b7d582dadb2735079f92f7fe246069647ae7 /drivers/net/igb | |
parent | d24fff22d8dba13cc21034144f68f213415cb7c8 (diff) |
igb: access to NIC time
Adds the register definitions and code to read the time
register.
Signed-off-by: John Ronciak <john.ronciak@intel.com>
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb')
-rw-r--r-- | drivers/net/igb/e1000_regs.h | 28 | ||||
-rw-r--r-- | drivers/net/igb/igb.h | 4 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 111 |
3 files changed, 143 insertions, 0 deletions
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index 5038b73c78e9..64d95cd71f2e 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h | |||
@@ -75,6 +75,34 @@ | |||
75 | #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ | 75 | #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ |
76 | #define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) | 76 | #define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) |
77 | #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ | 77 | #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ |
78 | |||
79 | /* IEEE 1588 TIMESYNCH */ | ||
80 | #define E1000_TSYNCTXCTL 0x0B614 | ||
81 | #define E1000_TSYNCRXCTL 0x0B620 | ||
82 | #define E1000_TSYNCRXCFG 0x05F50 | ||
83 | |||
84 | #define E1000_SYSTIML 0x0B600 | ||
85 | #define E1000_SYSTIMH 0x0B604 | ||
86 | #define E1000_TIMINCA 0x0B608 | ||
87 | |||
88 | #define E1000_RXMTRL 0x0B634 | ||
89 | #define E1000_RXSTMPL 0x0B624 | ||
90 | #define E1000_RXSTMPH 0x0B628 | ||
91 | #define E1000_RXSATRL 0x0B62C | ||
92 | #define E1000_RXSATRH 0x0B630 | ||
93 | |||
94 | #define E1000_TXSTMPL 0x0B618 | ||
95 | #define E1000_TXSTMPH 0x0B61C | ||
96 | |||
97 | #define E1000_ETQF0 0x05CB0 | ||
98 | #define E1000_ETQF1 0x05CB4 | ||
99 | #define E1000_ETQF2 0x05CB8 | ||
100 | #define E1000_ETQF3 0x05CBC | ||
101 | #define E1000_ETQF4 0x05CC0 | ||
102 | #define E1000_ETQF5 0x05CC4 | ||
103 | #define E1000_ETQF6 0x05CC8 | ||
104 | #define E1000_ETQF7 0x05CCC | ||
105 | |||
78 | /* Split and Replication RX Control - RW */ | 106 | /* Split and Replication RX Control - RW */ |
79 | /* | 107 | /* |
80 | * Convenience macros | 108 | * Convenience macros |
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index e507449b3cc2..797a9fe107ad 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "e1000_mac.h" | 34 | #include "e1000_mac.h" |
35 | #include "e1000_82575.h" | 35 | #include "e1000_82575.h" |
36 | 36 | ||
37 | #include <linux/clocksource.h> | ||
38 | |||
37 | struct igb_adapter; | 39 | struct igb_adapter; |
38 | 40 | ||
39 | /* Interrupt defines */ | 41 | /* Interrupt defines */ |
@@ -251,6 +253,8 @@ struct igb_adapter { | |||
251 | struct napi_struct napi; | 253 | struct napi_struct napi; |
252 | struct pci_dev *pdev; | 254 | struct pci_dev *pdev; |
253 | struct net_device_stats net_stats; | 255 | struct net_device_stats net_stats; |
256 | struct cyclecounter cycles; | ||
257 | struct timecounter clock; | ||
254 | 258 | ||
255 | /* structs defined in e1000_hw.h */ | 259 | /* structs defined in e1000_hw.h */ |
256 | struct e1000_hw hw; | 260 | struct e1000_hw hw; |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f8c2919bcec0..8b2ba4245090 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -175,6 +175,54 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); | |||
175 | MODULE_LICENSE("GPL"); | 175 | MODULE_LICENSE("GPL"); |
176 | MODULE_VERSION(DRV_VERSION); | 176 | MODULE_VERSION(DRV_VERSION); |
177 | 177 | ||
178 | /** | ||
179 | * Scale the NIC clock cycle by a large factor so that | ||
180 | * relatively small clock corrections can be added or | ||
181 | * substracted at each clock tick. The drawbacks of a | ||
182 | * large factor are a) that the clock register overflows | ||
183 | * more quickly (not such a big deal) and b) that the | ||
184 | * increment per tick has to fit into 24 bits. | ||
185 | * | ||
186 | * Note that | ||
187 | * TIMINCA = IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * | ||
188 | * IGB_TSYNC_SCALE | ||
189 | * TIMINCA += TIMINCA * adjustment [ppm] / 1e9 | ||
190 | * | ||
191 | * The base scale factor is intentionally a power of two | ||
192 | * so that the division in %struct timecounter can be done with | ||
193 | * a shift. | ||
194 | */ | ||
195 | #define IGB_TSYNC_SHIFT (19) | ||
196 | #define IGB_TSYNC_SCALE (1<<IGB_TSYNC_SHIFT) | ||
197 | |||
198 | /** | ||
199 | * The duration of one clock cycle of the NIC. | ||
200 | * | ||
201 | * @todo This hard-coded value is part of the specification and might change | ||
202 | * in future hardware revisions. Add revision check. | ||
203 | */ | ||
204 | #define IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS 16 | ||
205 | |||
206 | #if (IGB_TSYNC_SCALE * IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS) >= (1<<24) | ||
207 | # error IGB_TSYNC_SCALE and/or IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS are too large to fit into TIMINCA | ||
208 | #endif | ||
209 | |||
210 | /** | ||
211 | * igb_read_clock - read raw cycle counter (to be used by time counter) | ||
212 | */ | ||
213 | static cycle_t igb_read_clock(const struct cyclecounter *tc) | ||
214 | { | ||
215 | struct igb_adapter *adapter = | ||
216 | container_of(tc, struct igb_adapter, cycles); | ||
217 | struct e1000_hw *hw = &adapter->hw; | ||
218 | u64 stamp; | ||
219 | |||
220 | stamp = rd32(E1000_SYSTIML); | ||
221 | stamp |= (u64)rd32(E1000_SYSTIMH) << 32ULL; | ||
222 | |||
223 | return stamp; | ||
224 | } | ||
225 | |||
178 | #ifdef DEBUG | 226 | #ifdef DEBUG |
179 | /** | 227 | /** |
180 | * igb_get_hw_dev_name - return device name string | 228 | * igb_get_hw_dev_name - return device name string |
@@ -185,6 +233,29 @@ char *igb_get_hw_dev_name(struct e1000_hw *hw) | |||
185 | struct igb_adapter *adapter = hw->back; | 233 | struct igb_adapter *adapter = hw->back; |
186 | return adapter->netdev->name; | 234 | return adapter->netdev->name; |
187 | } | 235 | } |
236 | |||
237 | /** | ||
238 | * igb_get_time_str - format current NIC and system time as string | ||
239 | */ | ||
240 | static char *igb_get_time_str(struct igb_adapter *adapter, | ||
241 | char buffer[160]) | ||
242 | { | ||
243 | cycle_t hw = adapter->cycles.read(&adapter->cycles); | ||
244 | struct timespec nic = ns_to_timespec(timecounter_read(&adapter->clock)); | ||
245 | struct timespec sys; | ||
246 | struct timespec delta; | ||
247 | getnstimeofday(&sys); | ||
248 | |||
249 | delta = timespec_sub(nic, sys); | ||
250 | |||
251 | sprintf(buffer, | ||
252 | "NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns", | ||
253 | (long)nic.tv_sec, nic.tv_nsec, | ||
254 | (long)sys.tv_sec, sys.tv_nsec, | ||
255 | (long)delta.tv_sec, delta.tv_nsec); | ||
256 | |||
257 | return buffer; | ||
258 | } | ||
188 | #endif | 259 | #endif |
189 | 260 | ||
190 | /** | 261 | /** |
@@ -1298,6 +1369,46 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
1298 | } | 1369 | } |
1299 | #endif | 1370 | #endif |
1300 | 1371 | ||
1372 | /* | ||
1373 | * Initialize hardware timer: we keep it running just in case | ||
1374 | * that some program needs it later on. | ||
1375 | */ | ||
1376 | memset(&adapter->cycles, 0, sizeof(adapter->cycles)); | ||
1377 | adapter->cycles.read = igb_read_clock; | ||
1378 | adapter->cycles.mask = CLOCKSOURCE_MASK(64); | ||
1379 | adapter->cycles.mult = 1; | ||
1380 | adapter->cycles.shift = IGB_TSYNC_SHIFT; | ||
1381 | wr32(E1000_TIMINCA, | ||
1382 | (1<<24) | | ||
1383 | IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE); | ||
1384 | #if 0 | ||
1385 | /* | ||
1386 | * Avoid rollover while we initialize by resetting the time counter. | ||
1387 | */ | ||
1388 | wr32(E1000_SYSTIML, 0x00000000); | ||
1389 | wr32(E1000_SYSTIMH, 0x00000000); | ||
1390 | #else | ||
1391 | /* | ||
1392 | * Set registers so that rollover occurs soon to test this. | ||
1393 | */ | ||
1394 | wr32(E1000_SYSTIML, 0x00000000); | ||
1395 | wr32(E1000_SYSTIMH, 0xFF800000); | ||
1396 | #endif | ||
1397 | wrfl(); | ||
1398 | timecounter_init(&adapter->clock, | ||
1399 | &adapter->cycles, | ||
1400 | ktime_to_ns(ktime_get_real())); | ||
1401 | |||
1402 | #ifdef DEBUG | ||
1403 | { | ||
1404 | char buffer[160]; | ||
1405 | printk(KERN_DEBUG | ||
1406 | "igb: %s: hw %p initialized timer\n", | ||
1407 | igb_get_time_str(adapter, buffer), | ||
1408 | &adapter->hw); | ||
1409 | } | ||
1410 | #endif | ||
1411 | |||
1301 | dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); | 1412 | dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); |
1302 | /* print bus type/speed/width info */ | 1413 | /* print bus type/speed/width info */ |
1303 | dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", | 1414 | dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", |