]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.drivers/ixgbe-sfp.patch
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / ixgbe-sfp.patch
1 From: John Ronciak <john.ronciak@intel.com>
2 Subject: ixgbe driver update to add Longcove (SFP+) NIC support for FCoE needs
3 Acked-by: Karsten Keil <kkeil@novell.com>
4 Reference: bnc#442411
5
6
7 The patch that will be attached is to update the ixgbe driver to add SFP+ NIC
8 support to SLES11 beta4 version of the ixgbe driver. NIC have been sent to
9 Nurnberg for testing purposes. We have already been testing the patch with
10 both our test lab and in our FCoE testing.
11
12
13 ---
14 drivers/net/ixgbe/ixgbe.h | 5
15 drivers/net/ixgbe/ixgbe_82598.c | 161 ++++++++++++++++++++++++
16 drivers/net/ixgbe/ixgbe_main.c | 92 +++++++++++++-
17 drivers/net/ixgbe/ixgbe_phy.c | 258 ++++++++++++++++++++++++++++++++++++++++
18 drivers/net/ixgbe/ixgbe_phy.h | 18 ++
19 drivers/net/ixgbe/ixgbe_type.h | 19 ++
20 6 files changed, 546 insertions(+), 7 deletions(-)
21
22 --- a/drivers/net/ixgbe/ixgbe_82598.c
23 +++ b/drivers/net/ixgbe/ixgbe_82598.c
24 @@ -46,6 +46,8 @@ static s32 ixgbe_setup_copper_link_speed
25 ixgbe_link_speed speed,
26 bool autoneg,
27 bool autoneg_wait_to_complete);
28 +static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
29 + u8 *eeprom_data);
30
31 /**
32 */
33 @@ -53,12 +55,35 @@ static s32 ixgbe_get_invariants_82598(st
34 {
35 struct ixgbe_mac_info *mac = &hw->mac;
36 struct ixgbe_phy_info *phy = &hw->phy;
37 + s32 ret_val = 0;
38 + u16 list_offset, data_offset;
39
40 /* Call PHY identify routine to get the phy type */
41 ixgbe_identify_phy_generic(hw);
42
43 /* PHY Init */
44 switch (phy->type) {
45 + case ixgbe_phy_nl:
46 + phy->ops.reset = &ixgbe_reset_phy_nl;
47 +
48 + /* Call SFP+ identify routine to get the SFP+ module type */
49 + ret_val = phy->ops.identify_sfp(hw);
50 + if (ret_val != 0)
51 + goto out;
52 + else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
53 + ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
54 + goto out;
55 + }
56 +
57 + /* Check to see if SFP+ module is supported */
58 + ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
59 + &list_offset,
60 + &data_offset);
61 + if (ret_val != 0) {
62 + ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
63 + goto out;
64 + }
65 + break;
66 case ixgbe_phy_tn:
67 phy->ops.check_link = &ixgbe_check_phy_link_tnx;
68 phy->ops.get_firmware_version =
69 @@ -82,7 +107,8 @@ static s32 ixgbe_get_invariants_82598(st
70 mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
71 mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
72
73 - return 0;
74 +out:
75 + return ret_val;
76 }
77
78 /**
79 @@ -191,7 +217,10 @@ static enum ixgbe_media_type ixgbe_get_m
80 case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
81 case IXGBE_DEV_ID_82598EB_CX4:
82 case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
83 + case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
84 + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
85 case IXGBE_DEV_ID_82598EB_XF_LR:
86 + case IXGBE_DEV_ID_82598EB_SFP_LOM:
87 media_type = ixgbe_media_type_fiber;
88 break;
89 case IXGBE_DEV_ID_82598AT:
90 @@ -399,6 +428,47 @@ static s32 ixgbe_check_mac_link_82598(st
91 {
92 u32 links_reg;
93 u32 i;
94 + u16 link_reg, adapt_comp_reg;
95 +
96 + /*
97 + * SERDES PHY requires us to read link status from register 0xC79F.
98 + * Bit 0 set indicates link is up/ready; clear indicates link down.
99 + * OxC00C is read to check that the XAUI lanes are active. Bit 0
100 + * clear indicates active; set indicates inactive.
101 + */
102 + if (hw->phy.type == ixgbe_phy_nl) {
103 + hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
104 + hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
105 + hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
106 + &adapt_comp_reg);
107 + if (link_up_wait_to_complete) {
108 + for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
109 + if ((link_reg & 1) &&
110 + ((adapt_comp_reg & 1) == 0)) {
111 + *link_up = true;
112 + break;
113 + } else {
114 + *link_up = false;
115 + }
116 + msleep(100);
117 + hw->phy.ops.read_reg(hw, 0xC79F,
118 + IXGBE_TWINAX_DEV,
119 + &link_reg);
120 + hw->phy.ops.read_reg(hw, 0xC00C,
121 + IXGBE_TWINAX_DEV,
122 + &adapt_comp_reg);
123 + }
124 + } else {
125 + if ((link_reg & 1) &&
126 + ((adapt_comp_reg & 1) == 0))
127 + *link_up = true;
128 + else
129 + *link_up = false;
130 + }
131 +
132 + if (*link_up == false)
133 + goto out;
134 + }
135
136 links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
137 if (link_up_wait_to_complete) {
138 @@ -424,6 +494,7 @@ static s32 ixgbe_check_mac_link_82598(st
139 else
140 *speed = IXGBE_LINK_SPEED_1GB_FULL;
141
142 +out:
143 return 0;
144 }
145
146 @@ -859,6 +930,69 @@ s32 ixgbe_write_analog_reg8_82598(struct
147 }
148
149 /**
150 + * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit EEPROM word of an SFP+ module
151 + * over I2C interface through an intermediate phy.
152 + * @hw: pointer to hardware structure
153 + * @byte_offset: EEPROM byte offset to read
154 + * @eeprom_data: value read
155 + *
156 + * Performs byte read operation to SFP module's EEPROM over I2C interface.
157 + **/
158 +s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
159 + u8 *eeprom_data)
160 +{
161 + s32 status = 0;
162 + u16 sfp_addr = 0;
163 + u16 sfp_data = 0;
164 + u16 sfp_stat = 0;
165 + u32 i;
166 +
167 + if (hw->phy.type == ixgbe_phy_nl) {
168 + /*
169 + * phy SDA/SCL registers are at addresses 0xC30A to
170 + * 0xC30D. These registers are used to talk to the SFP+
171 + * module's EEPROM through the SDA/SCL (I2C) interface.
172 + */
173 + sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset;
174 + sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
175 + hw->phy.ops.write_reg(hw,
176 + IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
177 + IXGBE_MDIO_PMA_PMD_DEV_TYPE,
178 + sfp_addr);
179 +
180 + /* Poll status */
181 + for (i = 0; i < 100; i++) {
182 + hw->phy.ops.read_reg(hw,
183 + IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
184 + IXGBE_MDIO_PMA_PMD_DEV_TYPE,
185 + &sfp_stat);
186 + sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
187 + if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
188 + break;
189 + msleep(10);
190 + }
191 +
192 + if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
193 + hw_dbg(hw, "EEPROM read did not pass.\n");
194 + status = IXGBE_ERR_SFP_NOT_PRESENT;
195 + goto out;
196 + }
197 +
198 + /* Read data */
199 + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
200 + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
201 +
202 + *eeprom_data = (u8)(sfp_data >> 8);
203 + } else {
204 + status = IXGBE_ERR_PHY;
205 + goto out;
206 + }
207 +
208 +out:
209 + return status;
210 +}
211 +
212 +/**
213 * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
214 * @hw: pointer to hardware structure
215 *
216 @@ -873,13 +1007,35 @@ s32 ixgbe_get_supported_physical_layer_8
217 case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
218 physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
219 break;
220 + case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
221 + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
222 + break;
223 case IXGBE_DEV_ID_82598AF_DUAL_PORT:
224 case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
225 + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
226 physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
227 break;
228 case IXGBE_DEV_ID_82598EB_XF_LR:
229 physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
230 break;
231 + case IXGBE_DEV_ID_82598EB_SFP_LOM:
232 + hw->phy.ops.identify_sfp(hw);
233 +
234 + switch (hw->phy.sfp_type) {
235 + case ixgbe_sfp_type_da_cu:
236 + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
237 + break;
238 + case ixgbe_sfp_type_sr:
239 + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
240 + break;
241 + case ixgbe_sfp_type_lr:
242 + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
243 + break;
244 + default:
245 + physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
246 + break;
247 + }
248 + break;
249 case IXGBE_DEV_ID_82598AT:
250 physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
251 IXGBE_PHYSICAL_LAYER_1000BASE_T);
252 @@ -935,12 +1091,13 @@ static struct ixgbe_eeprom_operations ee
253
254 static struct ixgbe_phy_operations phy_ops_82598 = {
255 .identify = &ixgbe_identify_phy_generic,
256 - /* .identify_sfp = &ixgbe_identify_sfp_module_generic, */
257 + .identify_sfp = &ixgbe_identify_sfp_module_generic,
258 .reset = &ixgbe_reset_phy_generic,
259 .read_reg = &ixgbe_read_phy_reg_generic,
260 .write_reg = &ixgbe_write_phy_reg_generic,
261 .setup_link = &ixgbe_setup_phy_link_generic,
262 .setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
263 + .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598,
264 };
265
266 struct ixgbe_info ixgbe_82598_info = {
267 --- a/drivers/net/ixgbe/ixgbe.h
268 +++ b/drivers/net/ixgbe/ixgbe.h
269 @@ -318,12 +318,15 @@ struct ixgbe_adapter {
270 unsigned long link_check_timeout;
271
272 struct work_struct watchdog_task;
273 + struct work_struct sfp_task;
274 + struct timer_list sfp_timer;
275 };
276
277 enum ixbge_state_t {
278 __IXGBE_TESTING,
279 __IXGBE_RESETTING,
280 - __IXGBE_DOWN
281 + __IXGBE_DOWN,
282 + __IXGBE_SFP_MODULE_NOT_FOUND
283 };
284
285 enum ixgbe_boards {
286 --- a/drivers/net/ixgbe/ixgbe_main.c
287 +++ b/drivers/net/ixgbe/ixgbe_main.c
288 @@ -74,8 +74,14 @@ static struct pci_device_id ixgbe_pci_tb
289 board_82598 },
290 {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
291 board_82598 },
292 + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT),
293 + board_82598 },
294 + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM),
295 + board_82598 },
296 {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR),
297 board_82598 },
298 + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM),
299 + board_82598 },
300
301 /* required last entry */
302 {0, }
303 @@ -2678,6 +2684,56 @@ err_alloc_queues:
304 }
305
306 /**
307 + * ixgbe_sfp_timer - worker thread to find a missing module
308 + * @data: pointer to our adapter struct
309 + **/
310 +static void ixgbe_sfp_timer(unsigned long data)
311 +{
312 + struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
313 +
314 + /* Do the sfp_timer outside of interrupt context due to the
315 + * delays that sfp+ detection requires */
316 + schedule_work(&adapter->sfp_task);
317 +}
318 +
319 +/**
320 + * ixgbe_sfp_task - worker thread to find a missing module
321 + * @work: pointer to work_struct containing our data
322 + **/
323 +static void ixgbe_sfp_task(struct work_struct *work)
324 +{
325 + struct ixgbe_adapter *adapter = container_of(work,
326 + struct ixgbe_adapter,
327 + sfp_task);
328 + struct ixgbe_hw *hw = &adapter->hw;
329 +
330 + if ((hw->phy.type == ixgbe_phy_nl) &&
331 + (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
332 + s32 ret = hw->phy.ops.identify_sfp(hw);
333 + if (ret)
334 + goto reschedule;
335 + ret = hw->phy.ops.reset(hw);
336 + if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
337 + DPRINTK(PROBE, ERR, "failed to initialize because an "
338 + "unsupported SFP+ module type was detected.\n"
339 + "Reload the driver after installing a "
340 + "supported module.\n");
341 + unregister_netdev(adapter->netdev);
342 + } else {
343 + DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
344 + hw->phy.sfp_type);
345 + }
346 + /* don't need this routine any more */
347 + clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
348 + }
349 + return;
350 +reschedule:
351 + if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
352 + mod_timer(&adapter->sfp_timer,
353 + round_jiffies(jiffies + (2 * HZ)));
354 +}
355 +
356 +/**
357 * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
358 * @adapter: board private structure to initialize
359 *
360 @@ -4002,11 +4058,30 @@ static int __devinit ixgbe_probe(struct
361
362 /* PHY */
363 memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops));
364 - /* phy->sfp_type = ixgbe_sfp_type_unknown; */
365 + hw->phy.sfp_type = ixgbe_sfp_type_unknown;
366 +
367 + /* set up this timer and work struct before calling get_invariants
368 + * which might start the timer */
369 + init_timer(&adapter->sfp_timer);
370 + adapter->sfp_timer.function = &ixgbe_sfp_timer;
371 + adapter->sfp_timer.data = (unsigned long) adapter;
372 +
373 + INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
374
375 err = ii->get_invariants(hw);
376 - if (err)
377 + if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
378 + /* start a kernel thread to watch for a module to arrive */
379 + set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
380 + mod_timer(&adapter->sfp_timer,
381 + round_jiffies(jiffies + (2 * HZ)));
382 + err = 0;
383 + } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
384 + DPRINTK(PROBE, ERR, "failed to load because an "
385 + "unsupported SFP+ module type was detected.\n");
386 + goto err_hw_init;
387 + } else if (err) {
388 goto err_hw_init;
389 + }
390
391 /* setup the private structure */
392 err = ixgbe_sw_init(adapter);
393 @@ -4144,6 +4219,9 @@ err_hw_init:
394 err_sw_init:
395 ixgbe_reset_interrupt_capability(adapter);
396 err_eeprom:
397 + clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
398 + del_timer_sync(&adapter->sfp_timer);
399 + cancel_work_sync(&adapter->sfp_task);
400 iounmap(hw->hw_addr);
401 err_ioremap:
402 free_netdev(netdev);
403 @@ -4170,8 +4248,13 @@ static void __devexit ixgbe_remove(struc
404 struct ixgbe_adapter *adapter = netdev_priv(netdev);
405
406 set_bit(__IXGBE_DOWN, &adapter->state);
407 + /* clear the module not found bit to make sure the worker won't
408 + * reschedule */
409 + clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
410 del_timer_sync(&adapter->watchdog_timer);
411 -
412 + del_timer_sync(&adapter->sfp_timer);
413 + cancel_work_sync(&adapter->watchdog_task);
414 + cancel_work_sync(&adapter->sfp_task);
415 flush_scheduled_work();
416
417 #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
418 @@ -4182,7 +4265,8 @@ static void __devexit ixgbe_remove(struc
419 }
420
421 #endif
422 - unregister_netdev(netdev);
423 + if (netdev->reg_state == NETREG_REGISTERED)
424 + unregister_netdev(netdev);
425
426 ixgbe_reset_interrupt_capability(adapter);
427
428 --- a/drivers/net/ixgbe/ixgbe_phy.c
429 +++ b/drivers/net/ixgbe/ixgbe_phy.c
430 @@ -127,6 +127,9 @@ static enum ixgbe_phy_type ixgbe_get_phy
431 case QT2022_PHY_ID:
432 phy_type = ixgbe_phy_qt;
433 break;
434 + case ATH_PHY_ID:
435 + phy_type = ixgbe_phy_nl;
436 + break;
437 default:
438 phy_type = ixgbe_phy_unknown;
439 break;
440 @@ -430,6 +433,261 @@ s32 ixgbe_setup_phy_link_speed_generic(s
441 }
442
443 /**
444 + * ixgbe_reset_phy_nl - Performs a PHY reset
445 + * @hw: pointer to hardware structure
446 + **/
447 +s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
448 +{
449 + u16 phy_offset, control, eword, edata, block_crc;
450 + bool end_data = false;
451 + u16 list_offset, data_offset;
452 + u16 phy_data = 0;
453 + s32 ret_val = 0;
454 + u32 i;
455 +
456 + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
457 + IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
458 +
459 + /* reset the PHY and poll for completion */
460 + hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
461 + IXGBE_MDIO_PHY_XS_DEV_TYPE,
462 + (phy_data | IXGBE_MDIO_PHY_XS_RESET));
463 +
464 + for (i = 0; i < 100; i++) {
465 + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
466 + IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
467 + if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0)
468 + break;
469 + msleep(10);
470 + }
471 +
472 + if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
473 + hw_dbg(hw, "PHY reset did not complete.\n");
474 + ret_val = IXGBE_ERR_PHY;
475 + goto out;
476 + }
477 +
478 + /* Get init offsets */
479 + ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
480 + &data_offset);
481 + if (ret_val != 0)
482 + goto out;
483 +
484 + ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
485 + data_offset++;
486 + while (!end_data) {
487 + /*
488 + * Read control word from PHY init contents offset
489 + */
490 + ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
491 + control = (eword & IXGBE_CONTROL_MASK_NL) >>
492 + IXGBE_CONTROL_SHIFT_NL;
493 + edata = eword & IXGBE_DATA_MASK_NL;
494 + switch (control) {
495 + case IXGBE_DELAY_NL:
496 + data_offset++;
497 + hw_dbg(hw, "DELAY: %d MS\n", edata);
498 + msleep(edata);
499 + break;
500 + case IXGBE_DATA_NL:
501 + hw_dbg(hw, "DATA: \n");
502 + data_offset++;
503 + hw->eeprom.ops.read(hw, data_offset++,
504 + &phy_offset);
505 + for (i = 0; i < edata; i++) {
506 + hw->eeprom.ops.read(hw, data_offset, &eword);
507 + hw->phy.ops.write_reg(hw, phy_offset,
508 + IXGBE_TWINAX_DEV, eword);
509 + hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
510 + phy_offset);
511 + data_offset++;
512 + phy_offset++;
513 + }
514 + break;
515 + case IXGBE_CONTROL_NL:
516 + data_offset++;
517 + hw_dbg(hw, "CONTROL: \n");
518 + if (edata == IXGBE_CONTROL_EOL_NL) {
519 + hw_dbg(hw, "EOL\n");
520 + end_data = true;
521 + } else if (edata == IXGBE_CONTROL_SOL_NL) {
522 + hw_dbg(hw, "SOL\n");
523 + } else {
524 + hw_dbg(hw, "Bad control value\n");
525 + ret_val = IXGBE_ERR_PHY;
526 + goto out;
527 + }
528 + break;
529 + default:
530 + hw_dbg(hw, "Bad control type\n");
531 + ret_val = IXGBE_ERR_PHY;
532 + goto out;
533 + }
534 + }
535 +
536 +out:
537 + return ret_val;
538 +}
539 +
540 +/**
541 + * ixgbe_identify_sfp_module_generic - Identifies SFP module and assigns
542 + * the PHY type.
543 + * @hw: pointer to hardware structure
544 + *
545 + * Searches for and identifies the SFP module. Assigns appropriate PHY type.
546 + **/
547 +s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
548 +{
549 + s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
550 + u32 vendor_oui = 0;
551 + u8 identifier = 0;
552 + u8 comp_codes_1g = 0;
553 + u8 comp_codes_10g = 0;
554 + u8 oui_bytes[4] = {0, 0, 0, 0};
555 + u8 transmission_media = 0;
556 +
557 + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
558 + &identifier);
559 +
560 + if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
561 + hw->phy.sfp_type = ixgbe_sfp_type_not_present;
562 + goto out;
563 + }
564 +
565 + if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
566 + hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
567 + &comp_codes_1g);
568 + hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
569 + &comp_codes_10g);
570 + hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA,
571 + &transmission_media);
572 +
573 + /* ID Module
574 + * ============
575 + * 0 SFP_DA_CU
576 + * 1 SFP_SR
577 + * 2 SFP_LR
578 + */
579 + if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
580 + hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
581 + else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
582 + hw->phy.sfp_type = ixgbe_sfp_type_sr;
583 + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
584 + hw->phy.sfp_type = ixgbe_sfp_type_lr;
585 + else
586 + hw->phy.sfp_type = ixgbe_sfp_type_unknown;
587 +
588 + /* Determine PHY vendor */
589 + if (hw->phy.type == ixgbe_phy_unknown) {
590 + hw->phy.id = identifier;
591 + hw->phy.ops.read_i2c_eeprom(hw,
592 + IXGBE_SFF_VENDOR_OUI_BYTE0,
593 + &oui_bytes[0]);
594 + hw->phy.ops.read_i2c_eeprom(hw,
595 + IXGBE_SFF_VENDOR_OUI_BYTE1,
596 + &oui_bytes[1]);
597 + hw->phy.ops.read_i2c_eeprom(hw,
598 + IXGBE_SFF_VENDOR_OUI_BYTE2,
599 + &oui_bytes[2]);
600 +
601 + vendor_oui =
602 + ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
603 + (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
604 + (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
605 +
606 + switch (vendor_oui) {
607 + case IXGBE_SFF_VENDOR_OUI_TYCO:
608 + if (transmission_media &
609 + IXGBE_SFF_TWIN_AX_CAPABLE)
610 + hw->phy.type = ixgbe_phy_tw_tyco;
611 + break;
612 + case IXGBE_SFF_VENDOR_OUI_FTL:
613 + hw->phy.type = ixgbe_phy_sfp_ftl;
614 + break;
615 + case IXGBE_SFF_VENDOR_OUI_AVAGO:
616 + hw->phy.type = ixgbe_phy_sfp_avago;
617 + break;
618 + default:
619 + if (transmission_media &
620 + IXGBE_SFF_TWIN_AX_CAPABLE)
621 + hw->phy.type = ixgbe_phy_tw_unknown;
622 + else
623 + hw->phy.type = ixgbe_phy_sfp_unknown;
624 + break;
625 + }
626 + }
627 + status = 0;
628 + }
629 +
630 +out:
631 + return status;
632 +}
633 +
634 +/**
635 + * ixgbe_get_sfp_init_sequence_offsets - Checks the MAC's EEPROM to see
636 + * if it supports a given SFP+ module type, if so it returns the offsets to the
637 + * phy init sequence block.
638 + * @hw: pointer to hardware structure
639 + * @list_offset: offset to the SFP ID list
640 + * @data_offset: offset to the SFP data block
641 + **/
642 +s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
643 + u16 *list_offset,
644 + u16 *data_offset)
645 +{
646 + u16 sfp_id;
647 +
648 + if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
649 + return IXGBE_ERR_SFP_NOT_SUPPORTED;
650 +
651 + if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
652 + return IXGBE_ERR_SFP_NOT_PRESENT;
653 +
654 + if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
655 + (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
656 + return IXGBE_ERR_SFP_NOT_SUPPORTED;
657 +
658 + /* Read offset to PHY init contents */
659 + hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
660 +
661 + if ((!*list_offset) || (*list_offset == 0xFFFF))
662 + return IXGBE_ERR_PHY;
663 +
664 + /* Shift offset to first ID word */
665 + (*list_offset)++;
666 +
667 + /*
668 + * Find the matching SFP ID in the EEPROM
669 + * and program the init sequence
670 + */
671 + hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
672 +
673 + while (sfp_id != IXGBE_PHY_INIT_END_NL) {
674 + if (sfp_id == hw->phy.sfp_type) {
675 + (*list_offset)++;
676 + hw->eeprom.ops.read(hw, *list_offset, data_offset);
677 + if ((!*data_offset) || (*data_offset == 0xFFFF)) {
678 + hw_dbg(hw, "SFP+ module not supported\n");
679 + return IXGBE_ERR_SFP_NOT_SUPPORTED;
680 + } else {
681 + break;
682 + }
683 + } else {
684 + (*list_offset) += 2;
685 + if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
686 + return IXGBE_ERR_PHY;
687 + }
688 + }
689 +
690 + if (sfp_id == IXGBE_PHY_INIT_END_NL) {
691 + hw_dbg(hw, "No matching SFP+ module found\n");
692 + return IXGBE_ERR_SFP_NOT_SUPPORTED;
693 + }
694 +
695 + return 0;
696 +}
697 +
698 +/**
699 * ixgbe_check_phy_link_tnx - Determine link and speed status
700 * @hw: pointer to hardware structure
701 *
702 --- a/drivers/net/ixgbe/ixgbe_phy.h
703 +++ b/drivers/net/ixgbe/ixgbe_phy.h
704 @@ -63,6 +63,18 @@
705 #define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500
706 #define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00
707
708 +/* I2C SDA and SCL timing parameters for standard mode */
709 +#define IXGBE_I2C_T_HD_STA 4
710 +#define IXGBE_I2C_T_LOW 5
711 +#define IXGBE_I2C_T_HIGH 4
712 +#define IXGBE_I2C_T_SU_STA 5
713 +#define IXGBE_I2C_T_HD_DATA 5
714 +#define IXGBE_I2C_T_SU_DATA 1
715 +#define IXGBE_I2C_T_RISE 1
716 +#define IXGBE_I2C_T_FALL 1
717 +#define IXGBE_I2C_T_SU_STO 4
718 +#define IXGBE_I2C_T_BUF 5
719 +
720
721 s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
722 s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
723 @@ -84,4 +96,10 @@ s32 ixgbe_check_phy_link_tnx(struct ixgb
724 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
725 u16 *firmware_version);
726
727 +/* PHY specific */
728 +s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
729 +s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
730 +s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
731 + u16 *list_offset,
732 + u16 *data_offset);
733 #endif /* _IXGBE_PHY_H_ */
734 --- a/drivers/net/ixgbe/ixgbe_type.h
735 +++ b/drivers/net/ixgbe/ixgbe_type.h
736 @@ -36,9 +36,12 @@
737 /* Device IDs */
738 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
739 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
740 +#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
741 #define IXGBE_DEV_ID_82598AT 0x10C8
742 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD
743 #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
744 +#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
745 +#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
746 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
747
748 /* General Registers */
749 @@ -453,6 +456,7 @@
750 #define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
751 #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
752 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
753 +#define IXGBE_TWINAX_DEV 1
754
755 #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
756
757 @@ -492,9 +496,21 @@
758 #define TN1010_PHY_ID 0x00A19410
759 #define TNX_FW_REV 0xB
760 #define QT2022_PHY_ID 0x0043A400
761 +#define ATH_PHY_ID 0x03429050
762
763 /* PHY Types */
764 #define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
765 +/* Special PHY Init Routine */
766 +#define IXGBE_PHY_INIT_OFFSET_NL 0x002B
767 +#define IXGBE_PHY_INIT_END_NL 0xFFFF
768 +#define IXGBE_CONTROL_MASK_NL 0xF000
769 +#define IXGBE_DATA_MASK_NL 0x0FFF
770 +#define IXGBE_CONTROL_SHIFT_NL 12
771 +#define IXGBE_DELAY_NL 0
772 +#define IXGBE_DATA_NL 1
773 +#define IXGBE_CONTROL_NL 0x000F
774 +#define IXGBE_CONTROL_EOL_NL 0x0FFF
775 +#define IXGBE_CONTROL_SOL_NL 0x0000
776
777 /* General purpose Interrupt Enable */
778 #define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */
779 @@ -1208,6 +1224,7 @@ enum ixgbe_phy_type {
780 ixgbe_phy_tn,
781 ixgbe_phy_qt,
782 ixgbe_phy_xaui,
783 + ixgbe_phy_nl,
784 ixgbe_phy_tw_tyco,
785 ixgbe_phy_tw_unknown,
786 ixgbe_phy_sfp_avago,
787 @@ -1229,6 +1246,7 @@ enum ixgbe_sfp_type {
788 ixgbe_sfp_type_da_cu = 0,
789 ixgbe_sfp_type_sr = 1,
790 ixgbe_sfp_type_lr = 2,
791 + ixgbe_sfp_type_not_present = 0xFFFE,
792 ixgbe_sfp_type_unknown = 0xFFFF
793 };
794
795 @@ -1492,6 +1510,7 @@ struct ixgbe_info {
796 #define IXGBE_ERR_PHY_ADDR_INVALID -17
797 #define IXGBE_ERR_I2C -18
798 #define IXGBE_ERR_SFP_NOT_SUPPORTED -19
799 +#define IXGBE_ERR_SFP_NOT_PRESENT -20
800 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
801
802 #endif /* _IXGBE_TYPE_H_ */