diff options
Diffstat (limited to 'drivers/net/igb/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 111 |
1 files changed, 111 insertions, 0 deletions
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", |