i40e_dcb.c 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright(c) 2013 - 2021 Intel Corporation. */
  3. #include <linux/bitfield.h>
  4. #include "i40e_adminq.h"
  5. #include "i40e_alloc.h"
  6. #include "i40e_dcb.h"
  7. #include "i40e_prototype.h"
  8. /**
  9. * i40e_get_dcbx_status
  10. * @hw: pointer to the hw struct
  11. * @status: Embedded DCBX Engine Status
  12. *
  13. * Get the DCBX status from the Firmware
  14. **/
  15. int i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
  16. {
  17. u32 reg;
  18. if (!status)
  19. return -EINVAL;
  20. reg = rd32(hw, I40E_PRTDCB_GENS);
  21. *status = FIELD_GET(I40E_PRTDCB_GENS_DCBX_STATUS_MASK, reg);
  22. return 0;
  23. }
  24. /**
  25. * i40e_parse_ieee_etscfg_tlv
  26. * @tlv: IEEE 802.1Qaz ETS CFG TLV
  27. * @dcbcfg: Local store to update ETS CFG data
  28. *
  29. * Parses IEEE 802.1Qaz ETS CFG TLV
  30. **/
  31. static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
  32. struct i40e_dcbx_config *dcbcfg)
  33. {
  34. struct i40e_dcb_ets_config *etscfg;
  35. u8 *buf = tlv->tlvinfo;
  36. u16 offset = 0;
  37. u8 priority;
  38. int i;
  39. /* First Octet post subtype
  40. * --------------------------
  41. * |will-|CBS | Re- | Max |
  42. * |ing | |served| TCs |
  43. * --------------------------
  44. * |1bit | 1bit|3 bits|3bits|
  45. */
  46. etscfg = &dcbcfg->etscfg;
  47. etscfg->willing = FIELD_GET(I40E_IEEE_ETS_WILLING_MASK, buf[offset]);
  48. etscfg->cbs = FIELD_GET(I40E_IEEE_ETS_CBS_MASK, buf[offset]);
  49. etscfg->maxtcs = FIELD_GET(I40E_IEEE_ETS_MAXTC_MASK, buf[offset]);
  50. /* Move offset to Priority Assignment Table */
  51. offset++;
  52. /* Priority Assignment Table (4 octets)
  53. * Octets:| 1 | 2 | 3 | 4 |
  54. * -----------------------------------------
  55. * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  56. * -----------------------------------------
  57. * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
  58. * -----------------------------------------
  59. */
  60. for (i = 0; i < 4; i++) {
  61. priority = FIELD_GET(I40E_IEEE_ETS_PRIO_1_MASK, buf[offset]);
  62. etscfg->prioritytable[i * 2] = priority;
  63. priority = FIELD_GET(I40E_IEEE_ETS_PRIO_0_MASK, buf[offset]);
  64. etscfg->prioritytable[i * 2 + 1] = priority;
  65. offset++;
  66. }
  67. /* TC Bandwidth Table (8 octets)
  68. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  69. * ---------------------------------
  70. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  71. * ---------------------------------
  72. */
  73. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  74. etscfg->tcbwtable[i] = buf[offset++];
  75. /* TSA Assignment Table (8 octets)
  76. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  77. * ---------------------------------
  78. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  79. * ---------------------------------
  80. */
  81. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  82. etscfg->tsatable[i] = buf[offset++];
  83. }
  84. /**
  85. * i40e_parse_ieee_etsrec_tlv
  86. * @tlv: IEEE 802.1Qaz ETS REC TLV
  87. * @dcbcfg: Local store to update ETS REC data
  88. *
  89. * Parses IEEE 802.1Qaz ETS REC TLV
  90. **/
  91. static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
  92. struct i40e_dcbx_config *dcbcfg)
  93. {
  94. u8 *buf = tlv->tlvinfo;
  95. u16 offset = 0;
  96. u8 priority;
  97. int i;
  98. /* Move offset to priority table */
  99. offset++;
  100. /* Priority Assignment Table (4 octets)
  101. * Octets:| 1 | 2 | 3 | 4 |
  102. * -----------------------------------------
  103. * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  104. * -----------------------------------------
  105. * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
  106. * -----------------------------------------
  107. */
  108. for (i = 0; i < 4; i++) {
  109. priority = FIELD_GET(I40E_IEEE_ETS_PRIO_1_MASK, buf[offset]);
  110. dcbcfg->etsrec.prioritytable[i * 2] = priority;
  111. priority = FIELD_GET(I40E_IEEE_ETS_PRIO_0_MASK, buf[offset]);
  112. dcbcfg->etsrec.prioritytable[(i * 2) + 1] = priority;
  113. offset++;
  114. }
  115. /* TC Bandwidth Table (8 octets)
  116. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  117. * ---------------------------------
  118. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  119. * ---------------------------------
  120. */
  121. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  122. dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
  123. /* TSA Assignment Table (8 octets)
  124. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  125. * ---------------------------------
  126. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  127. * ---------------------------------
  128. */
  129. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  130. dcbcfg->etsrec.tsatable[i] = buf[offset++];
  131. }
  132. /**
  133. * i40e_parse_ieee_pfccfg_tlv
  134. * @tlv: IEEE 802.1Qaz PFC CFG TLV
  135. * @dcbcfg: Local store to update PFC CFG data
  136. *
  137. * Parses IEEE 802.1Qaz PFC CFG TLV
  138. **/
  139. static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
  140. struct i40e_dcbx_config *dcbcfg)
  141. {
  142. u8 *buf = tlv->tlvinfo;
  143. /* ----------------------------------------
  144. * |will-|MBC | Re- | PFC | PFC Enable |
  145. * |ing | |served| cap | |
  146. * -----------------------------------------
  147. * |1bit | 1bit|2 bits|4bits| 1 octet |
  148. */
  149. dcbcfg->pfc.willing = FIELD_GET(I40E_IEEE_PFC_WILLING_MASK, buf[0]);
  150. dcbcfg->pfc.mbc = FIELD_GET(I40E_IEEE_PFC_MBC_MASK, buf[0]);
  151. dcbcfg->pfc.pfccap = FIELD_GET(I40E_IEEE_PFC_CAP_MASK, buf[0]);
  152. dcbcfg->pfc.pfcenable = buf[1];
  153. }
  154. /**
  155. * i40e_parse_ieee_app_tlv
  156. * @tlv: IEEE 802.1Qaz APP TLV
  157. * @dcbcfg: Local store to update APP PRIO data
  158. *
  159. * Parses IEEE 802.1Qaz APP PRIO TLV
  160. **/
  161. static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
  162. struct i40e_dcbx_config *dcbcfg)
  163. {
  164. u16 typelength;
  165. u16 offset = 0;
  166. u16 length;
  167. int i = 0;
  168. u8 *buf;
  169. typelength = ntohs(tlv->typelength);
  170. length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  171. buf = tlv->tlvinfo;
  172. /* The App priority table starts 5 octets after TLV header */
  173. length -= (sizeof(tlv->ouisubtype) + 1);
  174. /* Move offset to App Priority Table */
  175. offset++;
  176. /* Application Priority Table (3 octets)
  177. * Octets:| 1 | 2 | 3 |
  178. * -----------------------------------------
  179. * |Priority|Rsrvd| Sel | Protocol ID |
  180. * -----------------------------------------
  181. * Bits:|23 21|20 19|18 16|15 0|
  182. * -----------------------------------------
  183. */
  184. while (offset < length) {
  185. dcbcfg->app[i].priority = FIELD_GET(I40E_IEEE_APP_PRIO_MASK,
  186. buf[offset]);
  187. dcbcfg->app[i].selector = FIELD_GET(I40E_IEEE_APP_SEL_MASK,
  188. buf[offset]);
  189. dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
  190. buf[offset + 2];
  191. /* Move to next app */
  192. offset += 3;
  193. i++;
  194. if (i >= I40E_DCBX_MAX_APPS)
  195. break;
  196. }
  197. dcbcfg->numapps = i;
  198. }
  199. /**
  200. * i40e_parse_ieee_tlv
  201. * @tlv: IEEE 802.1Qaz TLV
  202. * @dcbcfg: Local store to update ETS REC data
  203. *
  204. * Get the TLV subtype and send it to parsing function
  205. * based on the subtype value
  206. **/
  207. static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
  208. struct i40e_dcbx_config *dcbcfg)
  209. {
  210. u32 ouisubtype;
  211. u8 subtype;
  212. ouisubtype = ntohl(tlv->ouisubtype);
  213. subtype = FIELD_GET(I40E_LLDP_TLV_SUBTYPE_MASK, ouisubtype);
  214. switch (subtype) {
  215. case I40E_IEEE_SUBTYPE_ETS_CFG:
  216. i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
  217. break;
  218. case I40E_IEEE_SUBTYPE_ETS_REC:
  219. i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
  220. break;
  221. case I40E_IEEE_SUBTYPE_PFC_CFG:
  222. i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
  223. break;
  224. case I40E_IEEE_SUBTYPE_APP_PRI:
  225. i40e_parse_ieee_app_tlv(tlv, dcbcfg);
  226. break;
  227. default:
  228. break;
  229. }
  230. }
  231. /**
  232. * i40e_parse_cee_pgcfg_tlv
  233. * @tlv: CEE DCBX PG CFG TLV
  234. * @dcbcfg: Local store to update ETS CFG data
  235. *
  236. * Parses CEE DCBX PG CFG TLV
  237. **/
  238. static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv,
  239. struct i40e_dcbx_config *dcbcfg)
  240. {
  241. struct i40e_dcb_ets_config *etscfg;
  242. u8 *buf = tlv->tlvinfo;
  243. u16 offset = 0;
  244. u8 priority;
  245. int i;
  246. etscfg = &dcbcfg->etscfg;
  247. if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
  248. etscfg->willing = 1;
  249. etscfg->cbs = 0;
  250. /* Priority Group Table (4 octets)
  251. * Octets:| 1 | 2 | 3 | 4 |
  252. * -----------------------------------------
  253. * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  254. * -----------------------------------------
  255. * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
  256. * -----------------------------------------
  257. */
  258. for (i = 0; i < 4; i++) {
  259. priority = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK, buf[offset]);
  260. etscfg->prioritytable[i * 2] = priority;
  261. priority = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK, buf[offset]);
  262. etscfg->prioritytable[i * 2 + 1] = priority;
  263. offset++;
  264. }
  265. /* PG Percentage Table (8 octets)
  266. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  267. * ---------------------------------
  268. * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7|
  269. * ---------------------------------
  270. */
  271. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  272. etscfg->tcbwtable[i] = buf[offset++];
  273. /* Number of TCs supported (1 octet) */
  274. etscfg->maxtcs = buf[offset];
  275. }
  276. /**
  277. * i40e_parse_cee_pfccfg_tlv
  278. * @tlv: CEE DCBX PFC CFG TLV
  279. * @dcbcfg: Local store to update PFC CFG data
  280. *
  281. * Parses CEE DCBX PFC CFG TLV
  282. **/
  283. static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv,
  284. struct i40e_dcbx_config *dcbcfg)
  285. {
  286. u8 *buf = tlv->tlvinfo;
  287. if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK)
  288. dcbcfg->pfc.willing = 1;
  289. /* ------------------------
  290. * | PFC Enable | PFC TCs |
  291. * ------------------------
  292. * | 1 octet | 1 octet |
  293. */
  294. dcbcfg->pfc.pfcenable = buf[0];
  295. dcbcfg->pfc.pfccap = buf[1];
  296. }
  297. /**
  298. * i40e_parse_cee_app_tlv
  299. * @tlv: CEE DCBX APP TLV
  300. * @dcbcfg: Local store to update APP PRIO data
  301. *
  302. * Parses CEE DCBX APP PRIO TLV
  303. **/
  304. static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv,
  305. struct i40e_dcbx_config *dcbcfg)
  306. {
  307. u16 length, typelength, offset = 0;
  308. struct i40e_cee_app_prio *app;
  309. u8 i;
  310. typelength = ntohs(tlv->hdr.typelen);
  311. length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  312. dcbcfg->numapps = length / sizeof(*app);
  313. if (!dcbcfg->numapps)
  314. return;
  315. if (dcbcfg->numapps > I40E_DCBX_MAX_APPS)
  316. dcbcfg->numapps = I40E_DCBX_MAX_APPS;
  317. for (i = 0; i < dcbcfg->numapps; i++) {
  318. u8 up, selector;
  319. app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset);
  320. for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) {
  321. if (app->prio_map & BIT(up))
  322. break;
  323. }
  324. dcbcfg->app[i].priority = up;
  325. /* Get Selector from lower 2 bits, and convert to IEEE */
  326. selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK);
  327. switch (selector) {
  328. case I40E_CEE_APP_SEL_ETHTYPE:
  329. dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  330. break;
  331. case I40E_CEE_APP_SEL_TCPIP:
  332. dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
  333. break;
  334. default:
  335. /* Keep selector as it is for unknown types */
  336. dcbcfg->app[i].selector = selector;
  337. }
  338. dcbcfg->app[i].protocolid = ntohs(app->protocol);
  339. /* Move to next app */
  340. offset += sizeof(*app);
  341. }
  342. }
  343. /**
  344. * i40e_parse_cee_tlv
  345. * @tlv: CEE DCBX TLV
  346. * @dcbcfg: Local store to update DCBX config data
  347. *
  348. * Get the TLV subtype and send it to parsing function
  349. * based on the subtype value
  350. **/
  351. static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv,
  352. struct i40e_dcbx_config *dcbcfg)
  353. {
  354. u16 len, tlvlen, sublen, typelength;
  355. struct i40e_cee_feat_tlv *sub_tlv;
  356. u8 subtype, feat_tlv_count = 0;
  357. u32 ouisubtype;
  358. ouisubtype = ntohl(tlv->ouisubtype);
  359. subtype = FIELD_GET(I40E_LLDP_TLV_SUBTYPE_MASK, ouisubtype);
  360. /* Return if not CEE DCBX */
  361. if (subtype != I40E_CEE_DCBX_TYPE)
  362. return;
  363. typelength = ntohs(tlv->typelength);
  364. tlvlen = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  365. len = sizeof(tlv->typelength) + sizeof(ouisubtype) +
  366. sizeof(struct i40e_cee_ctrl_tlv);
  367. /* Return if no CEE DCBX Feature TLVs */
  368. if (tlvlen <= len)
  369. return;
  370. sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len);
  371. while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) {
  372. typelength = ntohs(sub_tlv->hdr.typelen);
  373. sublen = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  374. subtype = FIELD_GET(I40E_LLDP_TLV_TYPE_MASK, typelength);
  375. switch (subtype) {
  376. case I40E_CEE_SUBTYPE_PG_CFG:
  377. i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg);
  378. break;
  379. case I40E_CEE_SUBTYPE_PFC_CFG:
  380. i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg);
  381. break;
  382. case I40E_CEE_SUBTYPE_APP_PRI:
  383. i40e_parse_cee_app_tlv(sub_tlv, dcbcfg);
  384. break;
  385. default:
  386. return; /* Invalid Sub-type return */
  387. }
  388. feat_tlv_count++;
  389. /* Move to next sub TLV */
  390. sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv +
  391. sizeof(sub_tlv->hdr.typelen) +
  392. sublen);
  393. }
  394. }
  395. /**
  396. * i40e_parse_org_tlv
  397. * @tlv: Organization specific TLV
  398. * @dcbcfg: Local store to update ETS REC data
  399. *
  400. * Currently only IEEE 802.1Qaz TLV is supported, all others
  401. * will be returned
  402. **/
  403. static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
  404. struct i40e_dcbx_config *dcbcfg)
  405. {
  406. u32 ouisubtype;
  407. u32 oui;
  408. ouisubtype = ntohl(tlv->ouisubtype);
  409. oui = FIELD_GET(I40E_LLDP_TLV_OUI_MASK, ouisubtype);
  410. switch (oui) {
  411. case I40E_IEEE_8021QAZ_OUI:
  412. i40e_parse_ieee_tlv(tlv, dcbcfg);
  413. break;
  414. case I40E_CEE_DCBX_OUI:
  415. i40e_parse_cee_tlv(tlv, dcbcfg);
  416. break;
  417. default:
  418. break;
  419. }
  420. }
  421. /**
  422. * i40e_lldp_to_dcb_config
  423. * @lldpmib: LLDPDU to be parsed
  424. * @dcbcfg: store for LLDPDU data
  425. *
  426. * Parse DCB configuration from the LLDPDU
  427. **/
  428. int i40e_lldp_to_dcb_config(u8 *lldpmib,
  429. struct i40e_dcbx_config *dcbcfg)
  430. {
  431. struct i40e_lldp_org_tlv *tlv;
  432. u16 typelength;
  433. u16 offset = 0;
  434. int ret = 0;
  435. u16 length;
  436. u16 type;
  437. if (!lldpmib || !dcbcfg)
  438. return -EINVAL;
  439. /* set to the start of LLDPDU */
  440. lldpmib += ETH_HLEN;
  441. tlv = (struct i40e_lldp_org_tlv *)lldpmib;
  442. while (1) {
  443. typelength = ntohs(tlv->typelength);
  444. type = FIELD_GET(I40E_LLDP_TLV_TYPE_MASK, typelength);
  445. length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  446. offset += sizeof(typelength) + length;
  447. /* END TLV or beyond LLDPDU size */
  448. if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
  449. break;
  450. switch (type) {
  451. case I40E_TLV_TYPE_ORG:
  452. i40e_parse_org_tlv(tlv, dcbcfg);
  453. break;
  454. default:
  455. break;
  456. }
  457. /* Move to next TLV */
  458. tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
  459. sizeof(tlv->typelength) +
  460. length);
  461. }
  462. return ret;
  463. }
  464. /**
  465. * i40e_aq_get_dcb_config
  466. * @hw: pointer to the hw struct
  467. * @mib_type: mib type for the query
  468. * @bridgetype: bridge type for the query (remote)
  469. * @dcbcfg: store for LLDPDU data
  470. *
  471. * Query DCB configuration from the Firmware
  472. **/
  473. int i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
  474. u8 bridgetype,
  475. struct i40e_dcbx_config *dcbcfg)
  476. {
  477. struct i40e_virt_mem mem;
  478. int ret = 0;
  479. u8 *lldpmib;
  480. /* Allocate the LLDPDU */
  481. ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
  482. if (ret)
  483. return ret;
  484. lldpmib = (u8 *)mem.va;
  485. ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
  486. (void *)lldpmib, I40E_LLDPDU_SIZE,
  487. NULL, NULL, NULL);
  488. if (ret)
  489. goto free_mem;
  490. /* Parse LLDP MIB to get dcb configuration */
  491. ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
  492. free_mem:
  493. i40e_free_virt_mem(hw, &mem);
  494. return ret;
  495. }
  496. /**
  497. * i40e_cee_to_dcb_v1_config
  498. * @cee_cfg: pointer to CEE v1 response configuration struct
  499. * @dcbcfg: DCB configuration struct
  500. *
  501. * Convert CEE v1 configuration from firmware to DCB configuration
  502. **/
  503. static void i40e_cee_to_dcb_v1_config(
  504. struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg,
  505. struct i40e_dcbx_config *dcbcfg)
  506. {
  507. u16 status, tlv_status = le16_to_cpu(cee_cfg->tlv_status);
  508. u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
  509. u8 i, err;
  510. /* CEE PG data to ETS config */
  511. dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
  512. /* Note that the FW creates the oper_prio_tc nibbles reversed
  513. * from those in the CEE Priority Group sub-TLV.
  514. */
  515. for (i = 0; i < 4; i++) {
  516. u8 tc;
  517. tc = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK,
  518. cee_cfg->oper_prio_tc[i]);
  519. dcbcfg->etscfg.prioritytable[i * 2] = tc;
  520. tc = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK,
  521. cee_cfg->oper_prio_tc[i]);
  522. dcbcfg->etscfg.prioritytable[i*2 + 1] = tc;
  523. }
  524. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  525. dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
  526. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  527. if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
  528. /* Map it to next empty TC */
  529. dcbcfg->etscfg.prioritytable[i] =
  530. cee_cfg->oper_num_tc - 1;
  531. dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
  532. } else {
  533. dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
  534. }
  535. }
  536. /* CEE PFC data to ETS config */
  537. dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
  538. dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
  539. status = FIELD_GET(I40E_AQC_CEE_APP_STATUS_MASK, tlv_status);
  540. err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  541. /* Add APPs if Error is False */
  542. if (!err) {
  543. /* CEE operating configuration supports FCoE/iSCSI/FIP only */
  544. dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS;
  545. /* FCoE APP */
  546. dcbcfg->app[0].priority =
  547. FIELD_GET(I40E_AQC_CEE_APP_FCOE_MASK, app_prio);
  548. dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
  549. dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
  550. /* iSCSI APP */
  551. dcbcfg->app[1].priority =
  552. FIELD_GET(I40E_AQC_CEE_APP_ISCSI_MASK, app_prio);
  553. dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP;
  554. dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI;
  555. /* FIP APP */
  556. dcbcfg->app[2].priority =
  557. FIELD_GET(I40E_AQC_CEE_APP_FIP_MASK, app_prio);
  558. dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE;
  559. dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP;
  560. }
  561. }
  562. /**
  563. * i40e_cee_to_dcb_config
  564. * @cee_cfg: pointer to CEE configuration struct
  565. * @dcbcfg: DCB configuration struct
  566. *
  567. * Convert CEE configuration from firmware to DCB configuration
  568. **/
  569. static void i40e_cee_to_dcb_config(
  570. struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg,
  571. struct i40e_dcbx_config *dcbcfg)
  572. {
  573. u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);
  574. u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio);
  575. u8 i, err, sync, oper;
  576. /* CEE PG data to ETS config */
  577. dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;
  578. /* Note that the FW creates the oper_prio_tc nibbles reversed
  579. * from those in the CEE Priority Group sub-TLV.
  580. */
  581. for (i = 0; i < 4; i++) {
  582. u8 tc;
  583. tc = FIELD_GET(I40E_CEE_PGID_PRIO_0_MASK,
  584. cee_cfg->oper_prio_tc[i]);
  585. dcbcfg->etscfg.prioritytable[i * 2] = tc;
  586. tc = FIELD_GET(I40E_CEE_PGID_PRIO_1_MASK,
  587. cee_cfg->oper_prio_tc[i]);
  588. dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc;
  589. }
  590. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  591. dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i];
  592. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  593. if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) {
  594. /* Map it to next empty TC */
  595. dcbcfg->etscfg.prioritytable[i] =
  596. cee_cfg->oper_num_tc - 1;
  597. dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT;
  598. } else {
  599. dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
  600. }
  601. }
  602. /* CEE PFC data to ETS config */
  603. dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en;
  604. dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
  605. i = 0;
  606. status = FIELD_GET(I40E_AQC_CEE_FCOE_STATUS_MASK, tlv_status);
  607. err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  608. sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  609. oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  610. /* Add FCoE APP if Error is False and Oper/Sync is True */
  611. if (!err && sync && oper) {
  612. /* FCoE APP */
  613. dcbcfg->app[i].priority =
  614. FIELD_GET(I40E_AQC_CEE_APP_FCOE_MASK, app_prio);
  615. dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  616. dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE;
  617. i++;
  618. }
  619. status = FIELD_GET(I40E_AQC_CEE_ISCSI_STATUS_MASK, tlv_status);
  620. err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  621. sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  622. oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  623. /* Add iSCSI APP if Error is False and Oper/Sync is True */
  624. if (!err && sync && oper) {
  625. /* iSCSI APP */
  626. dcbcfg->app[i].priority =
  627. FIELD_GET(I40E_AQC_CEE_APP_ISCSI_MASK, app_prio);
  628. dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP;
  629. dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI;
  630. i++;
  631. }
  632. status = FIELD_GET(I40E_AQC_CEE_FIP_STATUS_MASK, tlv_status);
  633. err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0;
  634. sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0;
  635. oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0;
  636. /* Add FIP APP if Error is False and Oper/Sync is True */
  637. if (!err && sync && oper) {
  638. /* FIP APP */
  639. dcbcfg->app[i].priority =
  640. FIELD_GET(I40E_AQC_CEE_APP_FIP_MASK, app_prio);
  641. dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE;
  642. dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP;
  643. i++;
  644. }
  645. dcbcfg->numapps = i;
  646. }
  647. /**
  648. * i40e_get_ieee_dcb_config
  649. * @hw: pointer to the hw struct
  650. *
  651. * Get IEEE mode DCB configuration from the Firmware
  652. **/
  653. static int i40e_get_ieee_dcb_config(struct i40e_hw *hw)
  654. {
  655. int ret = 0;
  656. /* IEEE mode */
  657. hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;
  658. /* Get Local DCB Config */
  659. ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
  660. &hw->local_dcbx_config);
  661. if (ret)
  662. goto out;
  663. /* Get Remote DCB Config */
  664. ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
  665. I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
  666. &hw->remote_dcbx_config);
  667. /* Don't treat ENOENT as an error for Remote MIBs */
  668. if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  669. ret = 0;
  670. out:
  671. return ret;
  672. }
  673. /**
  674. * i40e_get_dcb_config
  675. * @hw: pointer to the hw struct
  676. *
  677. * Get DCB configuration from the Firmware
  678. **/
  679. int i40e_get_dcb_config(struct i40e_hw *hw)
  680. {
  681. struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg;
  682. struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg;
  683. int ret = 0;
  684. /* If Firmware version < v4.33 on X710/XL710, IEEE only */
  685. if (hw->mac.type == I40E_MAC_XL710 && i40e_is_fw_ver_lt(hw, 4, 33))
  686. return i40e_get_ieee_dcb_config(hw);
  687. /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */
  688. if (hw->mac.type == I40E_MAC_XL710 && i40e_is_fw_ver_eq(hw, 4, 33)) {
  689. ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg,
  690. sizeof(cee_v1_cfg), NULL);
  691. if (!ret) {
  692. /* CEE mode */
  693. hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
  694. hw->local_dcbx_config.tlv_status =
  695. le16_to_cpu(cee_v1_cfg.tlv_status);
  696. i40e_cee_to_dcb_v1_config(&cee_v1_cfg,
  697. &hw->local_dcbx_config);
  698. }
  699. } else {
  700. ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg,
  701. sizeof(cee_cfg), NULL);
  702. if (!ret) {
  703. /* CEE mode */
  704. hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;
  705. hw->local_dcbx_config.tlv_status =
  706. le32_to_cpu(cee_cfg.tlv_status);
  707. i40e_cee_to_dcb_config(&cee_cfg,
  708. &hw->local_dcbx_config);
  709. }
  710. }
  711. /* CEE mode not enabled try querying IEEE data */
  712. if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  713. return i40e_get_ieee_dcb_config(hw);
  714. if (ret)
  715. goto out;
  716. /* Get CEE DCB Desired Config */
  717. ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
  718. &hw->desired_dcbx_config);
  719. if (ret)
  720. goto out;
  721. /* Get Remote DCB Config */
  722. ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
  723. I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
  724. &hw->remote_dcbx_config);
  725. /* Don't treat ENOENT as an error for Remote MIBs */
  726. if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT)
  727. ret = 0;
  728. out:
  729. return ret;
  730. }
  731. /**
  732. * i40e_init_dcb
  733. * @hw: pointer to the hw struct
  734. * @enable_mib_change: enable mib change event
  735. *
  736. * Update DCB configuration from the Firmware
  737. **/
  738. int i40e_init_dcb(struct i40e_hw *hw, bool enable_mib_change)
  739. {
  740. struct i40e_lldp_variables lldp_cfg;
  741. u8 adminstatus = 0;
  742. int ret = 0;
  743. if (!hw->func_caps.dcb)
  744. return -EOPNOTSUPP;
  745. /* Read LLDP NVM area */
  746. if (test_bit(I40E_HW_CAP_FW_LLDP_PERSISTENT, hw->caps)) {
  747. u8 offset = 0;
  748. if (hw->mac.type == I40E_MAC_XL710)
  749. offset = I40E_LLDP_CURRENT_STATUS_XL710_OFFSET;
  750. else if (hw->mac.type == I40E_MAC_X722)
  751. offset = I40E_LLDP_CURRENT_STATUS_X722_OFFSET;
  752. else
  753. return -EOPNOTSUPP;
  754. ret = i40e_read_nvm_module_data(hw,
  755. I40E_SR_EMP_SR_SETTINGS_PTR,
  756. offset,
  757. I40E_LLDP_CURRENT_STATUS_OFFSET,
  758. I40E_LLDP_CURRENT_STATUS_SIZE,
  759. &lldp_cfg.adminstatus);
  760. } else {
  761. ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
  762. }
  763. if (ret)
  764. return -EBUSY;
  765. /* Get the LLDP AdminStatus for the current port */
  766. adminstatus = lldp_cfg.adminstatus >> (hw->port * 4);
  767. adminstatus &= 0xF;
  768. /* LLDP agent disabled */
  769. if (!adminstatus) {
  770. hw->dcbx_status = I40E_DCBX_STATUS_DISABLED;
  771. return -EBUSY;
  772. }
  773. /* Get DCBX status */
  774. ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
  775. if (ret)
  776. return ret;
  777. /* Check the DCBX Status */
  778. if (hw->dcbx_status == I40E_DCBX_STATUS_DONE ||
  779. hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) {
  780. /* Get current DCBX configuration */
  781. ret = i40e_get_dcb_config(hw);
  782. if (ret)
  783. return ret;
  784. } else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
  785. return -EBUSY;
  786. }
  787. /* Configure the LLDP MIB change event */
  788. if (enable_mib_change)
  789. ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
  790. return ret;
  791. }
  792. /**
  793. * i40e_get_fw_lldp_status
  794. * @hw: pointer to the hw struct
  795. * @lldp_status: pointer to the status enum
  796. *
  797. * Get status of FW Link Layer Discovery Protocol (LLDP) Agent.
  798. * Status of agent is reported via @lldp_status parameter.
  799. **/
  800. int
  801. i40e_get_fw_lldp_status(struct i40e_hw *hw,
  802. enum i40e_get_fw_lldp_status_resp *lldp_status)
  803. {
  804. struct i40e_virt_mem mem;
  805. u8 *lldpmib;
  806. int ret;
  807. if (!lldp_status)
  808. return -EINVAL;
  809. /* Allocate buffer for the LLDPDU */
  810. ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
  811. if (ret)
  812. return ret;
  813. lldpmib = (u8 *)mem.va;
  814. ret = i40e_aq_get_lldp_mib(hw, 0, 0, (void *)lldpmib,
  815. I40E_LLDPDU_SIZE, NULL, NULL, NULL);
  816. if (!ret) {
  817. *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
  818. } else if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) {
  819. /* MIB is not available yet but the agent is running */
  820. *lldp_status = I40E_GET_FW_LLDP_STATUS_ENABLED;
  821. ret = 0;
  822. } else if (hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
  823. *lldp_status = I40E_GET_FW_LLDP_STATUS_DISABLED;
  824. ret = 0;
  825. }
  826. i40e_free_virt_mem(hw, &mem);
  827. return ret;
  828. }
  829. /**
  830. * i40e_add_ieee_ets_tlv - Prepare ETS TLV in IEEE format
  831. * @tlv: Fill the ETS config data in IEEE format
  832. * @dcbcfg: Local store which holds the DCB Config
  833. *
  834. * Prepare IEEE 802.1Qaz ETS CFG TLV
  835. **/
  836. static void i40e_add_ieee_ets_tlv(struct i40e_lldp_org_tlv *tlv,
  837. struct i40e_dcbx_config *dcbcfg)
  838. {
  839. u8 priority0, priority1, maxtcwilling = 0;
  840. struct i40e_dcb_ets_config *etscfg;
  841. u16 offset = 0, typelength, i;
  842. u8 *buf = tlv->tlvinfo;
  843. u32 ouisubtype;
  844. typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
  845. I40E_IEEE_ETS_TLV_LENGTH);
  846. tlv->typelength = htons(typelength);
  847. ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
  848. I40E_IEEE_SUBTYPE_ETS_CFG);
  849. tlv->ouisubtype = htonl(ouisubtype);
  850. /* First Octet post subtype
  851. * --------------------------
  852. * |will-|CBS | Re- | Max |
  853. * |ing | |served| TCs |
  854. * --------------------------
  855. * |1bit | 1bit|3 bits|3bits|
  856. */
  857. etscfg = &dcbcfg->etscfg;
  858. if (etscfg->willing)
  859. maxtcwilling = BIT(I40E_IEEE_ETS_WILLING_SHIFT);
  860. maxtcwilling |= etscfg->maxtcs & I40E_IEEE_ETS_MAXTC_MASK;
  861. buf[offset] = maxtcwilling;
  862. /* Move offset to Priority Assignment Table */
  863. offset++;
  864. /* Priority Assignment Table (4 octets)
  865. * Octets:| 1 | 2 | 3 | 4 |
  866. * -----------------------------------------
  867. * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  868. * -----------------------------------------
  869. * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
  870. * -----------------------------------------
  871. */
  872. for (i = 0; i < 4; i++) {
  873. priority0 = etscfg->prioritytable[i * 2] & 0xF;
  874. priority1 = etscfg->prioritytable[i * 2 + 1] & 0xF;
  875. buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
  876. priority1;
  877. offset++;
  878. }
  879. /* TC Bandwidth Table (8 octets)
  880. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  881. * ---------------------------------
  882. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  883. * ---------------------------------
  884. */
  885. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  886. buf[offset++] = etscfg->tcbwtable[i];
  887. /* TSA Assignment Table (8 octets)
  888. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  889. * ---------------------------------
  890. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  891. * ---------------------------------
  892. */
  893. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  894. buf[offset++] = etscfg->tsatable[i];
  895. }
  896. /**
  897. * i40e_add_ieee_etsrec_tlv - Prepare ETS Recommended TLV in IEEE format
  898. * @tlv: Fill ETS Recommended TLV in IEEE format
  899. * @dcbcfg: Local store which holds the DCB Config
  900. *
  901. * Prepare IEEE 802.1Qaz ETS REC TLV
  902. **/
  903. static void i40e_add_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
  904. struct i40e_dcbx_config *dcbcfg)
  905. {
  906. struct i40e_dcb_ets_config *etsrec;
  907. u16 offset = 0, typelength, i;
  908. u8 priority0, priority1;
  909. u8 *buf = tlv->tlvinfo;
  910. u32 ouisubtype;
  911. typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
  912. I40E_IEEE_ETS_TLV_LENGTH);
  913. tlv->typelength = htons(typelength);
  914. ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
  915. I40E_IEEE_SUBTYPE_ETS_REC);
  916. tlv->ouisubtype = htonl(ouisubtype);
  917. etsrec = &dcbcfg->etsrec;
  918. /* First Octet is reserved */
  919. /* Move offset to Priority Assignment Table */
  920. offset++;
  921. /* Priority Assignment Table (4 octets)
  922. * Octets:| 1 | 2 | 3 | 4 |
  923. * -----------------------------------------
  924. * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
  925. * -----------------------------------------
  926. * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
  927. * -----------------------------------------
  928. */
  929. for (i = 0; i < 4; i++) {
  930. priority0 = etsrec->prioritytable[i * 2] & 0xF;
  931. priority1 = etsrec->prioritytable[i * 2 + 1] & 0xF;
  932. buf[offset] = (priority0 << I40E_IEEE_ETS_PRIO_1_SHIFT) |
  933. priority1;
  934. offset++;
  935. }
  936. /* TC Bandwidth Table (8 octets)
  937. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  938. * ---------------------------------
  939. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  940. * ---------------------------------
  941. */
  942. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  943. buf[offset++] = etsrec->tcbwtable[i];
  944. /* TSA Assignment Table (8 octets)
  945. * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
  946. * ---------------------------------
  947. * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
  948. * ---------------------------------
  949. */
  950. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
  951. buf[offset++] = etsrec->tsatable[i];
  952. }
  953. /**
  954. * i40e_add_ieee_pfc_tlv - Prepare PFC TLV in IEEE format
  955. * @tlv: Fill PFC TLV in IEEE format
  956. * @dcbcfg: Local store to get PFC CFG data
  957. *
  958. * Prepare IEEE 802.1Qaz PFC CFG TLV
  959. **/
  960. static void i40e_add_ieee_pfc_tlv(struct i40e_lldp_org_tlv *tlv,
  961. struct i40e_dcbx_config *dcbcfg)
  962. {
  963. u8 *buf = tlv->tlvinfo;
  964. u32 ouisubtype;
  965. u16 typelength;
  966. typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
  967. I40E_IEEE_PFC_TLV_LENGTH);
  968. tlv->typelength = htons(typelength);
  969. ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
  970. I40E_IEEE_SUBTYPE_PFC_CFG);
  971. tlv->ouisubtype = htonl(ouisubtype);
  972. /* ----------------------------------------
  973. * |will-|MBC | Re- | PFC | PFC Enable |
  974. * |ing | |served| cap | |
  975. * -----------------------------------------
  976. * |1bit | 1bit|2 bits|4bits| 1 octet |
  977. */
  978. if (dcbcfg->pfc.willing)
  979. buf[0] = BIT(I40E_IEEE_PFC_WILLING_SHIFT);
  980. if (dcbcfg->pfc.mbc)
  981. buf[0] |= BIT(I40E_IEEE_PFC_MBC_SHIFT);
  982. buf[0] |= dcbcfg->pfc.pfccap & 0xF;
  983. buf[1] = dcbcfg->pfc.pfcenable;
  984. }
  985. /**
  986. * i40e_add_ieee_app_pri_tlv - Prepare APP TLV in IEEE format
  987. * @tlv: Fill APP TLV in IEEE format
  988. * @dcbcfg: Local store to get APP CFG data
  989. *
  990. * Prepare IEEE 802.1Qaz APP CFG TLV
  991. **/
  992. static void i40e_add_ieee_app_pri_tlv(struct i40e_lldp_org_tlv *tlv,
  993. struct i40e_dcbx_config *dcbcfg)
  994. {
  995. u16 typelength, length, offset = 0;
  996. u8 priority, selector, i = 0;
  997. u8 *buf = tlv->tlvinfo;
  998. u32 ouisubtype;
  999. /* No APP TLVs then just return */
  1000. if (dcbcfg->numapps == 0)
  1001. return;
  1002. ouisubtype = (u32)((I40E_IEEE_8021QAZ_OUI << I40E_LLDP_TLV_OUI_SHIFT) |
  1003. I40E_IEEE_SUBTYPE_APP_PRI);
  1004. tlv->ouisubtype = htonl(ouisubtype);
  1005. /* Move offset to App Priority Table */
  1006. offset++;
  1007. /* Application Priority Table (3 octets)
  1008. * Octets:| 1 | 2 | 3 |
  1009. * -----------------------------------------
  1010. * |Priority|Rsrvd| Sel | Protocol ID |
  1011. * -----------------------------------------
  1012. * Bits:|23 21|20 19|18 16|15 0|
  1013. * -----------------------------------------
  1014. */
  1015. while (i < dcbcfg->numapps) {
  1016. priority = dcbcfg->app[i].priority & 0x7;
  1017. selector = dcbcfg->app[i].selector & 0x7;
  1018. buf[offset] = (priority << I40E_IEEE_APP_PRIO_SHIFT) | selector;
  1019. buf[offset + 1] = (dcbcfg->app[i].protocolid >> 0x8) & 0xFF;
  1020. buf[offset + 2] = dcbcfg->app[i].protocolid & 0xFF;
  1021. /* Move to next app */
  1022. offset += 3;
  1023. i++;
  1024. if (i >= I40E_DCBX_MAX_APPS)
  1025. break;
  1026. }
  1027. /* length includes size of ouisubtype + 1 reserved + 3*numapps */
  1028. length = sizeof(tlv->ouisubtype) + 1 + (i * 3);
  1029. typelength = (u16)((I40E_TLV_TYPE_ORG << I40E_LLDP_TLV_TYPE_SHIFT) |
  1030. (length & 0x1FF));
  1031. tlv->typelength = htons(typelength);
  1032. }
  1033. /**
  1034. * i40e_add_dcb_tlv - Add all IEEE TLVs
  1035. * @tlv: pointer to org tlv
  1036. * @dcbcfg: pointer to modified dcbx config structure *
  1037. * @tlvid: tlv id to be added
  1038. * add tlv information
  1039. **/
  1040. static void i40e_add_dcb_tlv(struct i40e_lldp_org_tlv *tlv,
  1041. struct i40e_dcbx_config *dcbcfg,
  1042. u16 tlvid)
  1043. {
  1044. switch (tlvid) {
  1045. case I40E_IEEE_TLV_ID_ETS_CFG:
  1046. i40e_add_ieee_ets_tlv(tlv, dcbcfg);
  1047. break;
  1048. case I40E_IEEE_TLV_ID_ETS_REC:
  1049. i40e_add_ieee_etsrec_tlv(tlv, dcbcfg);
  1050. break;
  1051. case I40E_IEEE_TLV_ID_PFC_CFG:
  1052. i40e_add_ieee_pfc_tlv(tlv, dcbcfg);
  1053. break;
  1054. case I40E_IEEE_TLV_ID_APP_PRI:
  1055. i40e_add_ieee_app_pri_tlv(tlv, dcbcfg);
  1056. break;
  1057. default:
  1058. break;
  1059. }
  1060. }
  1061. /**
  1062. * i40e_set_dcb_config - Set the local LLDP MIB to FW
  1063. * @hw: pointer to the hw struct
  1064. *
  1065. * Set DCB configuration to the Firmware
  1066. **/
  1067. int i40e_set_dcb_config(struct i40e_hw *hw)
  1068. {
  1069. struct i40e_dcbx_config *dcbcfg;
  1070. struct i40e_virt_mem mem;
  1071. u8 mib_type, *lldpmib;
  1072. u16 miblen;
  1073. int ret;
  1074. /* update the hw local config */
  1075. dcbcfg = &hw->local_dcbx_config;
  1076. /* Allocate the LLDPDU */
  1077. ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
  1078. if (ret)
  1079. return ret;
  1080. mib_type = SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB;
  1081. if (dcbcfg->app_mode == I40E_DCBX_APPS_NON_WILLING) {
  1082. mib_type |= SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS <<
  1083. SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT;
  1084. }
  1085. lldpmib = (u8 *)mem.va;
  1086. i40e_dcb_config_to_lldp(lldpmib, &miblen, dcbcfg);
  1087. ret = i40e_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, miblen, NULL);
  1088. i40e_free_virt_mem(hw, &mem);
  1089. return ret;
  1090. }
  1091. /**
  1092. * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
  1093. * @lldpmib: pointer to mib to be output
  1094. * @miblen: pointer to u16 for length of lldpmib
  1095. * @dcbcfg: store for LLDPDU data
  1096. *
  1097. * send DCB configuration to FW
  1098. **/
  1099. int i40e_dcb_config_to_lldp(u8 *lldpmib, u16 *miblen,
  1100. struct i40e_dcbx_config *dcbcfg)
  1101. {
  1102. u16 length, offset = 0, tlvid, typelength;
  1103. struct i40e_lldp_org_tlv *tlv;
  1104. tlv = (struct i40e_lldp_org_tlv *)lldpmib;
  1105. tlvid = I40E_TLV_ID_START;
  1106. do {
  1107. i40e_add_dcb_tlv(tlv, dcbcfg, tlvid++);
  1108. typelength = ntohs(tlv->typelength);
  1109. length = FIELD_GET(I40E_LLDP_TLV_LEN_MASK, typelength);
  1110. if (length)
  1111. offset += length + I40E_IEEE_TLV_HEADER_LENGTH;
  1112. /* END TLV or beyond LLDPDU size */
  1113. if (tlvid >= I40E_TLV_ID_END_OF_LLDPPDU ||
  1114. offset >= I40E_LLDPDU_SIZE)
  1115. break;
  1116. /* Move to next TLV */
  1117. if (length)
  1118. tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
  1119. sizeof(tlv->typelength) + length);
  1120. } while (tlvid < I40E_TLV_ID_END_OF_LLDPPDU);
  1121. *miblen = offset;
  1122. return 0;
  1123. }
  1124. /**
  1125. * i40e_dcb_hw_rx_fifo_config
  1126. * @hw: pointer to the hw struct
  1127. * @ets_mode: Strict Priority or Round Robin mode
  1128. * @non_ets_mode: Strict Priority or Round Robin
  1129. * @max_exponent: Exponent to calculate max refill credits
  1130. * @lltc_map: Low latency TC bitmap
  1131. *
  1132. * Configure HW Rx FIFO as part of DCB configuration.
  1133. **/
  1134. void i40e_dcb_hw_rx_fifo_config(struct i40e_hw *hw,
  1135. enum i40e_dcb_arbiter_mode ets_mode,
  1136. enum i40e_dcb_arbiter_mode non_ets_mode,
  1137. u32 max_exponent,
  1138. u8 lltc_map)
  1139. {
  1140. u32 reg = rd32(hw, I40E_PRTDCB_RETSC);
  1141. reg &= ~I40E_PRTDCB_RETSC_ETS_MODE_MASK;
  1142. reg |= FIELD_PREP(I40E_PRTDCB_RETSC_ETS_MODE_MASK, ets_mode);
  1143. reg &= ~I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK;
  1144. reg |= FIELD_PREP(I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK, non_ets_mode);
  1145. reg &= ~I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK;
  1146. reg |= FIELD_PREP(I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK, max_exponent);
  1147. reg &= ~I40E_PRTDCB_RETSC_LLTC_MASK;
  1148. reg |= FIELD_PREP(I40E_PRTDCB_RETSC_LLTC_MASK, lltc_map);
  1149. wr32(hw, I40E_PRTDCB_RETSC, reg);
  1150. }
  1151. /**
  1152. * i40e_dcb_hw_rx_cmd_monitor_config
  1153. * @hw: pointer to the hw struct
  1154. * @num_tc: Total number of traffic class
  1155. * @num_ports: Total number of ports on device
  1156. *
  1157. * Configure HW Rx command monitor as part of DCB configuration.
  1158. **/
  1159. void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
  1160. u8 num_tc, u8 num_ports)
  1161. {
  1162. u32 threshold;
  1163. u32 fifo_size;
  1164. u32 reg;
  1165. /* Set the threshold and fifo_size based on number of ports */
  1166. switch (num_ports) {
  1167. case 1:
  1168. threshold = I40E_DCB_1_PORT_THRESHOLD;
  1169. fifo_size = I40E_DCB_1_PORT_FIFO_SIZE;
  1170. break;
  1171. case 2:
  1172. if (num_tc > 4) {
  1173. threshold = I40E_DCB_2_PORT_THRESHOLD_HIGH_NUM_TC;
  1174. fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_HIGH_NUM_TC;
  1175. } else {
  1176. threshold = I40E_DCB_2_PORT_THRESHOLD_LOW_NUM_TC;
  1177. fifo_size = I40E_DCB_2_PORT_FIFO_SIZE_LOW_NUM_TC;
  1178. }
  1179. break;
  1180. case 4:
  1181. if (num_tc > 4) {
  1182. threshold = I40E_DCB_4_PORT_THRESHOLD_HIGH_NUM_TC;
  1183. fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_HIGH_NUM_TC;
  1184. } else {
  1185. threshold = I40E_DCB_4_PORT_THRESHOLD_LOW_NUM_TC;
  1186. fifo_size = I40E_DCB_4_PORT_FIFO_SIZE_LOW_NUM_TC;
  1187. }
  1188. break;
  1189. default:
  1190. i40e_debug(hw, I40E_DEBUG_DCB, "Invalid num_ports %u.\n",
  1191. (u32)num_ports);
  1192. return;
  1193. }
  1194. /* The hardware manual describes setting up of I40E_PRT_SWR_PM_THR
  1195. * based on the number of ports and traffic classes for a given port as
  1196. * part of DCB configuration.
  1197. */
  1198. reg = rd32(hw, I40E_PRT_SWR_PM_THR);
  1199. reg &= ~I40E_PRT_SWR_PM_THR_THRESHOLD_MASK;
  1200. reg |= FIELD_PREP(I40E_PRT_SWR_PM_THR_THRESHOLD_MASK, threshold);
  1201. wr32(hw, I40E_PRT_SWR_PM_THR, reg);
  1202. reg = rd32(hw, I40E_PRTDCB_RPPMC);
  1203. reg &= ~I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK;
  1204. reg |= FIELD_PREP(I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK, fifo_size);
  1205. wr32(hw, I40E_PRTDCB_RPPMC, reg);
  1206. }
  1207. /**
  1208. * i40e_dcb_hw_pfc_config
  1209. * @hw: pointer to the hw struct
  1210. * @pfc_en: Bitmap of PFC enabled priorities
  1211. * @prio_tc: priority to tc assignment indexed by priority
  1212. *
  1213. * Configure HW Priority Flow Controller as part of DCB configuration.
  1214. **/
  1215. void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
  1216. u8 pfc_en, u8 *prio_tc)
  1217. {
  1218. u16 refresh_time = (u16)I40E_DEFAULT_PAUSE_TIME / 2;
  1219. u32 link_speed = hw->phy.link_info.link_speed;
  1220. u8 first_pfc_prio = 0;
  1221. u8 num_pfc_tc = 0;
  1222. u8 tc2pfc = 0;
  1223. u32 reg;
  1224. u8 i;
  1225. /* Get Number of PFC TCs and TC2PFC map */
  1226. for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
  1227. if (pfc_en & BIT(i)) {
  1228. if (!first_pfc_prio)
  1229. first_pfc_prio = i;
  1230. /* Set bit for the PFC TC */
  1231. tc2pfc |= BIT(prio_tc[i]);
  1232. num_pfc_tc++;
  1233. }
  1234. }
  1235. switch (link_speed) {
  1236. case I40E_LINK_SPEED_10GB:
  1237. reg = rd32(hw, I40E_PRTDCB_MFLCN);
  1238. reg |= BIT(I40E_PRTDCB_MFLCN_DPF_SHIFT) &
  1239. I40E_PRTDCB_MFLCN_DPF_MASK;
  1240. reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK;
  1241. reg &= ~I40E_PRTDCB_MFLCN_RPFCE_MASK;
  1242. if (pfc_en) {
  1243. reg |= FIELD_PREP(I40E_PRTDCB_MFLCN_RPFCM_MASK, 1);
  1244. reg |= FIELD_PREP(I40E_PRTDCB_MFLCN_RPFCE_MASK,
  1245. pfc_en);
  1246. }
  1247. wr32(hw, I40E_PRTDCB_MFLCN, reg);
  1248. reg = rd32(hw, I40E_PRTDCB_FCCFG);
  1249. reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
  1250. if (pfc_en)
  1251. reg |= FIELD_PREP(I40E_PRTDCB_FCCFG_TFCE_MASK,
  1252. I40E_DCB_PFC_ENABLED);
  1253. wr32(hw, I40E_PRTDCB_FCCFG, reg);
  1254. /* FCTTV and FCRTV to be set by default */
  1255. break;
  1256. case I40E_LINK_SPEED_40GB:
  1257. reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
  1258. reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
  1259. wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, reg);
  1260. reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
  1261. reg &= ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_MASK;
  1262. reg |= BIT(I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_SHIFT) &
  1263. I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_MASK;
  1264. wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, reg);
  1265. reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
  1266. reg &= ~I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK;
  1267. reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_MASK,
  1268. pfc_en);
  1269. wr32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, reg);
  1270. reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
  1271. reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK;
  1272. reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_MASK,
  1273. pfc_en);
  1274. wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, reg);
  1275. for (i = 0; i < I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX; i++) {
  1276. reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i));
  1277. reg &= ~I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK;
  1278. if (pfc_en) {
  1279. reg |= FIELD_PREP(I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK,
  1280. refresh_time);
  1281. }
  1282. wr32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(i), reg);
  1283. }
  1284. /* PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA default value is 0xFFFF
  1285. * for all user priorities
  1286. */
  1287. break;
  1288. }
  1289. reg = rd32(hw, I40E_PRTDCB_TC2PFC);
  1290. reg &= ~I40E_PRTDCB_TC2PFC_TC2PFC_MASK;
  1291. reg |= FIELD_PREP(I40E_PRTDCB_TC2PFC_TC2PFC_MASK, tc2pfc);
  1292. wr32(hw, I40E_PRTDCB_TC2PFC, reg);
  1293. reg = rd32(hw, I40E_PRTDCB_RUP);
  1294. reg &= ~I40E_PRTDCB_RUP_NOVLANUP_MASK;
  1295. reg |= FIELD_PREP(I40E_PRTDCB_RUP_NOVLANUP_MASK, first_pfc_prio);
  1296. wr32(hw, I40E_PRTDCB_RUP, reg);
  1297. reg = rd32(hw, I40E_PRTDCB_TDPMC);
  1298. reg &= ~I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
  1299. if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
  1300. reg |= BIT(I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) &
  1301. I40E_PRTDCB_TDPMC_TCPM_MODE_MASK;
  1302. }
  1303. wr32(hw, I40E_PRTDCB_TDPMC, reg);
  1304. reg = rd32(hw, I40E_PRTDCB_TCPMC);
  1305. reg &= ~I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
  1306. if (num_pfc_tc > I40E_DCB_PFC_FORCED_NUM_TC) {
  1307. reg |= BIT(I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) &
  1308. I40E_PRTDCB_TCPMC_TCPM_MODE_MASK;
  1309. }
  1310. wr32(hw, I40E_PRTDCB_TCPMC, reg);
  1311. }
  1312. /**
  1313. * i40e_dcb_hw_set_num_tc
  1314. * @hw: pointer to the hw struct
  1315. * @num_tc: number of traffic classes
  1316. *
  1317. * Configure number of traffic classes in HW
  1318. **/
  1319. void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
  1320. {
  1321. u32 reg = rd32(hw, I40E_PRTDCB_GENC);
  1322. reg &= ~I40E_PRTDCB_GENC_NUMTC_MASK;
  1323. reg |= FIELD_PREP(I40E_PRTDCB_GENC_NUMTC_MASK, num_tc);
  1324. wr32(hw, I40E_PRTDCB_GENC, reg);
  1325. }
  1326. /**
  1327. * i40e_dcb_hw_get_num_tc
  1328. * @hw: pointer to the hw struct
  1329. *
  1330. * Returns number of traffic classes configured in HW
  1331. **/
  1332. u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
  1333. {
  1334. u32 reg = rd32(hw, I40E_PRTDCB_GENC);
  1335. return FIELD_GET(I40E_PRTDCB_GENC_NUMTC_MASK, reg);
  1336. }
  1337. /**
  1338. * i40e_dcb_hw_rx_ets_bw_config
  1339. * @hw: pointer to the hw struct
  1340. * @bw_share: Bandwidth share indexed per traffic class
  1341. * @mode: Strict Priority or Round Robin mode between UP sharing same
  1342. * traffic class
  1343. * @prio_type: TC is ETS enabled or strict priority
  1344. *
  1345. * Configure HW Rx ETS bandwidth as part of DCB configuration.
  1346. **/
  1347. void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
  1348. u8 *mode, u8 *prio_type)
  1349. {
  1350. u32 reg;
  1351. u8 i;
  1352. for (i = 0; i <= I40E_PRTDCB_RETSTCC_MAX_INDEX; i++) {
  1353. reg = rd32(hw, I40E_PRTDCB_RETSTCC(i));
  1354. reg &= ~(I40E_PRTDCB_RETSTCC_BWSHARE_MASK |
  1355. I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK |
  1356. I40E_PRTDCB_RETSTCC_ETSTC_MASK);
  1357. reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_BWSHARE_MASK,
  1358. bw_share[i]);
  1359. reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK,
  1360. mode[i]);
  1361. reg |= FIELD_PREP(I40E_PRTDCB_RETSTCC_ETSTC_MASK,
  1362. prio_type[i]);
  1363. wr32(hw, I40E_PRTDCB_RETSTCC(i), reg);
  1364. }
  1365. }
  1366. /**
  1367. * i40e_dcb_hw_rx_up2tc_config
  1368. * @hw: pointer to the hw struct
  1369. * @prio_tc: priority to tc assignment indexed by priority
  1370. *
  1371. * Configure HW Rx UP2TC map as part of DCB configuration.
  1372. **/
  1373. void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc)
  1374. {
  1375. u32 reg = rd32(hw, I40E_PRTDCB_RUP2TC);
  1376. #define I40E_UP2TC_REG(val, i) \
  1377. (((val) << I40E_PRTDCB_RUP2TC_UP##i##TC_SHIFT) & \
  1378. I40E_PRTDCB_RUP2TC_UP##i##TC_MASK)
  1379. reg |= I40E_UP2TC_REG(prio_tc[0], 0);
  1380. reg |= I40E_UP2TC_REG(prio_tc[1], 1);
  1381. reg |= I40E_UP2TC_REG(prio_tc[2], 2);
  1382. reg |= I40E_UP2TC_REG(prio_tc[3], 3);
  1383. reg |= I40E_UP2TC_REG(prio_tc[4], 4);
  1384. reg |= I40E_UP2TC_REG(prio_tc[5], 5);
  1385. reg |= I40E_UP2TC_REG(prio_tc[6], 6);
  1386. reg |= I40E_UP2TC_REG(prio_tc[7], 7);
  1387. wr32(hw, I40E_PRTDCB_RUP2TC, reg);
  1388. }
  1389. /**
  1390. * i40e_dcb_hw_calculate_pool_sizes - configure dcb pool sizes
  1391. * @hw: pointer to the hw struct
  1392. * @num_ports: Number of available ports on the device
  1393. * @eee_enabled: EEE enabled for the given port
  1394. * @pfc_en: Bit map of PFC enabled traffic classes
  1395. * @mfs_tc: Array of max frame size for each traffic class
  1396. * @pb_cfg: pointer to packet buffer configuration
  1397. *
  1398. * Calculate the shared and dedicated per TC pool sizes,
  1399. * watermarks and threshold values.
  1400. **/
  1401. void i40e_dcb_hw_calculate_pool_sizes(struct i40e_hw *hw,
  1402. u8 num_ports, bool eee_enabled,
  1403. u8 pfc_en, u32 *mfs_tc,
  1404. struct i40e_rx_pb_config *pb_cfg)
  1405. {
  1406. u32 pool_size[I40E_MAX_TRAFFIC_CLASS];
  1407. u32 high_wm[I40E_MAX_TRAFFIC_CLASS];
  1408. u32 low_wm[I40E_MAX_TRAFFIC_CLASS];
  1409. u32 total_pool_size = 0;
  1410. int shared_pool_size; /* Need signed variable */
  1411. u32 port_pb_size;
  1412. u32 mfs_max = 0;
  1413. u32 pcirtt;
  1414. u8 i;
  1415. /* Get the MFS(max) for the port */
  1416. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1417. if (mfs_tc[i] > mfs_max)
  1418. mfs_max = mfs_tc[i];
  1419. }
  1420. pcirtt = I40E_BT2B(I40E_PCIRTT_LINK_SPEED_10G);
  1421. /* Calculate effective Rx PB size per port */
  1422. port_pb_size = I40E_DEVICE_RPB_SIZE / num_ports;
  1423. if (eee_enabled)
  1424. port_pb_size -= I40E_BT2B(I40E_EEE_TX_LPI_EXIT_TIME);
  1425. port_pb_size -= mfs_max;
  1426. /* Step 1 Calculating tc pool/shared pool sizes and watermarks */
  1427. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1428. if (pfc_en & BIT(i)) {
  1429. low_wm[i] = (I40E_DCB_WATERMARK_START_FACTOR *
  1430. mfs_tc[i]) + pcirtt;
  1431. high_wm[i] = low_wm[i];
  1432. high_wm[i] += ((mfs_max > I40E_MAX_FRAME_SIZE)
  1433. ? mfs_max : I40E_MAX_FRAME_SIZE);
  1434. pool_size[i] = high_wm[i];
  1435. pool_size[i] += I40E_BT2B(I40E_STD_DV_TC(mfs_max,
  1436. mfs_tc[i]));
  1437. } else {
  1438. low_wm[i] = 0;
  1439. pool_size[i] = (I40E_DCB_WATERMARK_START_FACTOR *
  1440. mfs_tc[i]) + pcirtt;
  1441. high_wm[i] = pool_size[i];
  1442. }
  1443. total_pool_size += pool_size[i];
  1444. }
  1445. shared_pool_size = port_pb_size - total_pool_size;
  1446. if (shared_pool_size > 0) {
  1447. pb_cfg->shared_pool_size = shared_pool_size;
  1448. pb_cfg->shared_pool_high_wm = shared_pool_size;
  1449. pb_cfg->shared_pool_low_wm = 0;
  1450. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1451. pb_cfg->shared_pool_low_thresh[i] = 0;
  1452. pb_cfg->shared_pool_high_thresh[i] = shared_pool_size;
  1453. pb_cfg->tc_pool_size[i] = pool_size[i];
  1454. pb_cfg->tc_pool_high_wm[i] = high_wm[i];
  1455. pb_cfg->tc_pool_low_wm[i] = low_wm[i];
  1456. }
  1457. } else {
  1458. i40e_debug(hw, I40E_DEBUG_DCB,
  1459. "The shared pool size for the port is negative %d.\n",
  1460. shared_pool_size);
  1461. }
  1462. }
  1463. /**
  1464. * i40e_dcb_hw_rx_pb_config
  1465. * @hw: pointer to the hw struct
  1466. * @old_pb_cfg: Existing Rx Packet buffer configuration
  1467. * @new_pb_cfg: New Rx Packet buffer configuration
  1468. *
  1469. * Program the Rx Packet Buffer registers.
  1470. **/
  1471. void i40e_dcb_hw_rx_pb_config(struct i40e_hw *hw,
  1472. struct i40e_rx_pb_config *old_pb_cfg,
  1473. struct i40e_rx_pb_config *new_pb_cfg)
  1474. {
  1475. u32 old_val;
  1476. u32 new_val;
  1477. u32 reg;
  1478. u8 i;
  1479. /* The Rx Packet buffer register programming needs to be done in a
  1480. * certain order and the following code is based on that
  1481. * requirement.
  1482. */
  1483. /* Program the shared pool low water mark per port if decreasing */
  1484. old_val = old_pb_cfg->shared_pool_low_wm;
  1485. new_val = new_pb_cfg->shared_pool_low_wm;
  1486. if (new_val < old_val) {
  1487. reg = rd32(hw, I40E_PRTRPB_SLW);
  1488. reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
  1489. reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val);
  1490. wr32(hw, I40E_PRTRPB_SLW, reg);
  1491. }
  1492. /* Program the shared pool low threshold and tc pool
  1493. * low water mark per TC that are decreasing.
  1494. */
  1495. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1496. old_val = old_pb_cfg->shared_pool_low_thresh[i];
  1497. new_val = new_pb_cfg->shared_pool_low_thresh[i];
  1498. if (new_val < old_val) {
  1499. reg = rd32(hw, I40E_PRTRPB_SLT(i));
  1500. reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
  1501. reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK,
  1502. new_val);
  1503. wr32(hw, I40E_PRTRPB_SLT(i), reg);
  1504. }
  1505. old_val = old_pb_cfg->tc_pool_low_wm[i];
  1506. new_val = new_pb_cfg->tc_pool_low_wm[i];
  1507. if (new_val < old_val) {
  1508. reg = rd32(hw, I40E_PRTRPB_DLW(i));
  1509. reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
  1510. reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK,
  1511. new_val);
  1512. wr32(hw, I40E_PRTRPB_DLW(i), reg);
  1513. }
  1514. }
  1515. /* Program the shared pool high water mark per port if decreasing */
  1516. old_val = old_pb_cfg->shared_pool_high_wm;
  1517. new_val = new_pb_cfg->shared_pool_high_wm;
  1518. if (new_val < old_val) {
  1519. reg = rd32(hw, I40E_PRTRPB_SHW);
  1520. reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
  1521. reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val);
  1522. wr32(hw, I40E_PRTRPB_SHW, reg);
  1523. }
  1524. /* Program the shared pool high threshold and tc pool
  1525. * high water mark per TC that are decreasing.
  1526. */
  1527. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1528. old_val = old_pb_cfg->shared_pool_high_thresh[i];
  1529. new_val = new_pb_cfg->shared_pool_high_thresh[i];
  1530. if (new_val < old_val) {
  1531. reg = rd32(hw, I40E_PRTRPB_SHT(i));
  1532. reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
  1533. reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK,
  1534. new_val);
  1535. wr32(hw, I40E_PRTRPB_SHT(i), reg);
  1536. }
  1537. old_val = old_pb_cfg->tc_pool_high_wm[i];
  1538. new_val = new_pb_cfg->tc_pool_high_wm[i];
  1539. if (new_val < old_val) {
  1540. reg = rd32(hw, I40E_PRTRPB_DHW(i));
  1541. reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
  1542. reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK,
  1543. new_val);
  1544. wr32(hw, I40E_PRTRPB_DHW(i), reg);
  1545. }
  1546. }
  1547. /* Write Dedicated Pool Sizes per TC */
  1548. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1549. new_val = new_pb_cfg->tc_pool_size[i];
  1550. reg = rd32(hw, I40E_PRTRPB_DPS(i));
  1551. reg &= ~I40E_PRTRPB_DPS_DPS_TCN_MASK;
  1552. reg |= FIELD_PREP(I40E_PRTRPB_DPS_DPS_TCN_MASK, new_val);
  1553. wr32(hw, I40E_PRTRPB_DPS(i), reg);
  1554. }
  1555. /* Write Shared Pool Size per port */
  1556. new_val = new_pb_cfg->shared_pool_size;
  1557. reg = rd32(hw, I40E_PRTRPB_SPS);
  1558. reg &= ~I40E_PRTRPB_SPS_SPS_MASK;
  1559. reg |= FIELD_PREP(I40E_PRTRPB_SPS_SPS_MASK, new_val);
  1560. wr32(hw, I40E_PRTRPB_SPS, reg);
  1561. /* Program the shared pool low water mark per port if increasing */
  1562. old_val = old_pb_cfg->shared_pool_low_wm;
  1563. new_val = new_pb_cfg->shared_pool_low_wm;
  1564. if (new_val > old_val) {
  1565. reg = rd32(hw, I40E_PRTRPB_SLW);
  1566. reg &= ~I40E_PRTRPB_SLW_SLW_MASK;
  1567. reg |= FIELD_PREP(I40E_PRTRPB_SLW_SLW_MASK, new_val);
  1568. wr32(hw, I40E_PRTRPB_SLW, reg);
  1569. }
  1570. /* Program the shared pool low threshold and tc pool
  1571. * low water mark per TC that are increasing.
  1572. */
  1573. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1574. old_val = old_pb_cfg->shared_pool_low_thresh[i];
  1575. new_val = new_pb_cfg->shared_pool_low_thresh[i];
  1576. if (new_val > old_val) {
  1577. reg = rd32(hw, I40E_PRTRPB_SLT(i));
  1578. reg &= ~I40E_PRTRPB_SLT_SLT_TCN_MASK;
  1579. reg |= FIELD_PREP(I40E_PRTRPB_SLT_SLT_TCN_MASK,
  1580. new_val);
  1581. wr32(hw, I40E_PRTRPB_SLT(i), reg);
  1582. }
  1583. old_val = old_pb_cfg->tc_pool_low_wm[i];
  1584. new_val = new_pb_cfg->tc_pool_low_wm[i];
  1585. if (new_val > old_val) {
  1586. reg = rd32(hw, I40E_PRTRPB_DLW(i));
  1587. reg &= ~I40E_PRTRPB_DLW_DLW_TCN_MASK;
  1588. reg |= FIELD_PREP(I40E_PRTRPB_DLW_DLW_TCN_MASK,
  1589. new_val);
  1590. wr32(hw, I40E_PRTRPB_DLW(i), reg);
  1591. }
  1592. }
  1593. /* Program the shared pool high water mark per port if increasing */
  1594. old_val = old_pb_cfg->shared_pool_high_wm;
  1595. new_val = new_pb_cfg->shared_pool_high_wm;
  1596. if (new_val > old_val) {
  1597. reg = rd32(hw, I40E_PRTRPB_SHW);
  1598. reg &= ~I40E_PRTRPB_SHW_SHW_MASK;
  1599. reg |= FIELD_PREP(I40E_PRTRPB_SHW_SHW_MASK, new_val);
  1600. wr32(hw, I40E_PRTRPB_SHW, reg);
  1601. }
  1602. /* Program the shared pool high threshold and tc pool
  1603. * high water mark per TC that are increasing.
  1604. */
  1605. for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
  1606. old_val = old_pb_cfg->shared_pool_high_thresh[i];
  1607. new_val = new_pb_cfg->shared_pool_high_thresh[i];
  1608. if (new_val > old_val) {
  1609. reg = rd32(hw, I40E_PRTRPB_SHT(i));
  1610. reg &= ~I40E_PRTRPB_SHT_SHT_TCN_MASK;
  1611. reg |= FIELD_PREP(I40E_PRTRPB_SHT_SHT_TCN_MASK,
  1612. new_val);
  1613. wr32(hw, I40E_PRTRPB_SHT(i), reg);
  1614. }
  1615. old_val = old_pb_cfg->tc_pool_high_wm[i];
  1616. new_val = new_pb_cfg->tc_pool_high_wm[i];
  1617. if (new_val > old_val) {
  1618. reg = rd32(hw, I40E_PRTRPB_DHW(i));
  1619. reg &= ~I40E_PRTRPB_DHW_DHW_TCN_MASK;
  1620. reg |= FIELD_PREP(I40E_PRTRPB_DHW_DHW_TCN_MASK,
  1621. new_val);
  1622. wr32(hw, I40E_PRTRPB_DHW(i), reg);
  1623. }
  1624. }
  1625. }
  1626. /**
  1627. * _i40e_read_lldp_cfg - generic read of LLDP Configuration data from NVM
  1628. * @hw: pointer to the HW structure
  1629. * @lldp_cfg: pointer to hold lldp configuration variables
  1630. * @module: address of the module pointer
  1631. * @word_offset: offset of LLDP configuration
  1632. *
  1633. * Reads the LLDP configuration data from NVM using passed addresses
  1634. **/
  1635. static int _i40e_read_lldp_cfg(struct i40e_hw *hw,
  1636. struct i40e_lldp_variables *lldp_cfg,
  1637. u8 module, u32 word_offset)
  1638. {
  1639. u32 address, offset = (2 * word_offset);
  1640. __le16 raw_mem;
  1641. int ret;
  1642. u16 mem;
  1643. ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
  1644. if (ret)
  1645. return ret;
  1646. ret = i40e_aq_read_nvm(hw, 0x0, module * 2, sizeof(raw_mem), &raw_mem,
  1647. true, NULL);
  1648. i40e_release_nvm(hw);
  1649. if (ret)
  1650. return ret;
  1651. mem = le16_to_cpu(raw_mem);
  1652. /* Check if this pointer needs to be read in word size or 4K sector
  1653. * units.
  1654. */
  1655. if (mem & I40E_PTR_TYPE)
  1656. address = (0x7FFF & mem) * 4096;
  1657. else
  1658. address = (0x7FFF & mem) * 2;
  1659. ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
  1660. if (ret)
  1661. goto err_lldp_cfg;
  1662. ret = i40e_aq_read_nvm(hw, module, offset, sizeof(raw_mem), &raw_mem,
  1663. true, NULL);
  1664. i40e_release_nvm(hw);
  1665. if (ret)
  1666. return ret;
  1667. mem = le16_to_cpu(raw_mem);
  1668. offset = mem + word_offset;
  1669. offset *= 2;
  1670. ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
  1671. if (ret)
  1672. goto err_lldp_cfg;
  1673. ret = i40e_aq_read_nvm(hw, 0, address + offset,
  1674. sizeof(struct i40e_lldp_variables), lldp_cfg,
  1675. true, NULL);
  1676. i40e_release_nvm(hw);
  1677. err_lldp_cfg:
  1678. return ret;
  1679. }
  1680. /**
  1681. * i40e_read_lldp_cfg - read LLDP Configuration data from NVM
  1682. * @hw: pointer to the HW structure
  1683. * @lldp_cfg: pointer to hold lldp configuration variables
  1684. *
  1685. * Reads the LLDP configuration data from NVM
  1686. **/
  1687. int i40e_read_lldp_cfg(struct i40e_hw *hw,
  1688. struct i40e_lldp_variables *lldp_cfg)
  1689. {
  1690. int ret = 0;
  1691. u32 mem;
  1692. if (!lldp_cfg)
  1693. return -EINVAL;
  1694. ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
  1695. if (ret)
  1696. return ret;
  1697. ret = i40e_aq_read_nvm(hw, I40E_SR_NVM_CONTROL_WORD, 0, sizeof(mem),
  1698. &mem, true, NULL);
  1699. i40e_release_nvm(hw);
  1700. if (ret)
  1701. return ret;
  1702. /* Read a bit that holds information whether we are running flat or
  1703. * structured NVM image. Flat image has LLDP configuration in shadow
  1704. * ram, so there is a need to pass different addresses for both cases.
  1705. */
  1706. if (mem & I40E_SR_NVM_MAP_STRUCTURE_TYPE) {
  1707. /* Flat NVM case */
  1708. ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_SR_EMP_MODULE_PTR,
  1709. I40E_SR_LLDP_CFG_PTR);
  1710. } else {
  1711. /* Good old structured NVM image */
  1712. ret = _i40e_read_lldp_cfg(hw, lldp_cfg, I40E_EMP_MODULE_PTR,
  1713. I40E_NVM_LLDP_CFG_PTR);
  1714. }
  1715. return ret;
  1716. }