skethtool.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /******************************************************************************
  2. *
  3. * Name: skethtool.c
  4. * Project: GEnesis, PCI Gigabit Ethernet Adapter
  5. * Version: $Revision: 1.7 $
  6. * Date: $Date: 2004/09/29 13:32:07 $
  7. * Purpose: All functions regarding ethtool handling
  8. *
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. * (C)Copyright 1998-2002 SysKonnect GmbH.
  13. * (C)Copyright 2002-2004 Marvell.
  14. *
  15. * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
  16. * Server Adapters.
  17. *
  18. * Author: Ralph Roesler (rroesler@syskonnect.de)
  19. * Mirko Lindner (mlindner@syskonnect.de)
  20. *
  21. * Address all question to: linux@syskonnect.de
  22. *
  23. * The technical manual for the adapters is available from SysKonnect's
  24. * web pages: www.syskonnect.com
  25. *
  26. * This program is free software; you can redistribute it and/or modify
  27. * it under the terms of the GNU General Public License as published by
  28. * the Free Software Foundation; either version 2 of the License, or
  29. * (at your option) any later version.
  30. *
  31. * The information in this file is provided "AS IS" without warranty.
  32. *
  33. *****************************************************************************/
  34. #include "h/skdrv1st.h"
  35. #include "h/skdrv2nd.h"
  36. #include "h/skversion.h"
  37. #include <linux/ethtool.h>
  38. #include <linux/timer.h>
  39. #include <linux/delay.h>
  40. /******************************************************************************
  41. *
  42. * Defines
  43. *
  44. *****************************************************************************/
  45. #define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
  46. SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
  47. SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
  48. SUPPORTED_TP)
  49. #define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
  50. ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
  51. ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
  52. ADVERTISED_TP)
  53. #define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \
  54. SUPPORTED_FIBRE | \
  55. SUPPORTED_Autoneg)
  56. #define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \
  57. ADVERTISED_FIBRE | \
  58. ADVERTISED_Autoneg)
  59. /******************************************************************************
  60. *
  61. * Local Functions
  62. *
  63. *****************************************************************************/
  64. /*****************************************************************************
  65. *
  66. * getSettings - retrieves the current settings of the selected adapter
  67. *
  68. * Description:
  69. * The current configuration of the selected adapter is returned.
  70. * This configuration involves a)speed, b)duplex and c)autoneg plus
  71. * a number of other variables.
  72. *
  73. * Returns: always 0
  74. *
  75. */
  76. static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
  77. {
  78. const DEV_NET *pNet = netdev_priv(dev);
  79. int port = pNet->PortNr;
  80. const SK_AC *pAC = pNet->pAC;
  81. const SK_GEPORT *pPort = &pAC->GIni.GP[port];
  82. static int DuplexAutoNegConfMap[9][3]= {
  83. { -1 , -1 , -1 },
  84. { 0 , -1 , -1 },
  85. { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE },
  86. { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE },
  87. { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE },
  88. { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE },
  89. { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE },
  90. { SK_LMODE_AUTOSENSE , -1 , -1 },
  91. { SK_LMODE_INDETERMINATED, -1 , -1 }
  92. };
  93. static int SpeedConfMap[6][2] = {
  94. { 0 , -1 },
  95. { SK_LSPEED_AUTO , -1 },
  96. { SK_LSPEED_10MBPS , SPEED_10 },
  97. { SK_LSPEED_100MBPS , SPEED_100 },
  98. { SK_LSPEED_1000MBPS , SPEED_1000 },
  99. { SK_LSPEED_INDETERMINATED, -1 }
  100. };
  101. static int AdvSpeedMap[6][2] = {
  102. { 0 , -1 },
  103. { SK_LSPEED_AUTO , -1 },
  104. { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full },
  105. { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full },
  106. { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
  107. { SK_LSPEED_INDETERMINATED, -1 }
  108. };
  109. ecmd->phy_address = port;
  110. ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1];
  111. ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
  112. ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
  113. ecmd->transceiver = XCVR_INTERNAL;
  114. if (pAC->GIni.GICopperType) {
  115. ecmd->port = PORT_TP;
  116. ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
  117. if (pAC->GIni.GIGenesis) {
  118. ecmd->supported &= ~(SUPPORTED_10baseT_Half);
  119. ecmd->supported &= ~(SUPPORTED_10baseT_Full);
  120. ecmd->supported &= ~(SUPPORTED_100baseT_Half);
  121. ecmd->supported &= ~(SUPPORTED_100baseT_Full);
  122. } else {
  123. if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
  124. ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
  125. }
  126. #ifdef CHIP_ID_YUKON_FE
  127. if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
  128. ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
  129. ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
  130. }
  131. #endif
  132. }
  133. if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
  134. ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
  135. if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
  136. ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
  137. }
  138. } else {
  139. ecmd->advertising = ecmd->supported;
  140. }
  141. if (ecmd->autoneg == AUTONEG_ENABLE)
  142. ecmd->advertising |= ADVERTISED_Autoneg;
  143. } else {
  144. ecmd->port = PORT_FIBRE;
  145. ecmd->supported = SUPP_FIBRE_ALL;
  146. ecmd->advertising = ADV_FIBRE_ALL;
  147. }
  148. return 0;
  149. }
  150. /*
  151. * MIB infrastructure uses instance value starting at 1
  152. * based on board and port.
  153. */
  154. static inline u32 pnmiInstance(const DEV_NET *pNet)
  155. {
  156. return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
  157. }
  158. /*****************************************************************************
  159. *
  160. * setSettings - configures the settings of a selected adapter
  161. *
  162. * Description:
  163. * Possible settings that may be altered are a)speed, b)duplex or
  164. * c)autonegotiation.
  165. *
  166. * Returns:
  167. * 0: everything fine, no error
  168. * <0: the return value is the error code of the failure
  169. */
  170. static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
  171. {
  172. DEV_NET *pNet = netdev_priv(dev);
  173. SK_AC *pAC = pNet->pAC;
  174. u32 instance;
  175. char buf[4];
  176. int len = 1;
  177. if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100
  178. && ecmd->speed != SPEED_1000)
  179. return -EINVAL;
  180. if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
  181. return -EINVAL;
  182. if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
  183. return -EINVAL;
  184. if (ecmd->autoneg == AUTONEG_DISABLE)
  185. *buf = (ecmd->duplex == DUPLEX_FULL)
  186. ? SK_LMODE_FULL : SK_LMODE_HALF;
  187. else
  188. *buf = (ecmd->duplex == DUPLEX_FULL)
  189. ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
  190. instance = pnmiInstance(pNet);
  191. if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE,
  192. &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
  193. return -EINVAL;
  194. switch(ecmd->speed) {
  195. case SPEED_1000:
  196. *buf = SK_LSPEED_1000MBPS;
  197. break;
  198. case SPEED_100:
  199. *buf = SK_LSPEED_100MBPS;
  200. break;
  201. case SPEED_10:
  202. *buf = SK_LSPEED_10MBPS;
  203. }
  204. if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
  205. &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
  206. return -EINVAL;
  207. return 0;
  208. }
  209. /*****************************************************************************
  210. *
  211. * getDriverInfo - returns generic driver and adapter information
  212. *
  213. * Description:
  214. * Generic driver information is returned via this function, such as
  215. * the name of the driver, its version and and firmware version.
  216. * In addition to this, the location of the selected adapter is
  217. * returned as a bus info string (e.g. '01:05.0').
  218. *
  219. * Returns: N/A
  220. *
  221. */
  222. static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
  223. {
  224. const DEV_NET *pNet = netdev_priv(dev);
  225. const SK_AC *pAC = pNet->pAC;
  226. char vers[32];
  227. snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
  228. (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
  229. strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
  230. strcpy(info->version, vers);
  231. strcpy(info->fw_version, "N/A");
  232. strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
  233. }
  234. /*
  235. * Ethtool statistics support.
  236. */
  237. static const char StringsStats[][ETH_GSTRING_LEN] = {
  238. "rx_packets", "tx_packets",
  239. "rx_bytes", "tx_bytes",
  240. "rx_errors", "tx_errors",
  241. "rx_dropped", "tx_dropped",
  242. "multicasts", "collisions",
  243. "rx_length_errors", "rx_buffer_overflow_errors",
  244. "rx_crc_errors", "rx_frame_errors",
  245. "rx_too_short_errors", "rx_too_long_errors",
  246. "rx_carrier_extension_errors", "rx_symbol_errors",
  247. "rx_llc_mac_size_errors", "rx_carrier_errors",
  248. "rx_jabber_errors", "rx_missed_errors",
  249. "tx_abort_collision_errors", "tx_carrier_errors",
  250. "tx_buffer_underrun_errors", "tx_heartbeat_errors",
  251. "tx_window_errors",
  252. };
  253. static int getStatsCount(struct net_device *dev)
  254. {
  255. return ARRAY_SIZE(StringsStats);
  256. }
  257. static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
  258. {
  259. switch(stringset) {
  260. case ETH_SS_STATS:
  261. memcpy(data, *StringsStats, sizeof(StringsStats));
  262. break;
  263. }
  264. }
  265. static void getEthtoolStats(struct net_device *dev,
  266. struct ethtool_stats *stats, u64 *data)
  267. {
  268. const DEV_NET *pNet = netdev_priv(dev);
  269. const SK_AC *pAC = pNet->pAC;
  270. const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
  271. *data++ = pPnmiStruct->Stat[0].StatRxOkCts;
  272. *data++ = pPnmiStruct->Stat[0].StatTxOkCts;
  273. *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
  274. *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
  275. *data++ = pPnmiStruct->InErrorsCts;
  276. *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
  277. *data++ = pPnmiStruct->RxNoBufCts;
  278. *data++ = pPnmiStruct->TxNoBufCts;
  279. *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
  280. *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
  281. *data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
  282. *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
  283. *data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
  284. *data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
  285. *data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
  286. *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
  287. *data++ = pPnmiStruct->Stat[0].StatRxCextCts;
  288. *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
  289. *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
  290. *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
  291. *data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
  292. *data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
  293. *data++ = pAC->stats.tx_aborted_errors;
  294. *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
  295. *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
  296. *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
  297. *data++ = pAC->stats.tx_window_errors;
  298. }
  299. /*****************************************************************************
  300. *
  301. * toggleLeds - Changes the LED state of an adapter
  302. *
  303. * Description:
  304. * This function changes the current state of all LEDs of an adapter so
  305. * that it can be located by a user.
  306. *
  307. * Returns: N/A
  308. *
  309. */
  310. static void toggleLeds(DEV_NET *pNet, int on)
  311. {
  312. SK_AC *pAC = pNet->pAC;
  313. int port = pNet->PortNr;
  314. void __iomem *io = pAC->IoBase;
  315. if (pAC->GIni.GIGenesis) {
  316. SK_OUT8(io, MR_ADDR(port,LNK_LED_REG),
  317. on ? SK_LNK_ON : SK_LNK_OFF);
  318. SkGeYellowLED(pAC, io,
  319. on ? (LED_ON >> 1) : (LED_OFF >> 1));
  320. SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
  321. on ? SK_LED_TST : SK_LED_DIS);
  322. if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
  323. SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL,
  324. on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
  325. else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
  326. SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
  327. on ? 0x0800 : PHY_L_LC_LEDT);
  328. else
  329. SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
  330. on ? SK_LED_TST : SK_LED_DIS);
  331. } else {
  332. const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) |
  333. PHY_M_LED_MO_10(MO_LED_ON) |
  334. PHY_M_LED_MO_100(MO_LED_ON) |
  335. PHY_M_LED_MO_1000(MO_LED_ON) |
  336. PHY_M_LED_MO_RX(MO_LED_ON));
  337. const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) |
  338. PHY_M_LED_MO_10(MO_LED_OFF) |
  339. PHY_M_LED_MO_100(MO_LED_OFF) |
  340. PHY_M_LED_MO_1000(MO_LED_OFF) |
  341. PHY_M_LED_MO_RX(MO_LED_OFF));
  342. SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
  343. SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER,
  344. on ? YukLedOn : YukLedOff);
  345. }
  346. }
  347. /*****************************************************************************
  348. *
  349. * skGeBlinkTimer - Changes the LED state of an adapter
  350. *
  351. * Description:
  352. * This function changes the current state of all LEDs of an adapter so
  353. * that it can be located by a user. If the requested time interval for
  354. * this test has elapsed, this function cleans up everything that was
  355. * temporarily setup during the locate NIC test. This involves of course
  356. * also closing or opening any adapter so that the initial board state
  357. * is recovered.
  358. *
  359. * Returns: N/A
  360. *
  361. */
  362. void SkGeBlinkTimer(unsigned long data)
  363. {
  364. struct net_device *dev = (struct net_device *) data;
  365. DEV_NET *pNet = netdev_priv(dev);
  366. SK_AC *pAC = pNet->pAC;
  367. toggleLeds(pNet, pAC->LedsOn);
  368. pAC->LedsOn = !pAC->LedsOn;
  369. mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
  370. }
  371. /*****************************************************************************
  372. *
  373. * locateDevice - start the locate NIC feature of the elected adapter
  374. *
  375. * Description:
  376. * This function is used if the user want to locate a particular NIC.
  377. * All LEDs are regularly switched on and off, so the NIC can easily
  378. * be identified.
  379. *
  380. * Returns:
  381. * ==0: everything fine, no error, locateNIC test was started
  382. * !=0: one locateNIC test runs already
  383. *
  384. */
  385. static int locateDevice(struct net_device *dev, u32 data)
  386. {
  387. DEV_NET *pNet = netdev_priv(dev);
  388. SK_AC *pAC = pNet->pAC;
  389. if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
  390. data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
  391. /* start blinking */
  392. pAC->LedsOn = 0;
  393. mod_timer(&pAC->BlinkTimer, jiffies);
  394. msleep_interruptible(data * 1000);
  395. del_timer_sync(&pAC->BlinkTimer);
  396. toggleLeds(pNet, 0);
  397. return 0;
  398. }
  399. /*****************************************************************************
  400. *
  401. * getPauseParams - retrieves the pause parameters
  402. *
  403. * Description:
  404. * All current pause parameters of a selected adapter are placed
  405. * in the passed ethtool_pauseparam structure and are returned.
  406. *
  407. * Returns: N/A
  408. *
  409. */
  410. static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause)
  411. {
  412. DEV_NET *pNet = netdev_priv(dev);
  413. SK_AC *pAC = pNet->pAC;
  414. SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
  415. epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
  416. (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
  417. epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
  418. epause->autoneg = epause->rx_pause || epause->tx_pause;
  419. }
  420. /*****************************************************************************
  421. *
  422. * setPauseParams - configures the pause parameters of an adapter
  423. *
  424. * Description:
  425. * This function sets the Rx or Tx pause parameters
  426. *
  427. * Returns:
  428. * ==0: everything fine, no error
  429. * !=0: the return value is the error code of the failure
  430. */
  431. static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
  432. {
  433. DEV_NET *pNet = netdev_priv(dev);
  434. SK_AC *pAC = pNet->pAC;
  435. SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
  436. u32 instance = pnmiInstance(pNet);
  437. struct ethtool_pauseparam old;
  438. u8 oldspeed = pPort->PLinkSpeedUsed;
  439. char buf[4];
  440. int len = 1;
  441. int ret;
  442. /*
  443. ** we have to determine the current settings to see if
  444. ** the operator requested any modification of the flow
  445. ** control parameters...
  446. */
  447. getPauseParams(dev, &old);
  448. /*
  449. ** perform modifications regarding the changes
  450. ** requested by the operator
  451. */
  452. if (epause->autoneg != old.autoneg)
  453. *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
  454. else {
  455. if (epause->rx_pause && epause->tx_pause)
  456. *buf = SK_FLOW_MODE_SYMMETRIC;
  457. else if (epause->rx_pause && !epause->tx_pause)
  458. *buf = SK_FLOW_MODE_SYM_OR_REM;
  459. else if (!epause->rx_pause && epause->tx_pause)
  460. *buf = SK_FLOW_MODE_LOC_SEND;
  461. else
  462. *buf = SK_FLOW_MODE_NONE;
  463. }
  464. ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
  465. &buf, &len, instance, pNet->NetNr);
  466. if (ret != SK_PNMI_ERR_OK) {
  467. SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
  468. ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
  469. goto err;
  470. }
  471. /*
  472. ** It may be that autoneg has been disabled! Therefore
  473. ** set the speed to the previously used value...
  474. */
  475. if (!epause->autoneg) {
  476. len = 1;
  477. ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
  478. &oldspeed, &len, instance, pNet->NetNr);
  479. if (ret != SK_PNMI_ERR_OK)
  480. SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
  481. ("ethtool (sk98lin): error setting speed (%i)\n", ret));
  482. }
  483. err:
  484. return ret ? -EIO : 0;
  485. }
  486. /* Only Yukon supports checksum offload. */
  487. static int setScatterGather(struct net_device *dev, u32 data)
  488. {
  489. DEV_NET *pNet = netdev_priv(dev);
  490. SK_AC *pAC = pNet->pAC;
  491. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
  492. return -EOPNOTSUPP;
  493. return ethtool_op_set_sg(dev, data);
  494. }
  495. static int setTxCsum(struct net_device *dev, u32 data)
  496. {
  497. DEV_NET *pNet = netdev_priv(dev);
  498. SK_AC *pAC = pNet->pAC;
  499. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
  500. return -EOPNOTSUPP;
  501. return ethtool_op_set_tx_csum(dev, data);
  502. }
  503. static u32 getRxCsum(struct net_device *dev)
  504. {
  505. DEV_NET *pNet = netdev_priv(dev);
  506. SK_AC *pAC = pNet->pAC;
  507. return pAC->RxPort[pNet->PortNr].RxCsum;
  508. }
  509. static int setRxCsum(struct net_device *dev, u32 data)
  510. {
  511. DEV_NET *pNet = netdev_priv(dev);
  512. SK_AC *pAC = pNet->pAC;
  513. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
  514. return -EOPNOTSUPP;
  515. pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
  516. return 0;
  517. }
  518. struct ethtool_ops SkGeEthtoolOps = {
  519. .get_settings = getSettings,
  520. .set_settings = setSettings,
  521. .get_drvinfo = getDriverInfo,
  522. .get_strings = getStrings,
  523. .get_stats_count = getStatsCount,
  524. .get_ethtool_stats = getEthtoolStats,
  525. .phys_id = locateDevice,
  526. .get_pauseparam = getPauseParams,
  527. .set_pauseparam = setPauseParams,
  528. .get_link = ethtool_op_get_link,
  529. .get_perm_addr = ethtool_op_get_perm_addr,
  530. .get_sg = ethtool_op_get_sg,
  531. .set_sg = setScatterGather,
  532. .get_tx_csum = ethtool_op_get_tx_csum,
  533. .set_tx_csum = setTxCsum,
  534. .get_rx_csum = getRxCsum,
  535. .set_rx_csum = setRxCsum,
  536. };