qlcnic_sysfs.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. #include <linux/slab.h>
  2. #include <linux/vmalloc.h>
  3. #include <linux/interrupt.h>
  4. #include "qlcnic.h"
  5. #include "qlcnic_hw.h"
  6. #include <linux/swab.h>
  7. #include <linux/dma-mapping.h>
  8. #include <net/ip.h>
  9. #include <linux/ipv6.h>
  10. #include <linux/inetdevice.h>
  11. #include <linux/sysfs.h>
  12. #include <linux/aer.h>
  13. #include <linux/log2.h>
  14. #include <linux/sysfs.h>
  15. #define QLC_STATUS_UNSUPPORTED_CMD -2
  16. int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
  17. {
  18. return -EOPNOTSUPP;
  19. }
  20. int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
  21. {
  22. return -EOPNOTSUPP;
  23. }
  24. static ssize_t qlcnic_store_bridged_mode(struct device *dev,
  25. struct device_attribute *attr,
  26. const char *buf, size_t len)
  27. {
  28. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  29. unsigned long new;
  30. int ret = -EINVAL;
  31. if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
  32. goto err_out;
  33. if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
  34. goto err_out;
  35. if (strict_strtoul(buf, 2, &new))
  36. goto err_out;
  37. if (!qlcnic_config_bridged_mode(adapter, !!new))
  38. ret = len;
  39. err_out:
  40. return ret;
  41. }
  42. static ssize_t qlcnic_show_bridged_mode(struct device *dev,
  43. struct device_attribute *attr,
  44. char *buf)
  45. {
  46. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  47. int bridged_mode = 0;
  48. if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
  49. bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
  50. return sprintf(buf, "%d\n", bridged_mode);
  51. }
  52. static ssize_t qlcnic_store_diag_mode(struct device *dev,
  53. struct device_attribute *attr,
  54. const char *buf, size_t len)
  55. {
  56. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  57. unsigned long new;
  58. if (strict_strtoul(buf, 2, &new))
  59. return -EINVAL;
  60. if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
  61. adapter->flags ^= QLCNIC_DIAG_ENABLED;
  62. return len;
  63. }
  64. static ssize_t qlcnic_show_diag_mode(struct device *dev,
  65. struct device_attribute *attr, char *buf)
  66. {
  67. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  68. return sprintf(buf, "%d\n", !!(adapter->flags & QLCNIC_DIAG_ENABLED));
  69. }
  70. static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
  71. u8 *state, u8 *rate)
  72. {
  73. *rate = LSB(beacon);
  74. *state = MSB(beacon);
  75. QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
  76. if (!*state) {
  77. *rate = __QLCNIC_MAX_LED_RATE;
  78. return 0;
  79. } else if (*state > __QLCNIC_MAX_LED_STATE) {
  80. return -EINVAL;
  81. }
  82. if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
  83. return -EINVAL;
  84. return 0;
  85. }
  86. static ssize_t qlcnic_store_beacon(struct device *dev,
  87. struct device_attribute *attr,
  88. const char *buf, size_t len)
  89. {
  90. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  91. struct qlcnic_hardware_context *ahw = adapter->ahw;
  92. int err, max_sds_rings = adapter->max_sds_rings;
  93. u16 beacon;
  94. u8 b_state, b_rate;
  95. unsigned long h_beacon;
  96. if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
  97. dev_warn(dev,
  98. "LED test not supported in non privileged mode\n");
  99. return -EOPNOTSUPP;
  100. }
  101. if (qlcnic_83xx_check(adapter) &&
  102. !test_bit(__QLCNIC_RESETTING, &adapter->state)) {
  103. if (kstrtoul(buf, 2, &h_beacon))
  104. return -EINVAL;
  105. if (ahw->beacon_state == h_beacon)
  106. return len;
  107. rtnl_lock();
  108. if (!ahw->beacon_state) {
  109. if (test_and_set_bit(__QLCNIC_LED_ENABLE,
  110. &adapter->state)) {
  111. rtnl_unlock();
  112. return -EBUSY;
  113. }
  114. }
  115. if (h_beacon) {
  116. err = qlcnic_83xx_config_led(adapter, 1, h_beacon);
  117. if (err)
  118. goto beacon_err;
  119. } else {
  120. err = qlcnic_83xx_config_led(adapter, 0, !h_beacon);
  121. if (err)
  122. goto beacon_err;
  123. }
  124. /* set the current beacon state */
  125. ahw->beacon_state = h_beacon;
  126. beacon_err:
  127. if (!ahw->beacon_state)
  128. clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
  129. rtnl_unlock();
  130. return len;
  131. }
  132. if (len != sizeof(u16))
  133. return QL_STATUS_INVALID_PARAM;
  134. memcpy(&beacon, buf, sizeof(u16));
  135. err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
  136. if (err)
  137. return err;
  138. if (adapter->ahw->beacon_state == b_state)
  139. return len;
  140. rtnl_lock();
  141. if (!adapter->ahw->beacon_state)
  142. if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
  143. rtnl_unlock();
  144. return -EBUSY;
  145. }
  146. if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
  147. err = -EIO;
  148. goto out;
  149. }
  150. if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
  151. err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
  152. if (err)
  153. goto out;
  154. set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
  155. }
  156. err = qlcnic_config_led(adapter, b_state, b_rate);
  157. if (!err)
  158. err = len;
  159. else
  160. ahw->beacon_state = b_state;
  161. if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
  162. qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
  163. out:
  164. if (!adapter->ahw->beacon_state)
  165. clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
  166. rtnl_unlock();
  167. return err;
  168. }
  169. static ssize_t qlcnic_show_beacon(struct device *dev,
  170. struct device_attribute *attr, char *buf)
  171. {
  172. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  173. return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
  174. }
  175. static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
  176. loff_t offset, size_t size)
  177. {
  178. size_t crb_size = 4;
  179. if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
  180. return -EIO;
  181. if (offset < QLCNIC_PCI_CRBSPACE) {
  182. if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
  183. QLCNIC_PCI_CAMQM_END))
  184. crb_size = 8;
  185. else
  186. return -EINVAL;
  187. }
  188. if ((size != crb_size) || (offset & (crb_size-1)))
  189. return -EINVAL;
  190. return 0;
  191. }
  192. static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
  193. struct bin_attribute *attr, char *buf,
  194. loff_t offset, size_t size)
  195. {
  196. struct device *dev = container_of(kobj, struct device, kobj);
  197. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  198. int ret;
  199. ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
  200. if (ret != 0)
  201. return ret;
  202. qlcnic_read_crb(adapter, buf, offset, size);
  203. return size;
  204. }
  205. static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
  206. struct bin_attribute *attr, char *buf,
  207. loff_t offset, size_t size)
  208. {
  209. struct device *dev = container_of(kobj, struct device, kobj);
  210. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  211. int ret;
  212. ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
  213. if (ret != 0)
  214. return ret;
  215. qlcnic_write_crb(adapter, buf, offset, size);
  216. return size;
  217. }
  218. static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
  219. loff_t offset, size_t size)
  220. {
  221. if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
  222. return -EIO;
  223. if ((size != 8) || (offset & 0x7))
  224. return -EIO;
  225. return 0;
  226. }
  227. static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
  228. struct bin_attribute *attr, char *buf,
  229. loff_t offset, size_t size)
  230. {
  231. struct device *dev = container_of(kobj, struct device, kobj);
  232. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  233. u64 data;
  234. int ret;
  235. ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
  236. if (ret != 0)
  237. return ret;
  238. if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
  239. return -EIO;
  240. memcpy(buf, &data, size);
  241. return size;
  242. }
  243. static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
  244. struct bin_attribute *attr, char *buf,
  245. loff_t offset, size_t size)
  246. {
  247. struct device *dev = container_of(kobj, struct device, kobj);
  248. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  249. u64 data;
  250. int ret;
  251. ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
  252. if (ret != 0)
  253. return ret;
  254. memcpy(&data, buf, size);
  255. if (qlcnic_pci_mem_write_2M(adapter, offset, data))
  256. return -EIO;
  257. return size;
  258. }
  259. static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
  260. {
  261. int i;
  262. for (i = 0; i < adapter->ahw->act_pci_func; i++) {
  263. if (adapter->npars[i].pci_func == pci_func)
  264. return i;
  265. }
  266. return -1;
  267. }
  268. static int validate_pm_config(struct qlcnic_adapter *adapter,
  269. struct qlcnic_pm_func_cfg *pm_cfg, int count)
  270. {
  271. u8 src_pci_func, s_esw_id, d_esw_id;
  272. u8 dest_pci_func;
  273. int i, src_index, dest_index;
  274. for (i = 0; i < count; i++) {
  275. src_pci_func = pm_cfg[i].pci_func;
  276. dest_pci_func = pm_cfg[i].dest_npar;
  277. src_index = qlcnic_is_valid_nic_func(adapter, src_pci_func);
  278. if (src_index < 0)
  279. return QL_STATUS_INVALID_PARAM;
  280. dest_index = qlcnic_is_valid_nic_func(adapter, dest_pci_func);
  281. if (dest_index < 0)
  282. return QL_STATUS_INVALID_PARAM;
  283. s_esw_id = adapter->npars[src_index].phy_port;
  284. d_esw_id = adapter->npars[dest_index].phy_port;
  285. if (s_esw_id != d_esw_id)
  286. return QL_STATUS_INVALID_PARAM;
  287. }
  288. return 0;
  289. }
  290. static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
  291. struct kobject *kobj,
  292. struct bin_attribute *attr,
  293. char *buf, loff_t offset,
  294. size_t size)
  295. {
  296. struct device *dev = container_of(kobj, struct device, kobj);
  297. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  298. struct qlcnic_pm_func_cfg *pm_cfg;
  299. u32 id, action, pci_func;
  300. int count, rem, i, ret, index;
  301. count = size / sizeof(struct qlcnic_pm_func_cfg);
  302. rem = size % sizeof(struct qlcnic_pm_func_cfg);
  303. if (rem)
  304. return QL_STATUS_INVALID_PARAM;
  305. pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
  306. ret = validate_pm_config(adapter, pm_cfg, count);
  307. if (ret)
  308. return ret;
  309. for (i = 0; i < count; i++) {
  310. pci_func = pm_cfg[i].pci_func;
  311. action = !!pm_cfg[i].action;
  312. index = qlcnic_is_valid_nic_func(adapter, pci_func);
  313. if (index < 0)
  314. return QL_STATUS_INVALID_PARAM;
  315. id = adapter->npars[index].phy_port;
  316. ret = qlcnic_config_port_mirroring(adapter, id,
  317. action, pci_func);
  318. if (ret)
  319. return ret;
  320. }
  321. for (i = 0; i < count; i++) {
  322. pci_func = pm_cfg[i].pci_func;
  323. index = qlcnic_is_valid_nic_func(adapter, pci_func);
  324. id = adapter->npars[index].phy_port;
  325. adapter->npars[index].enable_pm = !!pm_cfg[i].action;
  326. adapter->npars[index].dest_npar = id;
  327. }
  328. return size;
  329. }
  330. static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
  331. struct kobject *kobj,
  332. struct bin_attribute *attr,
  333. char *buf, loff_t offset,
  334. size_t size)
  335. {
  336. struct device *dev = container_of(kobj, struct device, kobj);
  337. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  338. struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
  339. int i;
  340. u8 pci_func;
  341. if (size != sizeof(pm_cfg))
  342. return QL_STATUS_INVALID_PARAM;
  343. memset(&pm_cfg, 0,
  344. sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC);
  345. for (i = 0; i < adapter->ahw->act_pci_func; i++) {
  346. pci_func = adapter->npars[i].pci_func;
  347. pm_cfg[pci_func].action = adapter->npars[i].enable_pm;
  348. pm_cfg[pci_func].dest_npar = 0;
  349. pm_cfg[pci_func].pci_func = i;
  350. }
  351. memcpy(buf, &pm_cfg, size);
  352. return size;
  353. }
  354. static int validate_esw_config(struct qlcnic_adapter *adapter,
  355. struct qlcnic_esw_func_cfg *esw_cfg, int count)
  356. {
  357. u32 op_mode;
  358. u8 pci_func;
  359. int i, ret;
  360. if (qlcnic_82xx_check(adapter))
  361. op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
  362. else
  363. op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
  364. for (i = 0; i < count; i++) {
  365. pci_func = esw_cfg[i].pci_func;
  366. if (pci_func >= QLCNIC_MAX_PCI_FUNC)
  367. return QL_STATUS_INVALID_PARAM;
  368. if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
  369. if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
  370. return QL_STATUS_INVALID_PARAM;
  371. switch (esw_cfg[i].op_mode) {
  372. case QLCNIC_PORT_DEFAULTS:
  373. if (qlcnic_82xx_check(adapter)) {
  374. ret = QLC_DEV_GET_DRV(op_mode, pci_func);
  375. } else {
  376. ret = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
  377. pci_func);
  378. esw_cfg[i].offload_flags = 0;
  379. }
  380. if (ret != QLCNIC_NON_PRIV_FUNC) {
  381. if (esw_cfg[i].mac_anti_spoof != 0)
  382. return QL_STATUS_INVALID_PARAM;
  383. if (esw_cfg[i].mac_override != 1)
  384. return QL_STATUS_INVALID_PARAM;
  385. if (esw_cfg[i].promisc_mode != 1)
  386. return QL_STATUS_INVALID_PARAM;
  387. }
  388. break;
  389. case QLCNIC_ADD_VLAN:
  390. if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
  391. return QL_STATUS_INVALID_PARAM;
  392. if (!esw_cfg[i].op_type)
  393. return QL_STATUS_INVALID_PARAM;
  394. break;
  395. case QLCNIC_DEL_VLAN:
  396. if (!esw_cfg[i].op_type)
  397. return QL_STATUS_INVALID_PARAM;
  398. break;
  399. default:
  400. return QL_STATUS_INVALID_PARAM;
  401. }
  402. }
  403. return 0;
  404. }
  405. static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
  406. struct kobject *kobj,
  407. struct bin_attribute *attr,
  408. char *buf, loff_t offset,
  409. size_t size)
  410. {
  411. struct device *dev = container_of(kobj, struct device, kobj);
  412. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  413. struct qlcnic_esw_func_cfg *esw_cfg;
  414. struct qlcnic_npar_info *npar;
  415. int count, rem, i, ret;
  416. int index;
  417. u8 op_mode = 0, pci_func;
  418. count = size / sizeof(struct qlcnic_esw_func_cfg);
  419. rem = size % sizeof(struct qlcnic_esw_func_cfg);
  420. if (rem)
  421. return QL_STATUS_INVALID_PARAM;
  422. esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
  423. ret = validate_esw_config(adapter, esw_cfg, count);
  424. if (ret)
  425. return ret;
  426. for (i = 0; i < count; i++) {
  427. if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
  428. if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
  429. return QL_STATUS_INVALID_PARAM;
  430. if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
  431. continue;
  432. op_mode = esw_cfg[i].op_mode;
  433. qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
  434. esw_cfg[i].op_mode = op_mode;
  435. esw_cfg[i].pci_func = adapter->ahw->pci_func;
  436. switch (esw_cfg[i].op_mode) {
  437. case QLCNIC_PORT_DEFAULTS:
  438. qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
  439. break;
  440. case QLCNIC_ADD_VLAN:
  441. qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
  442. break;
  443. case QLCNIC_DEL_VLAN:
  444. esw_cfg[i].vlan_id = 0;
  445. qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
  446. break;
  447. }
  448. }
  449. if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
  450. goto out;
  451. for (i = 0; i < count; i++) {
  452. pci_func = esw_cfg[i].pci_func;
  453. index = qlcnic_is_valid_nic_func(adapter, pci_func);
  454. npar = &adapter->npars[index];
  455. switch (esw_cfg[i].op_mode) {
  456. case QLCNIC_PORT_DEFAULTS:
  457. npar->promisc_mode = esw_cfg[i].promisc_mode;
  458. npar->mac_override = esw_cfg[i].mac_override;
  459. npar->offload_flags = esw_cfg[i].offload_flags;
  460. npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
  461. npar->discard_tagged = esw_cfg[i].discard_tagged;
  462. break;
  463. case QLCNIC_ADD_VLAN:
  464. npar->pvid = esw_cfg[i].vlan_id;
  465. break;
  466. case QLCNIC_DEL_VLAN:
  467. npar->pvid = 0;
  468. break;
  469. }
  470. }
  471. out:
  472. return size;
  473. }
  474. static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
  475. struct kobject *kobj,
  476. struct bin_attribute *attr,
  477. char *buf, loff_t offset,
  478. size_t size)
  479. {
  480. struct device *dev = container_of(kobj, struct device, kobj);
  481. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  482. struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
  483. u8 i, pci_func;
  484. if (size != sizeof(esw_cfg))
  485. return QL_STATUS_INVALID_PARAM;
  486. memset(&esw_cfg, 0,
  487. sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC);
  488. for (i = 0; i < adapter->ahw->act_pci_func; i++) {
  489. pci_func = adapter->npars[i].pci_func;
  490. esw_cfg[pci_func].pci_func = pci_func;
  491. if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
  492. return QL_STATUS_INVALID_PARAM;
  493. }
  494. memcpy(buf, &esw_cfg, size);
  495. return size;
  496. }
  497. static int validate_npar_config(struct qlcnic_adapter *adapter,
  498. struct qlcnic_npar_func_cfg *np_cfg,
  499. int count)
  500. {
  501. u8 pci_func, i;
  502. for (i = 0; i < count; i++) {
  503. pci_func = np_cfg[i].pci_func;
  504. if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0)
  505. return QL_STATUS_INVALID_PARAM;
  506. if (!IS_VALID_BW(np_cfg[i].min_bw) ||
  507. !IS_VALID_BW(np_cfg[i].max_bw))
  508. return QL_STATUS_INVALID_PARAM;
  509. }
  510. return 0;
  511. }
  512. static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
  513. struct kobject *kobj,
  514. struct bin_attribute *attr,
  515. char *buf, loff_t offset,
  516. size_t size)
  517. {
  518. struct device *dev = container_of(kobj, struct device, kobj);
  519. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  520. struct qlcnic_info nic_info;
  521. struct qlcnic_npar_func_cfg *np_cfg;
  522. int i, count, rem, ret, index;
  523. u8 pci_func;
  524. count = size / sizeof(struct qlcnic_npar_func_cfg);
  525. rem = size % sizeof(struct qlcnic_npar_func_cfg);
  526. if (rem)
  527. return QL_STATUS_INVALID_PARAM;
  528. np_cfg = (struct qlcnic_npar_func_cfg *)buf;
  529. ret = validate_npar_config(adapter, np_cfg, count);
  530. if (ret)
  531. return ret;
  532. for (i = 0; i < count; i++) {
  533. pci_func = np_cfg[i].pci_func;
  534. memset(&nic_info, 0, sizeof(struct qlcnic_info));
  535. ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
  536. if (ret)
  537. return ret;
  538. nic_info.pci_func = pci_func;
  539. nic_info.min_tx_bw = np_cfg[i].min_bw;
  540. nic_info.max_tx_bw = np_cfg[i].max_bw;
  541. ret = qlcnic_set_nic_info(adapter, &nic_info);
  542. if (ret)
  543. return ret;
  544. index = qlcnic_is_valid_nic_func(adapter, pci_func);
  545. adapter->npars[index].min_bw = nic_info.min_tx_bw;
  546. adapter->npars[index].max_bw = nic_info.max_tx_bw;
  547. }
  548. return size;
  549. }
  550. static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
  551. struct kobject *kobj,
  552. struct bin_attribute *attr,
  553. char *buf, loff_t offset,
  554. size_t size)
  555. {
  556. struct device *dev = container_of(kobj, struct device, kobj);
  557. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  558. struct qlcnic_info nic_info;
  559. struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
  560. int i, ret;
  561. if (size != sizeof(np_cfg))
  562. return QL_STATUS_INVALID_PARAM;
  563. memset(&nic_info, 0, sizeof(struct qlcnic_info));
  564. memset(&np_cfg, 0,
  565. sizeof(struct qlcnic_npar_func_cfg) * QLCNIC_MAX_PCI_FUNC);
  566. for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
  567. if (qlcnic_is_valid_nic_func(adapter, i) < 0)
  568. continue;
  569. ret = qlcnic_get_nic_info(adapter, &nic_info, i);
  570. if (ret)
  571. return ret;
  572. np_cfg[i].pci_func = i;
  573. np_cfg[i].op_mode = (u8)nic_info.op_mode;
  574. np_cfg[i].port_num = nic_info.phys_port;
  575. np_cfg[i].fw_capab = nic_info.capabilities;
  576. np_cfg[i].min_bw = nic_info.min_tx_bw;
  577. np_cfg[i].max_bw = nic_info.max_tx_bw;
  578. np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
  579. np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
  580. }
  581. memcpy(buf, &np_cfg, size);
  582. return size;
  583. }
  584. static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
  585. struct kobject *kobj,
  586. struct bin_attribute *attr,
  587. char *buf, loff_t offset,
  588. size_t size)
  589. {
  590. struct device *dev = container_of(kobj, struct device, kobj);
  591. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  592. struct qlcnic_esw_statistics port_stats;
  593. int ret;
  594. if (qlcnic_83xx_check(adapter))
  595. return QLC_STATUS_UNSUPPORTED_CMD;
  596. if (size != sizeof(struct qlcnic_esw_statistics))
  597. return QL_STATUS_INVALID_PARAM;
  598. if (offset >= QLCNIC_MAX_PCI_FUNC)
  599. return QL_STATUS_INVALID_PARAM;
  600. memset(&port_stats, 0, size);
  601. ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
  602. &port_stats.rx);
  603. if (ret)
  604. return ret;
  605. ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
  606. &port_stats.tx);
  607. if (ret)
  608. return ret;
  609. memcpy(buf, &port_stats, size);
  610. return size;
  611. }
  612. static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
  613. struct kobject *kobj,
  614. struct bin_attribute *attr,
  615. char *buf, loff_t offset,
  616. size_t size)
  617. {
  618. struct device *dev = container_of(kobj, struct device, kobj);
  619. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  620. struct qlcnic_esw_statistics esw_stats;
  621. int ret;
  622. if (qlcnic_83xx_check(adapter))
  623. return QLC_STATUS_UNSUPPORTED_CMD;
  624. if (size != sizeof(struct qlcnic_esw_statistics))
  625. return QL_STATUS_INVALID_PARAM;
  626. if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
  627. return QL_STATUS_INVALID_PARAM;
  628. memset(&esw_stats, 0, size);
  629. ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
  630. &esw_stats.rx);
  631. if (ret)
  632. return ret;
  633. ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
  634. &esw_stats.tx);
  635. if (ret)
  636. return ret;
  637. memcpy(buf, &esw_stats, size);
  638. return size;
  639. }
  640. static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
  641. struct kobject *kobj,
  642. struct bin_attribute *attr,
  643. char *buf, loff_t offset,
  644. size_t size)
  645. {
  646. struct device *dev = container_of(kobj, struct device, kobj);
  647. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  648. int ret;
  649. if (qlcnic_83xx_check(adapter))
  650. return QLC_STATUS_UNSUPPORTED_CMD;
  651. if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
  652. return QL_STATUS_INVALID_PARAM;
  653. ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
  654. QLCNIC_QUERY_RX_COUNTER);
  655. if (ret)
  656. return ret;
  657. ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
  658. QLCNIC_QUERY_TX_COUNTER);
  659. if (ret)
  660. return ret;
  661. return size;
  662. }
  663. static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
  664. struct kobject *kobj,
  665. struct bin_attribute *attr,
  666. char *buf, loff_t offset,
  667. size_t size)
  668. {
  669. struct device *dev = container_of(kobj, struct device, kobj);
  670. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  671. int ret;
  672. if (qlcnic_83xx_check(adapter))
  673. return QLC_STATUS_UNSUPPORTED_CMD;
  674. if (offset >= QLCNIC_MAX_PCI_FUNC)
  675. return QL_STATUS_INVALID_PARAM;
  676. ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
  677. QLCNIC_QUERY_RX_COUNTER);
  678. if (ret)
  679. return ret;
  680. ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
  681. QLCNIC_QUERY_TX_COUNTER);
  682. if (ret)
  683. return ret;
  684. return size;
  685. }
  686. static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
  687. struct kobject *kobj,
  688. struct bin_attribute *attr,
  689. char *buf, loff_t offset,
  690. size_t size)
  691. {
  692. struct device *dev = container_of(kobj, struct device, kobj);
  693. struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
  694. struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
  695. struct qlcnic_pci_info *pci_info;
  696. int i, ret;
  697. if (size != sizeof(pci_cfg))
  698. return QL_STATUS_INVALID_PARAM;
  699. pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
  700. if (!pci_info)
  701. return -ENOMEM;
  702. ret = qlcnic_get_pci_info(adapter, pci_info);
  703. if (ret) {
  704. kfree(pci_info);
  705. return ret;
  706. }
  707. memset(&pci_cfg, 0,
  708. sizeof(struct qlcnic_pci_func_cfg) * QLCNIC_MAX_PCI_FUNC);
  709. for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
  710. pci_cfg[i].pci_func = pci_info[i].id;
  711. pci_cfg[i].func_type = pci_info[i].type;
  712. pci_cfg[i].port_num = pci_info[i].default_port;
  713. pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
  714. pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
  715. memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
  716. }
  717. memcpy(buf, &pci_cfg, size);
  718. kfree(pci_info);
  719. return size;
  720. }
  721. static struct device_attribute dev_attr_bridged_mode = {
  722. .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
  723. .show = qlcnic_show_bridged_mode,
  724. .store = qlcnic_store_bridged_mode,
  725. };
  726. static struct device_attribute dev_attr_diag_mode = {
  727. .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
  728. .show = qlcnic_show_diag_mode,
  729. .store = qlcnic_store_diag_mode,
  730. };
  731. static struct device_attribute dev_attr_beacon = {
  732. .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
  733. .show = qlcnic_show_beacon,
  734. .store = qlcnic_store_beacon,
  735. };
  736. static struct bin_attribute bin_attr_crb = {
  737. .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
  738. .size = 0,
  739. .read = qlcnic_sysfs_read_crb,
  740. .write = qlcnic_sysfs_write_crb,
  741. };
  742. static struct bin_attribute bin_attr_mem = {
  743. .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
  744. .size = 0,
  745. .read = qlcnic_sysfs_read_mem,
  746. .write = qlcnic_sysfs_write_mem,
  747. };
  748. static struct bin_attribute bin_attr_npar_config = {
  749. .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
  750. .size = 0,
  751. .read = qlcnic_sysfs_read_npar_config,
  752. .write = qlcnic_sysfs_write_npar_config,
  753. };
  754. static struct bin_attribute bin_attr_pci_config = {
  755. .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
  756. .size = 0,
  757. .read = qlcnic_sysfs_read_pci_config,
  758. .write = NULL,
  759. };
  760. static struct bin_attribute bin_attr_port_stats = {
  761. .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
  762. .size = 0,
  763. .read = qlcnic_sysfs_get_port_stats,
  764. .write = qlcnic_sysfs_clear_port_stats,
  765. };
  766. static struct bin_attribute bin_attr_esw_stats = {
  767. .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
  768. .size = 0,
  769. .read = qlcnic_sysfs_get_esw_stats,
  770. .write = qlcnic_sysfs_clear_esw_stats,
  771. };
  772. static struct bin_attribute bin_attr_esw_config = {
  773. .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
  774. .size = 0,
  775. .read = qlcnic_sysfs_read_esw_config,
  776. .write = qlcnic_sysfs_write_esw_config,
  777. };
  778. static struct bin_attribute bin_attr_pm_config = {
  779. .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
  780. .size = 0,
  781. .read = qlcnic_sysfs_read_pm_config,
  782. .write = qlcnic_sysfs_write_pm_config,
  783. };
  784. void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
  785. {
  786. struct device *dev = &adapter->pdev->dev;
  787. if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
  788. if (device_create_file(dev, &dev_attr_bridged_mode))
  789. dev_warn(dev,
  790. "failed to create bridged_mode sysfs entry\n");
  791. }
  792. void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
  793. {
  794. struct device *dev = &adapter->pdev->dev;
  795. if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
  796. device_remove_file(dev, &dev_attr_bridged_mode);
  797. }
  798. void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
  799. {
  800. struct device *dev = &adapter->pdev->dev;
  801. if (device_create_bin_file(dev, &bin_attr_port_stats))
  802. dev_info(dev, "failed to create port stats sysfs entry");
  803. if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
  804. return;
  805. if (device_create_file(dev, &dev_attr_diag_mode))
  806. dev_info(dev, "failed to create diag_mode sysfs entry\n");
  807. if (device_create_bin_file(dev, &bin_attr_crb))
  808. dev_info(dev, "failed to create crb sysfs entry\n");
  809. if (device_create_bin_file(dev, &bin_attr_mem))
  810. dev_info(dev, "failed to create mem sysfs entry\n");
  811. if (device_create_bin_file(dev, &bin_attr_pci_config))
  812. dev_info(dev, "failed to create pci config sysfs entry");
  813. if (device_create_file(dev, &dev_attr_beacon))
  814. dev_info(dev, "failed to create beacon sysfs entry");
  815. if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
  816. return;
  817. if (device_create_bin_file(dev, &bin_attr_esw_config))
  818. dev_info(dev, "failed to create esw config sysfs entry");
  819. if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
  820. return;
  821. if (device_create_bin_file(dev, &bin_attr_npar_config))
  822. dev_info(dev, "failed to create npar config sysfs entry");
  823. if (device_create_bin_file(dev, &bin_attr_pm_config))
  824. dev_info(dev, "failed to create pm config sysfs entry");
  825. if (device_create_bin_file(dev, &bin_attr_esw_stats))
  826. dev_info(dev, "failed to create eswitch stats sysfs entry");
  827. }
  828. void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
  829. {
  830. struct device *dev = &adapter->pdev->dev;
  831. device_remove_bin_file(dev, &bin_attr_port_stats);
  832. if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
  833. return;
  834. device_remove_file(dev, &dev_attr_diag_mode);
  835. device_remove_bin_file(dev, &bin_attr_crb);
  836. device_remove_bin_file(dev, &bin_attr_mem);
  837. device_remove_bin_file(dev, &bin_attr_pci_config);
  838. device_remove_file(dev, &dev_attr_beacon);
  839. if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
  840. return;
  841. device_remove_bin_file(dev, &bin_attr_esw_config);
  842. if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
  843. return;
  844. device_remove_bin_file(dev, &bin_attr_npar_config);
  845. device_remove_bin_file(dev, &bin_attr_pm_config);
  846. device_remove_bin_file(dev, &bin_attr_esw_stats);
  847. }
  848. void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter)
  849. {
  850. qlcnic_create_diag_entries(adapter);
  851. }
  852. void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)
  853. {
  854. qlcnic_remove_diag_entries(adapter);
  855. }
  856. void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)
  857. {
  858. qlcnic_create_diag_entries(adapter);
  859. }
  860. void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)
  861. {
  862. qlcnic_remove_diag_entries(adapter);
  863. }