Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind...
[pandora-kernel.git] / drivers / net / cxgb4 / t4_hw.c
index cadead5..da272a9 100644 (file)
@@ -347,33 +347,21 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        return 0;
 }
 
-#define VPD_ENTRY(name, len) \
-       u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]
-
 /*
  * Partial EEPROM Vital Product Data structure.  Includes only the ID and
- * VPD-R sections.
+ * VPD-R header.
  */
-struct t4_vpd {
+struct t4_vpd_hdr {
        u8  id_tag;
        u8  id_len[2];
        u8  id_data[ID_LEN];
        u8  vpdr_tag;
        u8  vpdr_len[2];
-       VPD_ENTRY(pn, 16);                     /* part number */
-       VPD_ENTRY(ec, EC_LEN);                 /* EC level */
-       VPD_ENTRY(sn, SERNUM_LEN);             /* serial number */
-       VPD_ENTRY(na, 12);                     /* MAC address base */
-       VPD_ENTRY(port_type, 8);               /* port types */
-       VPD_ENTRY(gpio, 14);                   /* GPIO usage */
-       VPD_ENTRY(cclk, 6);                    /* core clock */
-       VPD_ENTRY(port_addr, 8);               /* port MDIO addresses */
-       VPD_ENTRY(rv, 1);                      /* csum */
-       u32 pad;                  /* for multiple-of-4 sizing and alignment */
 };
 
 #define EEPROM_STAT_ADDR   0x7bfc
 #define VPD_BASE           0
+#define VPD_LEN            512
 
 /**
  *     t4_seeprom_wp - enable/disable EEPROM write protection
@@ -398,16 +386,36 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable)
  */
 static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 {
-       int ret;
-       struct t4_vpd vpd;
-       u8 *q = (u8 *)&vpd, csum;
+       int i, ret;
+       int ec, sn, v2;
+       u8 vpd[VPD_LEN], csum;
+       unsigned int vpdr_len;
+       const struct t4_vpd_hdr *v;
 
-       ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), &vpd);
+       ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
        if (ret < 0)
                return ret;
 
-       for (csum = 0; q <= vpd.rv_data; q++)
-               csum += *q;
+       v = (const struct t4_vpd_hdr *)vpd;
+       vpdr_len = pci_vpd_lrdt_size(&v->vpdr_tag);
+       if (vpdr_len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
+               dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
+               return -EINVAL;
+       }
+
+#define FIND_VPD_KW(var, name) do { \
+       var = pci_vpd_find_info_keyword(&v->id_tag, sizeof(struct t4_vpd_hdr), \
+                                       vpdr_len, name); \
+       if (var < 0) { \
+               dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
+               return -EINVAL; \
+       } \
+       var += PCI_VPD_INFO_FLD_HDR_SIZE; \
+} while (0)
+
+       FIND_VPD_KW(i, "RV");
+       for (csum = 0; i >= 0; i--)
+               csum += vpd[i];
 
        if (csum) {
                dev_err(adapter->pdev_dev,
@@ -415,12 +423,18 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
                return -EINVAL;
        }
 
-       p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10);
-       memcpy(p->id, vpd.id_data, sizeof(vpd.id_data));
+       FIND_VPD_KW(ec, "EC");
+       FIND_VPD_KW(sn, "SN");
+       FIND_VPD_KW(v2, "V2");
+#undef FIND_VPD_KW
+
+       p->cclk = simple_strtoul(vpd + v2, NULL, 10);
+       memcpy(p->id, v->id_data, ID_LEN);
        strim(p->id);
-       memcpy(p->ec, vpd.ec_data, sizeof(vpd.ec_data));
+       memcpy(p->ec, vpd + ec, EC_LEN);
        strim(p->ec);
-       memcpy(p->sn, vpd.sn_data, sizeof(vpd.sn_data));
+       i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
+       memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
        strim(p->sn);
        return 0;
 }
@@ -872,22 +886,6 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
 
-/**
- *     t4_set_vlan_accel - configure HW VLAN extraction
- *     @adap: the adapter
- *     @ports: bitmap of adapter ports to operate on
- *     @on: enable (1) or disable (0) HW VLAN extraction
- *
- *     Enables or disables HW extraction of VLAN tags for the ports specified
- *     by @ports.  @ports is a bitmap with the ith bit designating the port
- *     associated with the ith adapter channel.
- */
-void t4_set_vlan_accel(struct adapter *adap, unsigned int ports, int on)
-{
-       ports <<= VLANEXTENABLE_SHIFT;
-       t4_set_reg_field(adap, TP_OUT_CONFIG, ports, on ? ports : 0);
-}
-
 struct intr_info {
        unsigned int mask;       /* bits to check in interrupt status */
        const char *msg;         /* message to print or NULL */
@@ -2610,12 +2608,14 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
  *     @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
  *     @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
  *     @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
+ *     @vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change
  *     @sleep_ok: if true we may sleep while awaiting command completion
  *
  *     Sets Rx properties of a virtual interface.
  */
 int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
-                 int mtu, int promisc, int all_multi, int bcast, bool sleep_ok)
+                 int mtu, int promisc, int all_multi, int bcast, int vlanex,
+                 bool sleep_ok)
 {
        struct fw_vi_rxmode_cmd c;
 
@@ -2628,15 +2628,18 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
                all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK;
        if (bcast < 0)
                bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK;
+       if (vlanex < 0)
+               vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK;
 
        memset(&c, 0, sizeof(c));
        c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST |
                             FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid));
        c.retval_len16 = htonl(FW_LEN16(c));
-       c.mtu_to_broadcasten = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
-                                    FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
-                                    FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
-                                    FW_VI_RXMODE_CMD_BROADCASTEN(bcast));
+       c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
+                                 FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
+                                 FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
+                                 FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
+                                 FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
        return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
 }