diff options
Diffstat (limited to 'drivers/net/cxgb4/t4_hw.c')
-rw-r--r-- | drivers/net/cxgb4/t4_hw.c | 117 |
1 files changed, 61 insertions, 56 deletions
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c index a814a3afe123..da272a98fdbc 100644 --- a/drivers/net/cxgb4/t4_hw.c +++ b/drivers/net/cxgb4/t4_hw.c | |||
@@ -53,8 +53,8 @@ | |||
53 | * at the time it indicated completion is stored there. Returns 0 if the | 53 | * at the time it indicated completion is stored there. Returns 0 if the |
54 | * operation completes and -EAGAIN otherwise. | 54 | * operation completes and -EAGAIN otherwise. |
55 | */ | 55 | */ |
56 | int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, | 56 | static int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, |
57 | int polarity, int attempts, int delay, u32 *valp) | 57 | int polarity, int attempts, int delay, u32 *valp) |
58 | { | 58 | { |
59 | while (1) { | 59 | while (1) { |
60 | u32 val = t4_read_reg(adapter, reg); | 60 | u32 val = t4_read_reg(adapter, reg); |
@@ -109,9 +109,9 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, | |||
109 | * Reads registers that are accessed indirectly through an address/data | 109 | * Reads registers that are accessed indirectly through an address/data |
110 | * register pair. | 110 | * register pair. |
111 | */ | 111 | */ |
112 | void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | 112 | static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, |
113 | unsigned int data_reg, u32 *vals, unsigned int nregs, | 113 | unsigned int data_reg, u32 *vals, |
114 | unsigned int start_idx) | 114 | unsigned int nregs, unsigned int start_idx) |
115 | { | 115 | { |
116 | while (nregs--) { | 116 | while (nregs--) { |
117 | t4_write_reg(adap, addr_reg, start_idx); | 117 | t4_write_reg(adap, addr_reg, start_idx); |
@@ -120,6 +120,7 @@ void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | |||
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | #if 0 | ||
123 | /** | 124 | /** |
124 | * t4_write_indirect - write indirectly addressed registers | 125 | * t4_write_indirect - write indirectly addressed registers |
125 | * @adap: the adapter | 126 | * @adap: the adapter |
@@ -132,15 +133,16 @@ void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | |||
132 | * Writes a sequential block of registers that are accessed indirectly | 133 | * Writes a sequential block of registers that are accessed indirectly |
133 | * through an address/data register pair. | 134 | * through an address/data register pair. |
134 | */ | 135 | */ |
135 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, | 136 | static void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, |
136 | unsigned int data_reg, const u32 *vals, | 137 | unsigned int data_reg, const u32 *vals, |
137 | unsigned int nregs, unsigned int start_idx) | 138 | unsigned int nregs, unsigned int start_idx) |
138 | { | 139 | { |
139 | while (nregs--) { | 140 | while (nregs--) { |
140 | t4_write_reg(adap, addr_reg, start_idx++); | 141 | t4_write_reg(adap, addr_reg, start_idx++); |
141 | t4_write_reg(adap, data_reg, *vals++); | 142 | t4_write_reg(adap, data_reg, *vals++); |
142 | } | 143 | } |
143 | } | 144 | } |
145 | #endif | ||
144 | 146 | ||
145 | /* | 147 | /* |
146 | * Get the reply to a mailbox command and store it in @rpl in big-endian order. | 148 | * Get the reply to a mailbox command and store it in @rpl in big-endian order. |
@@ -345,33 +347,21 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc) | |||
345 | return 0; | 347 | return 0; |
346 | } | 348 | } |
347 | 349 | ||
348 | #define VPD_ENTRY(name, len) \ | ||
349 | u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] | ||
350 | |||
351 | /* | 350 | /* |
352 | * Partial EEPROM Vital Product Data structure. Includes only the ID and | 351 | * Partial EEPROM Vital Product Data structure. Includes only the ID and |
353 | * VPD-R sections. | 352 | * VPD-R header. |
354 | */ | 353 | */ |
355 | struct t4_vpd { | 354 | struct t4_vpd_hdr { |
356 | u8 id_tag; | 355 | u8 id_tag; |
357 | u8 id_len[2]; | 356 | u8 id_len[2]; |
358 | u8 id_data[ID_LEN]; | 357 | u8 id_data[ID_LEN]; |
359 | u8 vpdr_tag; | 358 | u8 vpdr_tag; |
360 | u8 vpdr_len[2]; | 359 | u8 vpdr_len[2]; |
361 | VPD_ENTRY(pn, 16); /* part number */ | ||
362 | VPD_ENTRY(ec, EC_LEN); /* EC level */ | ||
363 | VPD_ENTRY(sn, SERNUM_LEN); /* serial number */ | ||
364 | VPD_ENTRY(na, 12); /* MAC address base */ | ||
365 | VPD_ENTRY(port_type, 8); /* port types */ | ||
366 | VPD_ENTRY(gpio, 14); /* GPIO usage */ | ||
367 | VPD_ENTRY(cclk, 6); /* core clock */ | ||
368 | VPD_ENTRY(port_addr, 8); /* port MDIO addresses */ | ||
369 | VPD_ENTRY(rv, 1); /* csum */ | ||
370 | u32 pad; /* for multiple-of-4 sizing and alignment */ | ||
371 | }; | 360 | }; |
372 | 361 | ||
373 | #define EEPROM_STAT_ADDR 0x7bfc | 362 | #define EEPROM_STAT_ADDR 0x7bfc |
374 | #define VPD_BASE 0 | 363 | #define VPD_BASE 0 |
364 | #define VPD_LEN 512 | ||
375 | 365 | ||
376 | /** | 366 | /** |
377 | * t4_seeprom_wp - enable/disable EEPROM write protection | 367 | * t4_seeprom_wp - enable/disable EEPROM write protection |
@@ -396,16 +386,36 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable) | |||
396 | */ | 386 | */ |
397 | static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | 387 | static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) |
398 | { | 388 | { |
399 | int ret; | 389 | int i, ret; |
400 | struct t4_vpd vpd; | 390 | int ec, sn, v2; |
401 | u8 *q = (u8 *)&vpd, csum; | 391 | u8 vpd[VPD_LEN], csum; |
392 | unsigned int vpdr_len; | ||
393 | const struct t4_vpd_hdr *v; | ||
402 | 394 | ||
403 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), &vpd); | 395 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd); |
404 | if (ret < 0) | 396 | if (ret < 0) |
405 | return ret; | 397 | return ret; |
406 | 398 | ||
407 | for (csum = 0; q <= vpd.rv_data; q++) | 399 | v = (const struct t4_vpd_hdr *)vpd; |
408 | csum += *q; | 400 | vpdr_len = pci_vpd_lrdt_size(&v->vpdr_tag); |
401 | if (vpdr_len + sizeof(struct t4_vpd_hdr) > VPD_LEN) { | ||
402 | dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len); | ||
403 | return -EINVAL; | ||
404 | } | ||
405 | |||
406 | #define FIND_VPD_KW(var, name) do { \ | ||
407 | var = pci_vpd_find_info_keyword(&v->id_tag, sizeof(struct t4_vpd_hdr), \ | ||
408 | vpdr_len, name); \ | ||
409 | if (var < 0) { \ | ||
410 | dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \ | ||
411 | return -EINVAL; \ | ||
412 | } \ | ||
413 | var += PCI_VPD_INFO_FLD_HDR_SIZE; \ | ||
414 | } while (0) | ||
415 | |||
416 | FIND_VPD_KW(i, "RV"); | ||
417 | for (csum = 0; i >= 0; i--) | ||
418 | csum += vpd[i]; | ||
409 | 419 | ||
410 | if (csum) { | 420 | if (csum) { |
411 | dev_err(adapter->pdev_dev, | 421 | dev_err(adapter->pdev_dev, |
@@ -413,12 +423,18 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
413 | return -EINVAL; | 423 | return -EINVAL; |
414 | } | 424 | } |
415 | 425 | ||
416 | p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10); | 426 | FIND_VPD_KW(ec, "EC"); |
417 | memcpy(p->id, vpd.id_data, sizeof(vpd.id_data)); | 427 | FIND_VPD_KW(sn, "SN"); |
428 | FIND_VPD_KW(v2, "V2"); | ||
429 | #undef FIND_VPD_KW | ||
430 | |||
431 | p->cclk = simple_strtoul(vpd + v2, NULL, 10); | ||
432 | memcpy(p->id, v->id_data, ID_LEN); | ||
418 | strim(p->id); | 433 | strim(p->id); |
419 | memcpy(p->ec, vpd.ec_data, sizeof(vpd.ec_data)); | 434 | memcpy(p->ec, vpd + ec, EC_LEN); |
420 | strim(p->ec); | 435 | strim(p->ec); |
421 | memcpy(p->sn, vpd.sn_data, sizeof(vpd.sn_data)); | 436 | i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); |
437 | memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); | ||
422 | strim(p->sn); | 438 | strim(p->sn); |
423 | return 0; | 439 | return 0; |
424 | } | 440 | } |
@@ -537,8 +553,8 @@ static int flash_wait_op(struct adapter *adapter, int attempts, int delay) | |||
537 | * (i.e., big-endian), otherwise as 32-bit words in the platform's | 553 | * (i.e., big-endian), otherwise as 32-bit words in the platform's |
538 | * natural endianess. | 554 | * natural endianess. |
539 | */ | 555 | */ |
540 | int t4_read_flash(struct adapter *adapter, unsigned int addr, | 556 | static int t4_read_flash(struct adapter *adapter, unsigned int addr, |
541 | unsigned int nwords, u32 *data, int byte_oriented) | 557 | unsigned int nwords, u32 *data, int byte_oriented) |
542 | { | 558 | { |
543 | int ret; | 559 | int ret; |
544 | 560 | ||
@@ -870,22 +886,6 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port) | |||
870 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); | 886 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); |
871 | } | 887 | } |
872 | 888 | ||
873 | /** | ||
874 | * t4_set_vlan_accel - configure HW VLAN extraction | ||
875 | * @adap: the adapter | ||
876 | * @ports: bitmap of adapter ports to operate on | ||
877 | * @on: enable (1) or disable (0) HW VLAN extraction | ||
878 | * | ||
879 | * Enables or disables HW extraction of VLAN tags for the ports specified | ||
880 | * by @ports. @ports is a bitmap with the ith bit designating the port | ||
881 | * associated with the ith adapter channel. | ||
882 | */ | ||
883 | void t4_set_vlan_accel(struct adapter *adap, unsigned int ports, int on) | ||
884 | { | ||
885 | ports <<= VLANEXTENABLE_SHIFT; | ||
886 | t4_set_reg_field(adap, TP_OUT_CONFIG, ports, on ? ports : 0); | ||
887 | } | ||
888 | |||
889 | struct intr_info { | 889 | struct intr_info { |
890 | unsigned int mask; /* bits to check in interrupt status */ | 890 | unsigned int mask; /* bits to check in interrupt status */ |
891 | const char *msg; /* message to print or NULL */ | 891 | const char *msg; /* message to print or NULL */ |
@@ -2608,12 +2608,14 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, | |||
2608 | * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change | 2608 | * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change |
2609 | * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change | 2609 | * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change |
2610 | * @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change | 2610 | * @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change |
2611 | * @vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change | ||
2611 | * @sleep_ok: if true we may sleep while awaiting command completion | 2612 | * @sleep_ok: if true we may sleep while awaiting command completion |
2612 | * | 2613 | * |
2613 | * Sets Rx properties of a virtual interface. | 2614 | * Sets Rx properties of a virtual interface. |
2614 | */ | 2615 | */ |
2615 | int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, | 2616 | int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, |
2616 | int mtu, int promisc, int all_multi, int bcast, bool sleep_ok) | 2617 | int mtu, int promisc, int all_multi, int bcast, int vlanex, |
2618 | bool sleep_ok) | ||
2617 | { | 2619 | { |
2618 | struct fw_vi_rxmode_cmd c; | 2620 | struct fw_vi_rxmode_cmd c; |
2619 | 2621 | ||
@@ -2626,15 +2628,18 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, | |||
2626 | all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK; | 2628 | all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK; |
2627 | if (bcast < 0) | 2629 | if (bcast < 0) |
2628 | bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK; | 2630 | bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK; |
2631 | if (vlanex < 0) | ||
2632 | vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK; | ||
2629 | 2633 | ||
2630 | memset(&c, 0, sizeof(c)); | 2634 | memset(&c, 0, sizeof(c)); |
2631 | c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST | | 2635 | c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST | |
2632 | FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid)); | 2636 | FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid)); |
2633 | c.retval_len16 = htonl(FW_LEN16(c)); | 2637 | c.retval_len16 = htonl(FW_LEN16(c)); |
2634 | c.mtu_to_broadcasten = htonl(FW_VI_RXMODE_CMD_MTU(mtu) | | 2638 | c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) | |
2635 | FW_VI_RXMODE_CMD_PROMISCEN(promisc) | | 2639 | FW_VI_RXMODE_CMD_PROMISCEN(promisc) | |
2636 | FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) | | 2640 | FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) | |
2637 | FW_VI_RXMODE_CMD_BROADCASTEN(bcast)); | 2641 | FW_VI_RXMODE_CMD_BROADCASTEN(bcast) | |
2642 | FW_VI_RXMODE_CMD_VLANEXEN(vlanex)); | ||
2638 | return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); | 2643 | return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); |
2639 | } | 2644 | } |
2640 | 2645 | ||