qlcnic_83xx_hw.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. #include "qlcnic.h"
  2. #include <linux/if_vlan.h>
  3. #include <linux/ipv6.h>
  4. #include <linux/ethtool.h>
  5. #include <linux/interrupt.h>
  6. #define QLCNIC_MAX_TX_QUEUES 1
  7. #define QLCNIC_MBX_RSP(reg) LSW(reg)
  8. #define QLCNIC_MBX_NUM_REGS(reg) (MSW(reg) & 0x1FF)
  9. #define QLCNIC_MBX_STATUS(reg) (((reg) >> 25) & 0x7F)
  10. #define QLCNIC_MBX_HOST(ahw, i) ((ahw)->pci_base0 + ((i) * 4))
  11. #define QLCNIC_MBX_FW(ahw, i) ((ahw)->pci_base0 + 0x800 + ((i) * 4))
  12. #define RSS_HASHTYPE_IP_TCP 0x3
  13. /* status descriptor mailbox data
  14. * @phy_addr: physical address of buffer
  15. * @sds_ring_size: buffer size
  16. * @intrpt_id: interrupt id
  17. * @intrpt_val: source of interrupt
  18. */
  19. struct qlcnic_sds_mbx {
  20. u64 phy_addr;
  21. u8 rsvd1[16];
  22. u16 sds_ring_size;
  23. u16 rsvd2[3];
  24. u16 intrpt_id;
  25. u8 intrpt_val;
  26. u8 rsvd3[5];
  27. } __packed;
  28. /* receive descriptor buffer data
  29. * phy_addr_reg: physical address of regular buffer
  30. * phy_addr_jmb: physical address of jumbo buffer
  31. * reg_ring_sz: size of regular buffer
  32. * reg_ring_len: no. of entries in regular buffer
  33. * jmb_ring_len: no. of entries in jumbo buffer
  34. * jmb_ring_sz: size of jumbo buffer
  35. */
  36. struct qlcnic_rds_mbx {
  37. u64 phy_addr_reg;
  38. u64 phy_addr_jmb;
  39. u16 reg_ring_sz;
  40. u16 reg_ring_len;
  41. u16 jmb_ring_sz;
  42. u16 jmb_ring_len;
  43. } __packed;
  44. /* host producers for regular and jumbo rings */
  45. struct __host_producer_mbx {
  46. u32 reg_buf;
  47. u32 jmb_buf;
  48. } __packed;
  49. /* Receive context mailbox data outbox registers
  50. * @state: state of the context
  51. * @vport_id: virtual port id
  52. * @context_id: receive context id
  53. * @num_pci_func: number of pci functions of the port
  54. * @phy_port: physical port id
  55. */
  56. struct qlcnic_rcv_mbx_out {
  57. u8 rcv_num;
  58. u8 sts_num;
  59. u16 ctx_id;
  60. u8 state;
  61. u8 num_pci_func;
  62. u8 phy_port;
  63. u8 vport_id;
  64. u32 host_csmr[QLCNIC_MAX_RING_SETS];
  65. struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
  66. } __packed;
  67. struct qlcnic_add_rings_mbx_out {
  68. u8 rcv_num;
  69. u8 sts_num;
  70. u16 ctx_id;
  71. u32 host_csmr[QLCNIC_MAX_RING_SETS];
  72. struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
  73. } __packed;
  74. /* Transmit context mailbox inbox registers
  75. * @phys_addr: DMA address of the transmit buffer
  76. * @cnsmr_index: host consumer index
  77. * @size: legth of transmit buffer ring
  78. * @intr_id: interrput id
  79. * @src: src of interrupt
  80. */
  81. struct qlcnic_tx_mbx {
  82. u64 phys_addr;
  83. u64 cnsmr_index;
  84. u16 size;
  85. u16 intr_id;
  86. u8 src;
  87. u8 rsvd[3];
  88. } __packed;
  89. /* Transmit context mailbox outbox registers
  90. * @host_prod: host producer index
  91. * @ctx_id: transmit context id
  92. * @state: state of the transmit context
  93. */
  94. struct qlcnic_tx_mbx_out {
  95. u32 host_prod;
  96. u16 ctx_id;
  97. u8 state;
  98. u8 rsvd;
  99. } __packed;
  100. static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
  101. {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
  102. {QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
  103. {QLCNIC_CMD_CREATE_RX_CTX, 136, 27},
  104. {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
  105. {QLCNIC_CMD_CREATE_TX_CTX, 54, 18},
  106. {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
  107. {QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1},
  108. {QLCNIC_CMD_INTRPT_TEST, 22, 12},
  109. {QLCNIC_CMD_SET_MTU, 3, 1},
  110. {QLCNIC_CMD_READ_PHY, 4, 2},
  111. {QLCNIC_CMD_WRITE_PHY, 5, 1},
  112. {QLCNIC_CMD_READ_HW_REG, 4, 1},
  113. {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
  114. {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
  115. {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
  116. {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
  117. {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
  118. {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
  119. {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
  120. {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
  121. {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
  122. {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
  123. {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
  124. {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
  125. {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
  126. {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
  127. {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
  128. {QLCNIC_CMD_CONFIG_PORT, 4, 1},
  129. {QLCNIC_CMD_TEMP_SIZE, 1, 4},
  130. {QLCNIC_CMD_GET_TEMP_HDR, 5, 5},
  131. {QLCNIC_CMD_GET_LINK_EVENT, 2, 1},
  132. {QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3},
  133. {QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1},
  134. {QLCNIC_CMD_CONFIGURE_RSS, 14, 1},
  135. {QLCNIC_CMD_CONFIGURE_LED, 2, 1},
  136. {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1},
  137. {QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1},
  138. {QLCNIC_CMD_GET_STATISTICS, 2, 80},
  139. {QLCNIC_CMD_SET_PORT_CONFIG, 2, 1},
  140. {QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
  141. {QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
  142. {QLCNIC_CMD_IDC_ACK, 5, 1},
  143. {QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
  144. {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
  145. {QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
  146. {QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
  147. {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
  148. };
  149. static const u32 qlcnic_83xx_ext_reg_tbl[] = {
  150. 0x38CC, /* Global Reset */
  151. 0x38F0, /* Wildcard */
  152. 0x38FC, /* Informant */
  153. 0x3038, /* Host MBX ctrl */
  154. 0x303C, /* FW MBX ctrl */
  155. 0x355C, /* BOOT LOADER ADDRESS REG */
  156. 0x3560, /* BOOT LOADER SIZE REG */
  157. 0x3564, /* FW IMAGE ADDR REG */
  158. 0x1000, /* MBX intr enable */
  159. 0x1200, /* Default Intr mask */
  160. 0x1204, /* Default Interrupt ID */
  161. 0x3780, /* QLC_83XX_IDC_MAJ_VERSION */
  162. 0x3784, /* QLC_83XX_IDC_DEV_STATE */
  163. 0x3788, /* QLC_83XX_IDC_DRV_PRESENCE */
  164. 0x378C, /* QLC_83XX_IDC_DRV_ACK */
  165. 0x3790, /* QLC_83XX_IDC_CTRL */
  166. 0x3794, /* QLC_83XX_IDC_DRV_AUDIT */
  167. 0x3798, /* QLC_83XX_IDC_MIN_VERSION */
  168. 0x379C, /* QLC_83XX_RECOVER_DRV_LOCK */
  169. 0x37A0, /* QLC_83XX_IDC_PF_0 */
  170. 0x37A4, /* QLC_83XX_IDC_PF_1 */
  171. 0x37A8, /* QLC_83XX_IDC_PF_2 */
  172. 0x37AC, /* QLC_83XX_IDC_PF_3 */
  173. 0x37B0, /* QLC_83XX_IDC_PF_4 */
  174. 0x37B4, /* QLC_83XX_IDC_PF_5 */
  175. 0x37B8, /* QLC_83XX_IDC_PF_6 */
  176. 0x37BC, /* QLC_83XX_IDC_PF_7 */
  177. 0x37C0, /* QLC_83XX_IDC_PF_8 */
  178. 0x37C4, /* QLC_83XX_IDC_PF_9 */
  179. 0x37C8, /* QLC_83XX_IDC_PF_10 */
  180. 0x37CC, /* QLC_83XX_IDC_PF_11 */
  181. 0x37D0, /* QLC_83XX_IDC_PF_12 */
  182. 0x37D4, /* QLC_83XX_IDC_PF_13 */
  183. 0x37D8, /* QLC_83XX_IDC_PF_14 */
  184. 0x37DC, /* QLC_83XX_IDC_PF_15 */
  185. 0x37E0, /* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */
  186. 0x37E4, /* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */
  187. 0x37F0, /* QLC_83XX_DRV_OP_MODE */
  188. 0x37F4, /* QLC_83XX_VNIC_STATE */
  189. 0x3868, /* QLC_83XX_DRV_LOCK */
  190. 0x386C, /* QLC_83XX_DRV_UNLOCK */
  191. 0x3504, /* QLC_83XX_DRV_LOCK_ID */
  192. 0x34A4, /* QLC_83XX_ASIC_TEMP */
  193. };
  194. static const u32 qlcnic_83xx_reg_tbl[] = {
  195. 0x34A8, /* PEG_HALT_STAT1 */
  196. 0x34AC, /* PEG_HALT_STAT2 */
  197. 0x34B0, /* FW_HEARTBEAT */
  198. 0x3500, /* FLASH LOCK_ID */
  199. 0x3528, /* FW_CAPABILITIES */
  200. 0x3538, /* Driver active, DRV_REG0 */
  201. 0x3540, /* Device state, DRV_REG1 */
  202. 0x3544, /* Driver state, DRV_REG2 */
  203. 0x3548, /* Driver scratch, DRV_REG3 */
  204. 0x354C, /* Device partiton info, DRV_REG4 */
  205. 0x3524, /* Driver IDC ver, DRV_REG5 */
  206. 0x3550, /* FW_VER_MAJOR */
  207. 0x3554, /* FW_VER_MINOR */
  208. 0x3558, /* FW_VER_SUB */
  209. 0x359C, /* NPAR STATE */
  210. 0x35FC, /* FW_IMG_VALID */
  211. 0x3650, /* CMD_PEG_STATE */
  212. 0x373C, /* RCV_PEG_STATE */
  213. 0x37B4, /* ASIC TEMP */
  214. 0x356C, /* FW API */
  215. 0x3570, /* DRV OP MODE */
  216. 0x3850, /* FLASH LOCK */
  217. 0x3854, /* FLASH UNLOCK */
  218. };
  219. static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
  220. .read_crb = qlcnic_83xx_read_crb,
  221. .write_crb = qlcnic_83xx_write_crb,
  222. .read_reg = qlcnic_83xx_rd_reg_indirect,
  223. .write_reg = qlcnic_83xx_wrt_reg_indirect,
  224. .get_mac_address = qlcnic_83xx_get_mac_address,
  225. .setup_intr = qlcnic_83xx_setup_intr,
  226. .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args,
  227. .mbx_cmd = qlcnic_83xx_mbx_op,
  228. .get_func_no = qlcnic_83xx_get_func_no,
  229. .api_lock = qlcnic_83xx_cam_lock,
  230. .api_unlock = qlcnic_83xx_cam_unlock,
  231. .add_sysfs = qlcnic_83xx_add_sysfs,
  232. .remove_sysfs = qlcnic_83xx_remove_sysfs,
  233. .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
  234. .create_rx_ctx = qlcnic_83xx_create_rx_ctx,
  235. .create_tx_ctx = qlcnic_83xx_create_tx_ctx,
  236. .setup_link_event = qlcnic_83xx_setup_link_event,
  237. .get_nic_info = qlcnic_83xx_get_nic_info,
  238. .get_pci_info = qlcnic_83xx_get_pci_info,
  239. .set_nic_info = qlcnic_83xx_set_nic_info,
  240. .change_macvlan = qlcnic_83xx_sre_macaddr_change,
  241. .napi_enable = qlcnic_83xx_napi_enable,
  242. .napi_disable = qlcnic_83xx_napi_disable,
  243. .config_intr_coal = qlcnic_83xx_config_intr_coal,
  244. .config_rss = qlcnic_83xx_config_rss,
  245. .config_hw_lro = qlcnic_83xx_config_hw_lro,
  246. .config_loopback = qlcnic_83xx_set_lb_mode,
  247. .clear_loopback = qlcnic_83xx_clear_lb_mode,
  248. .config_promisc_mode = qlcnic_83xx_nic_set_promisc,
  249. .change_l2_filter = qlcnic_83xx_change_l2_filter,
  250. .get_board_info = qlcnic_83xx_get_port_info,
  251. };
  252. static struct qlcnic_nic_template qlcnic_83xx_ops = {
  253. .config_bridged_mode = qlcnic_config_bridged_mode,
  254. .config_led = qlcnic_config_led,
  255. .napi_add = qlcnic_83xx_napi_add,
  256. .napi_del = qlcnic_83xx_napi_del,
  257. .config_ipaddr = qlcnic_83xx_config_ipaddr,
  258. .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
  259. };
  260. void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
  261. {
  262. ahw->hw_ops = &qlcnic_83xx_hw_ops;
  263. ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl;
  264. ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl;
  265. }
  266. int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
  267. {
  268. u32 fw_major, fw_minor, fw_build;
  269. struct pci_dev *pdev = adapter->pdev;
  270. fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
  271. fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
  272. fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
  273. adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
  274. dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
  275. QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
  276. return adapter->fw_version;
  277. }
  278. static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
  279. {
  280. void __iomem *base;
  281. u32 val;
  282. base = adapter->ahw->pci_base0 +
  283. QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
  284. writel(addr, base);
  285. val = readl(base);
  286. if (val != addr)
  287. return -EIO;
  288. return 0;
  289. }
  290. int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr)
  291. {
  292. int ret;
  293. struct qlcnic_hardware_context *ahw = adapter->ahw;
  294. ret = __qlcnic_set_win_base(adapter, (u32) addr);
  295. if (!ret) {
  296. return QLCRDX(ahw, QLCNIC_WILDCARD);
  297. } else {
  298. dev_err(&adapter->pdev->dev,
  299. "%s failed, addr = 0x%x\n", __func__, (int)addr);
  300. return -EIO;
  301. }
  302. }
  303. int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
  304. u32 data)
  305. {
  306. int err;
  307. struct qlcnic_hardware_context *ahw = adapter->ahw;
  308. err = __qlcnic_set_win_base(adapter, (u32) addr);
  309. if (!err) {
  310. QLCWRX(ahw, QLCNIC_WILDCARD, data);
  311. return 0;
  312. } else {
  313. dev_err(&adapter->pdev->dev,
  314. "%s failed, addr = 0x%x data = 0x%x\n",
  315. __func__, (int)addr, data);
  316. return err;
  317. }
  318. }
  319. int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
  320. {
  321. int err, i, num_msix;
  322. struct qlcnic_hardware_context *ahw = adapter->ahw;
  323. if (!num_intr)
  324. num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
  325. num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
  326. num_intr));
  327. /* account for AEN interrupt MSI-X based interrupts */
  328. num_msix += 1;
  329. num_msix += adapter->max_drv_tx_rings;
  330. err = qlcnic_enable_msix(adapter, num_msix);
  331. if (err == -ENOMEM)
  332. return err;
  333. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  334. num_msix = adapter->ahw->num_msix;
  335. else
  336. num_msix = 1;
  337. /* setup interrupt mapping table for fw */
  338. ahw->intr_tbl = vzalloc(num_msix *
  339. sizeof(struct qlcnic_intrpt_config));
  340. if (!ahw->intr_tbl)
  341. return -ENOMEM;
  342. if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
  343. /* MSI-X enablement failed, use legacy interrupt */
  344. adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
  345. adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
  346. adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
  347. adapter->msix_entries[0].vector = adapter->pdev->irq;
  348. dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
  349. }
  350. for (i = 0; i < num_msix; i++) {
  351. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  352. ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
  353. else
  354. ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
  355. ahw->intr_tbl[i].id = i;
  356. ahw->intr_tbl[i].src = 0;
  357. }
  358. return 0;
  359. }
  360. inline void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
  361. struct qlcnic_host_sds_ring *sds_ring)
  362. {
  363. writel(0, sds_ring->crb_intr_mask);
  364. if (!QLCNIC_IS_MSI_FAMILY(adapter))
  365. writel(0, adapter->tgt_mask_reg);
  366. }
  367. static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
  368. struct qlcnic_cmd_args *cmd)
  369. {
  370. int i;
  371. for (i = 0; i < cmd->rsp.num; i++)
  372. cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
  373. }
  374. irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
  375. {
  376. u32 intr_val;
  377. struct qlcnic_hardware_context *ahw = adapter->ahw;
  378. int retries = 0;
  379. intr_val = readl(adapter->tgt_status_reg);
  380. if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
  381. return IRQ_NONE;
  382. if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
  383. adapter->stats.spurious_intr++;
  384. return IRQ_NONE;
  385. }
  386. /* clear the interrupt trigger control register */
  387. writel(0, adapter->isr_int_vec);
  388. do {
  389. intr_val = readl(adapter->tgt_status_reg);
  390. if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
  391. break;
  392. retries++;
  393. } while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
  394. (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
  395. if (retries == QLC_83XX_LEGACY_INTX_MAX_RETRY) {
  396. dev_info(&adapter->pdev->dev,
  397. "Reached maximum retries to clear legacy interrupt\n");
  398. return IRQ_NONE;
  399. }
  400. mdelay(QLC_83XX_LEGACY_INTX_DELAY);
  401. return IRQ_HANDLED;
  402. }
  403. irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
  404. {
  405. struct qlcnic_host_sds_ring *sds_ring = data;
  406. struct qlcnic_adapter *adapter = sds_ring->adapter;
  407. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  408. goto done;
  409. if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
  410. return IRQ_NONE;
  411. done:
  412. adapter->ahw->diag_cnt++;
  413. qlcnic_83xx_enable_intr(adapter, sds_ring);
  414. return IRQ_HANDLED;
  415. }
  416. void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
  417. {
  418. u32 val = 0;
  419. u32 num_msix = adapter->ahw->num_msix - 1;
  420. val = (num_msix << 8);
  421. QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
  422. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  423. free_irq(adapter->msix_entries[num_msix].vector, adapter);
  424. }
  425. int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
  426. {
  427. irq_handler_t handler;
  428. u32 val;
  429. char name[32];
  430. int err = 0;
  431. unsigned long flags = 0;
  432. if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
  433. !(adapter->flags & QLCNIC_MSIX_ENABLED))
  434. flags |= IRQF_SHARED;
  435. if (adapter->flags & QLCNIC_MSIX_ENABLED) {
  436. handler = qlcnic_83xx_handle_aen;
  437. val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
  438. snprintf(name, (IFNAMSIZ + 4),
  439. "%s[%s]", adapter->netdev->name, "aen");
  440. err = request_irq(val, handler, flags, name, adapter);
  441. if (err) {
  442. dev_err(&adapter->pdev->dev,
  443. "failed to register MBX interrupt\n");
  444. return err;
  445. }
  446. }
  447. /* Enable mailbox interrupt */
  448. qlcnic_83xx_enable_mbx_intrpt(adapter);
  449. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  450. err = qlcnic_83xx_config_intrpt(adapter, 1);
  451. return err;
  452. }
  453. void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
  454. {
  455. u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
  456. adapter->ahw->pci_func = val & 0xf;
  457. }
  458. int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
  459. {
  460. void __iomem *addr;
  461. u32 val, limit = 0;
  462. struct qlcnic_hardware_context *ahw = adapter->ahw;
  463. addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
  464. do {
  465. val = readl(addr);
  466. if (val) {
  467. /* write the function number to register */
  468. QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,
  469. ahw->pci_func);
  470. return 0;
  471. }
  472. usleep_range(1000, 2000);
  473. } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT);
  474. return -EIO;
  475. }
  476. void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
  477. {
  478. void __iomem *addr;
  479. u32 val;
  480. struct qlcnic_hardware_context *ahw = adapter->ahw;
  481. addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
  482. val = readl(addr);
  483. }
  484. void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
  485. loff_t offset, size_t size)
  486. {
  487. int ret;
  488. u32 data;
  489. if (qlcnic_api_lock(adapter)) {
  490. dev_err(&adapter->pdev->dev,
  491. "%s: failed to acquire lock. addr offset 0x%x\n",
  492. __func__, (u32)offset);
  493. return;
  494. }
  495. ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset);
  496. qlcnic_api_unlock(adapter);
  497. if (ret == -EIO) {
  498. dev_err(&adapter->pdev->dev,
  499. "%s: failed. addr offset 0x%x\n",
  500. __func__, (u32)offset);
  501. return;
  502. }
  503. data = ret;
  504. memcpy(buf, &data, size);
  505. }
  506. void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
  507. loff_t offset, size_t size)
  508. {
  509. u32 data;
  510. memcpy(&data, buf, size);
  511. qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
  512. }
  513. int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
  514. {
  515. int status;
  516. status = qlcnic_83xx_get_port_config(adapter);
  517. if (status) {
  518. dev_err(&adapter->pdev->dev,
  519. "Get Port Info failed\n");
  520. } else {
  521. if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config))
  522. adapter->ahw->port_type = QLCNIC_XGBE;
  523. else
  524. adapter->ahw->port_type = QLCNIC_GBE;
  525. if (QLC_83XX_AUTONEG(adapter->ahw->port_config))
  526. adapter->ahw->link_autoneg = AUTONEG_ENABLE;
  527. }
  528. return status;
  529. }
  530. void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
  531. {
  532. u32 val;
  533. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  534. val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
  535. else
  536. val = BIT_2;
  537. QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
  538. }
  539. void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
  540. const struct pci_device_id *ent)
  541. {
  542. u32 op_mode, priv_level;
  543. struct qlcnic_hardware_context *ahw = adapter->ahw;
  544. /* Determine FW API version */
  545. ahw->fw_hal_version = 2;
  546. /* Find PCI function number */
  547. qlcnic_get_func_no(adapter);
  548. /* Determine function privilege level */
  549. op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
  550. if (op_mode == QLC_83XX_DEFAULT_OPMODE)
  551. priv_level = QLCNIC_MGMT_FUNC;
  552. else
  553. priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
  554. ahw->pci_func);
  555. if (priv_level == QLCNIC_NON_PRIV_FUNC) {
  556. ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
  557. dev_info(&adapter->pdev->dev,
  558. "HAL Version: %d Non Privileged function\n",
  559. ahw->fw_hal_version);
  560. adapter->nic_ops = &qlcnic_vf_ops;
  561. } else {
  562. adapter->nic_ops = &qlcnic_83xx_ops;
  563. }
  564. }
  565. static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
  566. u32 data[]);
  567. static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
  568. u32 data[]);
  569. static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
  570. struct qlcnic_cmd_args *cmd)
  571. {
  572. int i;
  573. dev_info(&adapter->pdev->dev,
  574. "Host MBX regs(%d)\n", cmd->req.num);
  575. for (i = 0; i < cmd->req.num; i++) {
  576. if (i && !(i % 8))
  577. pr_info("\n");
  578. pr_info("%08x ", cmd->req.arg[i]);
  579. }
  580. pr_info("\n");
  581. dev_info(&adapter->pdev->dev,
  582. "FW MBX regs(%d)\n", cmd->rsp.num);
  583. for (i = 0; i < cmd->rsp.num; i++) {
  584. if (i && !(i % 8))
  585. pr_info("\n");
  586. pr_info("%08x ", cmd->rsp.arg[i]);
  587. }
  588. pr_info("\n");
  589. }
  590. static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
  591. {
  592. u32 data;
  593. unsigned long wait_time = 0;
  594. struct qlcnic_hardware_context *ahw = adapter->ahw;
  595. /* wait for mailbox completion */
  596. do {
  597. data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
  598. if (++wait_time > QLCNIC_MBX_TIMEOUT) {
  599. data = QLCNIC_RCODE_TIMEOUT;
  600. break;
  601. }
  602. mdelay(1);
  603. } while (!data);
  604. return data;
  605. }
  606. int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
  607. struct qlcnic_cmd_args *cmd)
  608. {
  609. int i;
  610. u16 opcode;
  611. u8 mbx_err_code, mac_cmd_rcode;
  612. u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, temp, fw[8];
  613. struct qlcnic_hardware_context *ahw = adapter->ahw;
  614. opcode = LSW(cmd->req.arg[0]);
  615. spin_lock(&ahw->mbx_lock);
  616. mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
  617. if (mbx_val) {
  618. QLCDB(adapter, DRV,
  619. "Mailbox cmd attempted, 0x%x\n", opcode);
  620. QLCDB(adapter, DRV,
  621. "Mailbox not available, 0x%x, collect FW dump\n",
  622. mbx_val);
  623. cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
  624. spin_unlock(&ahw->mbx_lock);
  625. return cmd->rsp.arg[0];
  626. }
  627. /* Fill in mailbox registers */
  628. mbx_cmd = cmd->req.arg[0];
  629. writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
  630. for (i = 1; i < cmd->req.num; i++)
  631. writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
  632. /* Signal FW about the impending command */
  633. QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
  634. poll:
  635. rsp = qlcnic_83xx_mbx_poll(adapter);
  636. /* Get the FW response data */
  637. fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
  638. mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
  639. rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
  640. opcode = QLCNIC_MBX_RSP(fw_data);
  641. if (rsp != QLCNIC_RCODE_TIMEOUT) {
  642. if (opcode == QLCNIC_MBX_LINK_EVENT) {
  643. for (i = 0; i < rsp_num; i++) {
  644. temp = readl(QLCNIC_MBX_FW(ahw, i));
  645. fw[i] = temp;
  646. }
  647. qlcnic_83xx_handle_link_aen(adapter, fw);
  648. /* clear fw mbx control register */
  649. QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
  650. mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
  651. if (mbx_val)
  652. goto poll;
  653. } else if (opcode == QLCNIC_MBX_COMP_EVENT) {
  654. for (i = 0; i < rsp_num; i++) {
  655. temp = readl(QLCNIC_MBX_FW(ahw, i));
  656. fw[i] = temp;
  657. }
  658. qlcnic_83xx_handle_idc_comp_aen(adapter, fw);
  659. /* clear fw mbx control register */
  660. QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
  661. mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
  662. if (mbx_val)
  663. goto poll;
  664. } else if (opcode == QLCNIC_MBX_REQUEST_EVENT) {
  665. /* IDC Request Notification */
  666. for (i = 0; i < rsp_num; i++) {
  667. temp = readl(QLCNIC_MBX_FW(ahw, i));
  668. fw[i] = temp;
  669. }
  670. for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) {
  671. temp = QLCNIC_MBX_RSP(fw[i]);
  672. adapter->ahw->mbox_aen[i] = temp;
  673. }
  674. queue_delayed_work(adapter->qlcnic_wq,
  675. &adapter->idc_aen_work, 0);
  676. /* clear fw mbx control register */
  677. QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
  678. mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
  679. if (mbx_val)
  680. goto poll;
  681. } else if ((mbx_err_code == QLCNIC_MBX_RSP_OK) ||
  682. (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
  683. qlcnic_83xx_get_mbx_data(adapter, cmd);
  684. rsp = QLCNIC_RCODE_SUCCESS;
  685. } else {
  686. qlcnic_83xx_get_mbx_data(adapter, cmd);
  687. if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
  688. fw_data = readl(QLCNIC_MBX_FW(ahw, 2));
  689. mac_cmd_rcode = (u8)fw_data;
  690. if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
  691. mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
  692. mac_cmd_rcode == QLC_83XX_MAC_ABSENT) {
  693. rsp = QLCNIC_RCODE_SUCCESS;
  694. goto out;
  695. }
  696. }
  697. dev_info(&adapter->pdev->dev,
  698. "MBX command 0x%x failed with err:0x%x\n",
  699. opcode, mbx_err_code);
  700. rsp = mbx_err_code;
  701. qlcnic_dump_mbx(adapter, cmd);
  702. }
  703. } else {
  704. dev_info(&adapter->pdev->dev,
  705. "MBX command 0x%x timed out\n", opcode);
  706. qlcnic_dump_mbx(adapter, cmd);
  707. }
  708. out:
  709. /* clear fw mbx control register */
  710. QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
  711. spin_unlock(&ahw->mbx_lock);
  712. return rsp;
  713. }
  714. int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
  715. struct qlcnic_adapter *adapter, u32 type)
  716. {
  717. int i, size;
  718. u32 temp;
  719. const struct qlcnic_mailbox_metadata *mbx_tbl;
  720. mbx_tbl = qlcnic_83xx_mbx_tbl;
  721. size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
  722. for (i = 0; i < size; i++) {
  723. if (type == mbx_tbl[i].cmd) {
  724. mbx->req.num = mbx_tbl[i].in_args;
  725. mbx->rsp.num = mbx_tbl[i].out_args;
  726. mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
  727. GFP_ATOMIC);
  728. if (!mbx->req.arg)
  729. return -ENOMEM;
  730. mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
  731. GFP_ATOMIC);
  732. if (!mbx->rsp.arg) {
  733. kfree(mbx->req.arg);
  734. mbx->req.arg = NULL;
  735. return -ENOMEM;
  736. }
  737. memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
  738. memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
  739. temp = adapter->ahw->fw_hal_version << 29;
  740. mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
  741. break;
  742. }
  743. }
  744. return 0;
  745. }
  746. void qlcnic_83xx_idc_aen_work(struct work_struct *work)
  747. {
  748. struct qlcnic_adapter *adapter;
  749. struct qlcnic_cmd_args cmd;
  750. int i, err = 0;
  751. adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
  752. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
  753. for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
  754. cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
  755. err = qlcnic_issue_cmd(adapter, &cmd);
  756. if (err)
  757. dev_info(&adapter->pdev->dev,
  758. "%s: Mailbox IDC ACK failed.\n", __func__);
  759. qlcnic_free_mbx_args(&cmd);
  760. }
  761. static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
  762. u32 data[])
  763. {
  764. dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
  765. QLCNIC_MBX_RSP(data[0]));
  766. return;
  767. }
  768. void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
  769. {
  770. u32 mask, resp, event[QLC_83XX_MBX_AEN_CNT];
  771. int i;
  772. struct qlcnic_hardware_context *ahw = adapter->ahw;
  773. if (!spin_trylock(&ahw->mbx_lock)) {
  774. mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
  775. writel(0, adapter->ahw->pci_base0 + mask);
  776. return;
  777. }
  778. resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
  779. if (!(resp & QLCNIC_SET_OWNER))
  780. goto out;
  781. for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
  782. event[i] = readl(QLCNIC_MBX_FW(ahw, i));
  783. switch (QLCNIC_MBX_RSP(event[0])) {
  784. case QLCNIC_MBX_LINK_EVENT:
  785. qlcnic_83xx_handle_link_aen(adapter, event);
  786. break;
  787. case QLCNIC_MBX_COMP_EVENT:
  788. qlcnic_83xx_handle_idc_comp_aen(adapter, event);
  789. break;
  790. case QLCNIC_MBX_REQUEST_EVENT:
  791. for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
  792. adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
  793. queue_delayed_work(adapter->qlcnic_wq,
  794. &adapter->idc_aen_work, 0);
  795. break;
  796. case QLCNIC_MBX_TIME_EXTEND_EVENT:
  797. break;
  798. case QLCNIC_MBX_SFP_INSERT_EVENT:
  799. dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
  800. QLCNIC_MBX_RSP(event[0]));
  801. break;
  802. case QLCNIC_MBX_SFP_REMOVE_EVENT:
  803. dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
  804. QLCNIC_MBX_RSP(event[0]));
  805. break;
  806. default:
  807. dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
  808. QLCNIC_MBX_RSP(event[0]));
  809. break;
  810. }
  811. QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
  812. out:
  813. mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
  814. writel(0, adapter->ahw->pci_base0 + mask);
  815. spin_unlock(&ahw->mbx_lock);
  816. }
  817. static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
  818. {
  819. int index, i, err, sds_mbx_size;
  820. u32 *buf, intrpt_id, intr_mask;
  821. u16 context_id;
  822. u8 num_sds;
  823. struct qlcnic_cmd_args cmd;
  824. struct qlcnic_host_sds_ring *sds;
  825. struct qlcnic_sds_mbx sds_mbx;
  826. struct qlcnic_add_rings_mbx_out *mbx_out;
  827. struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
  828. struct qlcnic_hardware_context *ahw = adapter->ahw;
  829. sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
  830. context_id = recv_ctx->context_id;
  831. num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS);
  832. ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
  833. QLCNIC_CMD_ADD_RCV_RINGS);
  834. cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
  835. /* set up status rings, mbx 2-81 */
  836. index = 2;
  837. for (i = 8; i < adapter->max_sds_rings; i++) {
  838. memset(&sds_mbx, 0, sds_mbx_size);
  839. sds = &recv_ctx->sds_rings[i];
  840. sds->consumer = 0;
  841. memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
  842. sds_mbx.phy_addr = sds->phys_addr;
  843. sds_mbx.sds_ring_size = sds->num_desc;
  844. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  845. intrpt_id = ahw->intr_tbl[i].id;
  846. else
  847. intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
  848. if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
  849. sds_mbx.intrpt_id = intrpt_id;
  850. else
  851. sds_mbx.intrpt_id = 0xffff;
  852. sds_mbx.intrpt_val = 0;
  853. buf = &cmd.req.arg[index];
  854. memcpy(buf, &sds_mbx, sds_mbx_size);
  855. index += sds_mbx_size / sizeof(u32);
  856. }
  857. /* send the mailbox command */
  858. err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
  859. if (err) {
  860. dev_err(&adapter->pdev->dev,
  861. "Failed to add rings %d\n", err);
  862. goto out;
  863. }
  864. mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
  865. index = 0;
  866. /* status descriptor ring */
  867. for (i = 8; i < adapter->max_sds_rings; i++) {
  868. sds = &recv_ctx->sds_rings[i];
  869. sds->crb_sts_consumer = ahw->pci_base0 +
  870. mbx_out->host_csmr[index];
  871. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  872. intr_mask = ahw->intr_tbl[i].src;
  873. else
  874. intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
  875. sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
  876. index++;
  877. }
  878. out:
  879. qlcnic_free_mbx_args(&cmd);
  880. return err;
  881. }
  882. int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
  883. {
  884. int i, err, index, sds_mbx_size, rds_mbx_size;
  885. u8 num_sds, num_rds;
  886. u32 *buf, intrpt_id, intr_mask, cap = 0;
  887. struct qlcnic_host_sds_ring *sds;
  888. struct qlcnic_host_rds_ring *rds;
  889. struct qlcnic_sds_mbx sds_mbx;
  890. struct qlcnic_rds_mbx rds_mbx;
  891. struct qlcnic_cmd_args cmd;
  892. struct qlcnic_rcv_mbx_out *mbx_out;
  893. struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
  894. struct qlcnic_hardware_context *ahw = adapter->ahw;
  895. num_rds = adapter->max_rds_rings;
  896. if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS)
  897. num_sds = adapter->max_sds_rings;
  898. else
  899. num_sds = QLCNIC_MAX_RING_SETS;
  900. sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
  901. rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
  902. cap = QLCNIC_CAP0_LEGACY_CONTEXT;
  903. if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
  904. cap |= QLC_83XX_FW_CAP_LRO_MSS;
  905. /* set mailbox hdr and capabilities */
  906. qlcnic_alloc_mbx_args(&cmd, adapter,
  907. QLCNIC_CMD_CREATE_RX_CTX);
  908. cmd.req.arg[1] = cap;
  909. cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
  910. (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
  911. /* set up status rings, mbx 8-57/87 */
  912. index = QLC_83XX_HOST_SDS_MBX_IDX;
  913. for (i = 0; i < num_sds; i++) {
  914. memset(&sds_mbx, 0, sds_mbx_size);
  915. sds = &recv_ctx->sds_rings[i];
  916. sds->consumer = 0;
  917. memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
  918. sds_mbx.phy_addr = sds->phys_addr;
  919. sds_mbx.sds_ring_size = sds->num_desc;
  920. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  921. intrpt_id = ahw->intr_tbl[i].id;
  922. else
  923. intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
  924. if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
  925. sds_mbx.intrpt_id = intrpt_id;
  926. else
  927. sds_mbx.intrpt_id = 0xffff;
  928. sds_mbx.intrpt_val = 0;
  929. buf = &cmd.req.arg[index];
  930. memcpy(buf, &sds_mbx, sds_mbx_size);
  931. index += sds_mbx_size / sizeof(u32);
  932. }
  933. /* set up receive rings, mbx 88-111/135 */
  934. index = QLCNIC_HOST_RDS_MBX_IDX;
  935. rds = &recv_ctx->rds_rings[0];
  936. rds->producer = 0;
  937. memset(&rds_mbx, 0, rds_mbx_size);
  938. rds_mbx.phy_addr_reg = rds->phys_addr;
  939. rds_mbx.reg_ring_sz = rds->dma_size;
  940. rds_mbx.reg_ring_len = rds->num_desc;
  941. /* Jumbo ring */
  942. rds = &recv_ctx->rds_rings[1];
  943. rds->producer = 0;
  944. rds_mbx.phy_addr_jmb = rds->phys_addr;
  945. rds_mbx.jmb_ring_sz = rds->dma_size;
  946. rds_mbx.jmb_ring_len = rds->num_desc;
  947. buf = &cmd.req.arg[index];
  948. memcpy(buf, &rds_mbx, rds_mbx_size);
  949. /* send the mailbox command */
  950. err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
  951. if (err) {
  952. dev_err(&adapter->pdev->dev,
  953. "Failed to create Rx ctx in firmware%d\n", err);
  954. goto out;
  955. }
  956. mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1];
  957. recv_ctx->context_id = mbx_out->ctx_id;
  958. recv_ctx->state = mbx_out->state;
  959. recv_ctx->virt_port = mbx_out->vport_id;
  960. dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
  961. recv_ctx->context_id, recv_ctx->state);
  962. /* Receive descriptor ring */
  963. /* Standard ring */
  964. rds = &recv_ctx->rds_rings[0];
  965. rds->crb_rcv_producer = ahw->pci_base0 +
  966. mbx_out->host_prod[0].reg_buf;
  967. /* Jumbo ring */
  968. rds = &recv_ctx->rds_rings[1];
  969. rds->crb_rcv_producer = ahw->pci_base0 +
  970. mbx_out->host_prod[0].jmb_buf;
  971. /* status descriptor ring */
  972. for (i = 0; i < num_sds; i++) {
  973. sds = &recv_ctx->sds_rings[i];
  974. sds->crb_sts_consumer = ahw->pci_base0 +
  975. mbx_out->host_csmr[i];
  976. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  977. intr_mask = ahw->intr_tbl[i].src;
  978. else
  979. intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
  980. sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
  981. }
  982. if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS)
  983. err = qlcnic_83xx_add_rings(adapter);
  984. out:
  985. qlcnic_free_mbx_args(&cmd);
  986. return err;
  987. }
  988. int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
  989. struct qlcnic_host_tx_ring *tx, int ring)
  990. {
  991. int err;
  992. u16 msix_id;
  993. u32 *buf, intr_mask;
  994. struct qlcnic_cmd_args cmd;
  995. struct qlcnic_tx_mbx mbx;
  996. struct qlcnic_tx_mbx_out *mbx_out;
  997. struct qlcnic_hardware_context *ahw = adapter->ahw;
  998. /* Reset host resources */
  999. tx->producer = 0;
  1000. tx->sw_consumer = 0;
  1001. *(tx->hw_consumer) = 0;
  1002. memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
  1003. /* setup mailbox inbox registerss */
  1004. mbx.phys_addr = tx->phys_addr;
  1005. mbx.cnsmr_index = tx->hw_cons_phys_addr;
  1006. mbx.size = tx->num_desc;
  1007. if (adapter->flags & QLCNIC_MSIX_ENABLED)
  1008. msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
  1009. else
  1010. msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
  1011. if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
  1012. mbx.intr_id = msix_id;
  1013. else
  1014. mbx.intr_id = 0xffff;
  1015. mbx.src = 0;
  1016. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
  1017. cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
  1018. cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES;
  1019. buf = &cmd.req.arg[6];
  1020. memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
  1021. /* send the mailbox command*/
  1022. err = qlcnic_issue_cmd(adapter, &cmd);
  1023. if (err) {
  1024. dev_err(&adapter->pdev->dev,
  1025. "Failed to create Tx ctx in firmware 0x%x\n", err);
  1026. goto out;
  1027. }
  1028. mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
  1029. tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
  1030. tx->ctx_id = mbx_out->ctx_id;
  1031. if (adapter->flags & QLCNIC_MSIX_ENABLED) {
  1032. intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
  1033. tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
  1034. }
  1035. dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n",
  1036. tx->ctx_id, mbx_out->state);
  1037. out:
  1038. qlcnic_free_mbx_args(&cmd);
  1039. return err;
  1040. }
  1041. int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
  1042. u32 beacon)
  1043. {
  1044. struct qlcnic_cmd_args cmd;
  1045. u32 mbx_in;
  1046. int i, status = 0;
  1047. if (state) {
  1048. /* Get LED configuration */
  1049. qlcnic_alloc_mbx_args(&cmd, adapter,
  1050. QLCNIC_CMD_GET_LED_CONFIG);
  1051. status = qlcnic_issue_cmd(adapter, &cmd);
  1052. if (status) {
  1053. dev_err(&adapter->pdev->dev,
  1054. "Get led config failed.\n");
  1055. goto mbx_err;
  1056. } else {
  1057. for (i = 0; i < 4; i++)
  1058. adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1];
  1059. }
  1060. qlcnic_free_mbx_args(&cmd);
  1061. /* Set LED Configuration */
  1062. mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
  1063. LSW(QLC_83XX_LED_CONFIG);
  1064. qlcnic_alloc_mbx_args(&cmd, adapter,
  1065. QLCNIC_CMD_SET_LED_CONFIG);
  1066. cmd.req.arg[1] = mbx_in;
  1067. cmd.req.arg[2] = mbx_in;
  1068. cmd.req.arg[3] = mbx_in;
  1069. if (beacon)
  1070. cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
  1071. status = qlcnic_issue_cmd(adapter, &cmd);
  1072. if (status) {
  1073. dev_err(&adapter->pdev->dev,
  1074. "Set led config failed.\n");
  1075. }
  1076. mbx_err:
  1077. qlcnic_free_mbx_args(&cmd);
  1078. return status;
  1079. } else {
  1080. /* Restoring default LED configuration */
  1081. qlcnic_alloc_mbx_args(&cmd, adapter,
  1082. QLCNIC_CMD_SET_LED_CONFIG);
  1083. cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
  1084. cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
  1085. cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
  1086. if (beacon)
  1087. cmd.req.arg[4] = adapter->ahw->mbox_reg[3];
  1088. status = qlcnic_issue_cmd(adapter, &cmd);
  1089. if (status)
  1090. dev_err(&adapter->pdev->dev,
  1091. "Restoring led config failed.\n");
  1092. qlcnic_free_mbx_args(&cmd);
  1093. return status;
  1094. }
  1095. }
  1096. void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
  1097. int enable)
  1098. {
  1099. struct qlcnic_cmd_args cmd;
  1100. int status;
  1101. if (enable) {
  1102. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC);
  1103. cmd.req.arg[1] = 1 | BIT_0;
  1104. } else {
  1105. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
  1106. cmd.req.arg[1] = 0 | BIT_0;
  1107. }
  1108. status = qlcnic_issue_cmd(adapter, &cmd);
  1109. if (status)
  1110. dev_err(&adapter->pdev->dev,
  1111. "Failed to %s in NIC IDC function event.\n",
  1112. (enable ? "register" : "unregister"));
  1113. qlcnic_free_mbx_args(&cmd);
  1114. }
  1115. int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
  1116. {
  1117. struct qlcnic_cmd_args cmd;
  1118. int err;
  1119. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
  1120. cmd.req.arg[1] = adapter->ahw->port_config;
  1121. err = qlcnic_issue_cmd(adapter, &cmd);
  1122. if (err)
  1123. dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
  1124. qlcnic_free_mbx_args(&cmd);
  1125. return err;
  1126. }
  1127. int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
  1128. {
  1129. struct qlcnic_cmd_args cmd;
  1130. int err;
  1131. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
  1132. err = qlcnic_issue_cmd(adapter, &cmd);
  1133. if (err)
  1134. dev_info(&adapter->pdev->dev, "Get Port config failed\n");
  1135. else
  1136. adapter->ahw->port_config = cmd.rsp.arg[1];
  1137. qlcnic_free_mbx_args(&cmd);
  1138. return err;
  1139. }
  1140. int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
  1141. {
  1142. int err;
  1143. u32 temp;
  1144. struct qlcnic_cmd_args cmd;
  1145. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
  1146. temp = adapter->recv_ctx->context_id << 16;
  1147. cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
  1148. err = qlcnic_issue_cmd(adapter, &cmd);
  1149. if (err)
  1150. dev_info(&adapter->pdev->dev,
  1151. "Setup linkevent mailbox failed\n");
  1152. qlcnic_free_mbx_args(&cmd);
  1153. return err;
  1154. }
  1155. int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
  1156. {
  1157. int err;
  1158. u32 temp;
  1159. struct qlcnic_cmd_args cmd;
  1160. if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
  1161. return -EIO;
  1162. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
  1163. temp = adapter->recv_ctx->context_id << 16;
  1164. cmd.req.arg[1] = (mode ? 1 : 0) | temp;
  1165. err = qlcnic_issue_cmd(adapter, &cmd);
  1166. if (err)
  1167. dev_info(&adapter->pdev->dev,
  1168. "Promiscous mode config failed\n");
  1169. qlcnic_free_mbx_args(&cmd);
  1170. return err;
  1171. }
  1172. int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
  1173. {
  1174. struct qlcnic_hardware_context *ahw = adapter->ahw;
  1175. int status = 0;
  1176. u32 config;
  1177. status = qlcnic_83xx_get_port_config(adapter);
  1178. if (status)
  1179. return status;
  1180. config = ahw->port_config;
  1181. if (mode == QLCNIC_ILB_MODE)
  1182. ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
  1183. if (mode == QLCNIC_ELB_MODE)
  1184. ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
  1185. status = qlcnic_83xx_set_port_config(adapter);
  1186. if (status) {
  1187. dev_err(&adapter->pdev->dev,
  1188. "Failed to Set Loopback Mode = 0x%x.\n",
  1189. ahw->port_config);
  1190. ahw->port_config = config;
  1191. return status;
  1192. }
  1193. qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
  1194. QLCNIC_MAC_ADD);
  1195. return status;
  1196. }
  1197. int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
  1198. {
  1199. struct qlcnic_hardware_context *ahw = adapter->ahw;
  1200. int status = 0;
  1201. u32 config = ahw->port_config;
  1202. if (mode == QLCNIC_ILB_MODE)
  1203. ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
  1204. if (mode == QLCNIC_ELB_MODE)
  1205. ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
  1206. status = qlcnic_83xx_set_port_config(adapter);
  1207. if (status) {
  1208. dev_err(&adapter->pdev->dev,
  1209. "Failed to Clear Loopback Mode = 0x%x.\n",
  1210. ahw->port_config);
  1211. ahw->port_config = config;
  1212. return status;
  1213. }
  1214. qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
  1215. QLCNIC_MAC_DEL);
  1216. return status;
  1217. }
  1218. void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
  1219. int mode)
  1220. {
  1221. int err;
  1222. u32 temp;
  1223. struct qlcnic_cmd_args cmd;
  1224. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR);
  1225. if (mode == QLCNIC_IP_UP) {
  1226. temp = adapter->recv_ctx->context_id << 16;
  1227. cmd.req.arg[1] = 1 | temp;
  1228. } else {
  1229. temp = adapter->recv_ctx->context_id << 16;
  1230. cmd.req.arg[1] = 2 | temp;
  1231. }
  1232. cmd.req.arg[2] = ntohl(ip);
  1233. err = qlcnic_issue_cmd(adapter, &cmd);
  1234. if (err != QLCNIC_RCODE_SUCCESS)
  1235. dev_err(&adapter->netdev->dev,
  1236. "could not notify %s IP 0x%x request\n",
  1237. (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
  1238. qlcnic_free_mbx_args(&cmd);
  1239. }
  1240. int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
  1241. {
  1242. int err;
  1243. u32 temp, arg1;
  1244. struct qlcnic_cmd_args cmd;
  1245. if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
  1246. return 0;
  1247. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
  1248. temp = adapter->recv_ctx->context_id << 16;
  1249. arg1 = (mode ? (BIT_0 | BIT_1 | BIT_3) : 0) | temp;
  1250. cmd.req.arg[1] = arg1;
  1251. err = qlcnic_issue_cmd(adapter, &cmd);
  1252. if (err)
  1253. dev_info(&adapter->pdev->dev, "LRO config failed\n");
  1254. qlcnic_free_mbx_args(&cmd);
  1255. return err;
  1256. }
  1257. int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
  1258. {
  1259. int err;
  1260. u32 word;
  1261. struct qlcnic_cmd_args cmd;
  1262. const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
  1263. 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
  1264. 0x255b0ec26d5a56daULL };
  1265. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
  1266. /*
  1267. * RSS request:
  1268. * bits 3-0: Rsvd
  1269. * 5-4: hash_type_ipv4
  1270. * 7-6: hash_type_ipv6
  1271. * 8: enable
  1272. * 9: use indirection table
  1273. * 16-31: indirection table mask
  1274. */
  1275. word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
  1276. ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
  1277. ((u32)(enable & 0x1) << 8) |
  1278. ((0x7ULL) << 16);
  1279. cmd.req.arg[1] = (adapter->recv_ctx->context_id);
  1280. cmd.req.arg[2] = word;
  1281. memcpy(&cmd.req.arg[4], key, sizeof(key));
  1282. err = qlcnic_issue_cmd(adapter, &cmd);
  1283. if (err)
  1284. dev_info(&adapter->pdev->dev, "RSS config failed\n");
  1285. qlcnic_free_mbx_args(&cmd);
  1286. return err;
  1287. }
  1288. int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
  1289. __le16 vlan_id, u8 op)
  1290. {
  1291. int err;
  1292. u32 *buf;
  1293. struct qlcnic_cmd_args cmd;
  1294. struct qlcnic_macvlan_mbx mv;
  1295. if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
  1296. return -EIO;
  1297. err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
  1298. if (err)
  1299. return err;
  1300. cmd.req.arg[1] = op | (1 << 8) |
  1301. (adapter->recv_ctx->context_id << 16);
  1302. mv.vlan = le16_to_cpu(vlan_id);
  1303. memcpy(&mv.mac, addr, ETH_ALEN);
  1304. buf = &cmd.req.arg[2];
  1305. memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
  1306. err = qlcnic_issue_cmd(adapter, &cmd);
  1307. if (err)
  1308. dev_err(&adapter->pdev->dev,
  1309. "MAC-VLAN %s to CAM failed, err=%d.\n",
  1310. ((op == 1) ? "add " : "delete "), err);
  1311. qlcnic_free_mbx_args(&cmd);
  1312. return err;
  1313. }
  1314. void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
  1315. __le16 vlan_id)
  1316. {
  1317. u8 mac[ETH_ALEN];
  1318. memcpy(&mac, addr, ETH_ALEN);
  1319. qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
  1320. }
  1321. void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
  1322. u8 type, struct qlcnic_cmd_args *cmd)
  1323. {
  1324. switch (type) {
  1325. case QLCNIC_SET_STATION_MAC:
  1326. case QLCNIC_SET_FAC_DEF_MAC:
  1327. memcpy(&cmd->req.arg[2], mac, sizeof(u32));
  1328. memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
  1329. break;
  1330. }
  1331. cmd->req.arg[1] = type;
  1332. }
  1333. int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
  1334. {
  1335. int err, i;
  1336. struct qlcnic_cmd_args cmd;
  1337. u32 mac_low, mac_high;
  1338. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
  1339. qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
  1340. err = qlcnic_issue_cmd(adapter, &cmd);
  1341. if (err == QLCNIC_RCODE_SUCCESS) {
  1342. mac_low = cmd.rsp.arg[1];
  1343. mac_high = cmd.rsp.arg[2];
  1344. for (i = 0; i < 2; i++)
  1345. mac[i] = (u8) (mac_high >> ((1 - i) * 8));
  1346. for (i = 2; i < 6; i++)
  1347. mac[i] = (u8) (mac_low >> ((5 - i) * 8));
  1348. } else {
  1349. dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n",
  1350. err);
  1351. err = -EIO;
  1352. }
  1353. qlcnic_free_mbx_args(&cmd);
  1354. return err;
  1355. }
  1356. void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
  1357. {
  1358. int err;
  1359. u32 temp;
  1360. struct qlcnic_cmd_args cmd;
  1361. struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
  1362. if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
  1363. return;
  1364. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
  1365. cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16);
  1366. cmd.req.arg[3] = coal->flag;
  1367. temp = coal->rx_time_us << 16;
  1368. cmd.req.arg[2] = coal->rx_packets | temp;
  1369. err = qlcnic_issue_cmd(adapter, &cmd);
  1370. if (err != QLCNIC_RCODE_SUCCESS)
  1371. dev_info(&adapter->pdev->dev,
  1372. "Failed to send interrupt coalescence parameters\n");
  1373. qlcnic_free_mbx_args(&cmd);
  1374. }
  1375. static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
  1376. u32 data[])
  1377. {
  1378. u8 link_status, duplex;
  1379. /* link speed */
  1380. link_status = LSB(data[3]) & 1;
  1381. adapter->ahw->link_speed = MSW(data[2]);
  1382. adapter->ahw->link_autoneg = MSB(MSW(data[3]));
  1383. adapter->ahw->module_type = MSB(LSW(data[3]));
  1384. duplex = LSB(MSW(data[3]));
  1385. if (duplex)
  1386. adapter->ahw->link_duplex = DUPLEX_FULL;
  1387. else
  1388. adapter->ahw->link_duplex = DUPLEX_HALF;
  1389. adapter->ahw->has_link_events = 1;
  1390. qlcnic_advert_link_change(adapter, link_status);
  1391. }
  1392. irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
  1393. {
  1394. struct qlcnic_adapter *adapter = data;
  1395. qlcnic_83xx_process_aen(adapter);
  1396. return IRQ_HANDLED;
  1397. }
  1398. int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
  1399. {
  1400. int err = -EIO;
  1401. struct qlcnic_cmd_args cmd;
  1402. if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
  1403. dev_err(&adapter->pdev->dev,
  1404. "%s: Error, invoked by non management func\n",
  1405. __func__);
  1406. return err;
  1407. }
  1408. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
  1409. cmd.req.arg[1] = (port & 0xf) | BIT_4;
  1410. err = qlcnic_issue_cmd(adapter, &cmd);
  1411. if (err != QLCNIC_RCODE_SUCCESS) {
  1412. dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n",
  1413. err);
  1414. err = -EIO;
  1415. }
  1416. qlcnic_free_mbx_args(&cmd);
  1417. return err;
  1418. }
  1419. int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
  1420. struct qlcnic_info *nic)
  1421. {
  1422. int i, err = -EIO;
  1423. struct qlcnic_cmd_args cmd;
  1424. if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
  1425. dev_err(&adapter->pdev->dev,
  1426. "%s: Error, invoked by non management func\n",
  1427. __func__);
  1428. return err;
  1429. }
  1430. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
  1431. cmd.req.arg[1] = (nic->pci_func << 16);
  1432. cmd.req.arg[2] = 0x1 << 16;
  1433. cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
  1434. cmd.req.arg[4] = nic->capabilities;
  1435. cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
  1436. cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
  1437. cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
  1438. for (i = 8; i < 32; i++)
  1439. cmd.req.arg[i] = 0;
  1440. err = qlcnic_issue_cmd(adapter, &cmd);
  1441. if (err != QLCNIC_RCODE_SUCCESS) {
  1442. dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n",
  1443. err);
  1444. err = -EIO;
  1445. }
  1446. qlcnic_free_mbx_args(&cmd);
  1447. return err;
  1448. }
  1449. int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
  1450. struct qlcnic_info *npar_info, u8 func_id)
  1451. {
  1452. int err;
  1453. u32 temp;
  1454. u8 op = 0;
  1455. struct qlcnic_cmd_args cmd;
  1456. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
  1457. if (func_id != adapter->ahw->pci_func) {
  1458. temp = func_id << 16;
  1459. cmd.req.arg[1] = op | BIT_31 | temp;
  1460. } else {
  1461. cmd.req.arg[1] = adapter->ahw->pci_func << 16;
  1462. }
  1463. err = qlcnic_issue_cmd(adapter, &cmd);
  1464. if (err) {
  1465. dev_info(&adapter->pdev->dev,
  1466. "Failed to get nic info %d\n", err);
  1467. goto out;
  1468. }
  1469. npar_info->op_type = cmd.rsp.arg[1];
  1470. npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
  1471. npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
  1472. npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
  1473. npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
  1474. npar_info->capabilities = cmd.rsp.arg[4];
  1475. npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
  1476. npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
  1477. npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
  1478. npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
  1479. npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
  1480. npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
  1481. if (cmd.rsp.arg[8] & 0x1)
  1482. npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
  1483. if (cmd.rsp.arg[8] & 0x10000) {
  1484. temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
  1485. npar_info->max_linkspeed_reg_offset = temp;
  1486. }
  1487. out:
  1488. qlcnic_free_mbx_args(&cmd);
  1489. return err;
  1490. }
  1491. int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
  1492. struct qlcnic_pci_info *pci_info)
  1493. {
  1494. int i, err = 0, j = 0;
  1495. u32 temp;
  1496. struct qlcnic_cmd_args cmd;
  1497. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
  1498. err = qlcnic_issue_cmd(adapter, &cmd);
  1499. adapter->ahw->act_pci_func = 0;
  1500. if (err == QLCNIC_RCODE_SUCCESS) {
  1501. pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
  1502. dev_info(&adapter->pdev->dev,
  1503. "%s: total functions = %d\n",
  1504. __func__, pci_info->func_count);
  1505. for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
  1506. pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
  1507. pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
  1508. i++;
  1509. pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
  1510. if (pci_info->type == QLCNIC_TYPE_NIC)
  1511. adapter->ahw->act_pci_func++;
  1512. temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
  1513. pci_info->default_port = temp;
  1514. i++;
  1515. pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
  1516. temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
  1517. pci_info->tx_max_bw = temp;
  1518. i = i + 2;
  1519. memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
  1520. i++;
  1521. memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
  1522. i = i + 3;
  1523. dev_info(&adapter->pdev->dev, "%s:\n"
  1524. "\tid = %d active = %d type = %d\n"
  1525. "\tport = %d min bw = %d max bw = %d\n"
  1526. "\tmac_addr = %pM\n", __func__,
  1527. pci_info->id, pci_info->active, pci_info->type,
  1528. pci_info->default_port, pci_info->tx_min_bw,
  1529. pci_info->tx_max_bw, pci_info->mac);
  1530. }
  1531. } else {
  1532. dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
  1533. err);
  1534. err = -EIO;
  1535. }
  1536. qlcnic_free_mbx_args(&cmd);
  1537. return err;
  1538. }
  1539. int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
  1540. {
  1541. int i, index, err;
  1542. bool type;
  1543. u8 max_ints;
  1544. u32 val, temp;
  1545. struct qlcnic_cmd_args cmd;
  1546. max_ints = adapter->ahw->num_msix;
  1547. qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
  1548. cmd.req.arg[1] = max_ints;
  1549. for (i = 0, index = 2; i < max_ints; i++) {
  1550. type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
  1551. val = type | (adapter->ahw->intr_tbl[i].type << 4);
  1552. if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
  1553. val |= (adapter->ahw->intr_tbl[i].id << 16);
  1554. cmd.req.arg[index++] = val;
  1555. }
  1556. err = qlcnic_issue_cmd(adapter, &cmd);
  1557. if (err) {
  1558. dev_err(&adapter->pdev->dev,
  1559. "Failed to configure interrupts 0x%x\n", err);
  1560. goto out;
  1561. }
  1562. max_ints = cmd.rsp.arg[1];
  1563. for (i = 0, index = 2; i < max_ints; i++, index += 2) {
  1564. val = cmd.rsp.arg[index];
  1565. if (LSB(val)) {
  1566. dev_info(&adapter->pdev->dev,
  1567. "Can't configure interrupt %d\n",
  1568. adapter->ahw->intr_tbl[i].id);
  1569. continue;
  1570. }
  1571. if (op_type) {
  1572. adapter->ahw->intr_tbl[i].id = MSW(val);
  1573. adapter->ahw->intr_tbl[i].enabled = 1;
  1574. temp = cmd.rsp.arg[index + 1];
  1575. adapter->ahw->intr_tbl[i].src = temp;
  1576. } else {
  1577. adapter->ahw->intr_tbl[i].id = i;
  1578. adapter->ahw->intr_tbl[i].enabled = 0;
  1579. adapter->ahw->intr_tbl[i].src = 0;
  1580. }
  1581. }
  1582. out:
  1583. qlcnic_free_mbx_args(&cmd);
  1584. return err;
  1585. }