summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2014-07-25 00:30:55 +0000
committernp <np@FreeBSD.org>2014-07-25 00:30:55 +0000
commit103bd6e167d38f5a8626fd51ccfcba53cd614e94 (patch)
tree8a7ed58dd1bc0ba5730f3c330b7e680336d19dc7
parentf9d311d90a7334dc987df3363e2870e342da6ddd (diff)
downloadFreeBSD-src-103bd6e167d38f5a8626fd51ccfcba53cd614e94.zip
FreeBSD-src-103bd6e167d38f5a8626fd51ccfcba53cd614e94.tar.gz
MFC r268640 and r268989.
r268640: Allow multi-byte reads in the private CHELSIO_T4_GET_I2C ioctl. The firmware allows up to 48B to be read this way but the driver limits itself to 8B at a time to remain compatible with old cxgbetool binaries. r268989: Add missing newline to an error message.
-rw-r--r--sys/dev/cxgbe/common/common.h10
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c111
-rw-r--r--sys/dev/cxgbe/t4_main.c8
-rw-r--r--sys/dev/cxgbe/t4_sge.c2
4 files changed, 93 insertions, 38 deletions
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index e3883db..84f31c7 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -583,12 +583,18 @@ int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool rx_en, bool tx_en);
int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
unsigned int nblinks);
-int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
- u8 dev_addr, u8 offset, u8 *valp);
int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int *valp);
int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int val);
+int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf);
+int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf);
int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
unsigned int pf, unsigned int vf, unsigned int iqid,
unsigned int fl0id, unsigned int fl1id);
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index a602ead..e4badf2 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -4145,36 +4145,6 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32
}
/**
- * t4_i2c_rd - read a byte from an i2c addressable device
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @port_id: the port id
- * @dev_addr: the i2c device address
- * @offset: the byte offset to read from
- * @valp: where to store the value
- */
-int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
- u8 dev_addr, u8 offset, u8 *valp)
-{
- int ret;
- struct fw_ldst_cmd c;
-
- memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_READ |
- V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_I2C));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.i2c_deprecated.pid_pkd = V_FW_LDST_CMD_PID(port_id);
- c.u.i2c_deprecated.base = dev_addr;
- c.u.i2c_deprecated.boffset = offset;
-
- ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
- if (ret == 0)
- *valp = c.u.i2c_deprecated.data;
- return ret;
-}
-
-/**
* t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -4234,6 +4204,87 @@ int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
}
/**
+ * t4_i2c_rd - read I2C data from adapter
+ * @adap: the adapter
+ * @port: Port number if per-port device; <0 if not
+ * @devid: per-port device ID or absolute device ID
+ * @offset: byte offset into device I2C space
+ * @len: byte length of I2C space data
+ * @buf: buffer in which to return I2C data
+ *
+ * Reads the I2C data from the indicated device and location.
+ */
+int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf)
+{
+ struct fw_ldst_cmd ldst;
+ int ret;
+
+ if (port >= 4 ||
+ devid >= 256 ||
+ offset >= 256 ||
+ len > sizeof ldst.u.i2c.data)
+ return -EINVAL;
+
+ memset(&ldst, 0, sizeof ldst);
+ ldst.op_to_addrspace =
+ cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_READ |
+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
+ ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
+ ldst.u.i2c.pid = (port < 0 ? 0xff : port);
+ ldst.u.i2c.did = devid;
+ ldst.u.i2c.boffset = offset;
+ ldst.u.i2c.blen = len;
+ ret = t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
+ if (!ret)
+ memcpy(buf, ldst.u.i2c.data, len);
+ return ret;
+}
+
+/**
+ * t4_i2c_wr - write I2C data to adapter
+ * @adap: the adapter
+ * @port: Port number if per-port device; <0 if not
+ * @devid: per-port device ID or absolute device ID
+ * @offset: byte offset into device I2C space
+ * @len: byte length of I2C space data
+ * @buf: buffer containing new I2C data
+ *
+ * Write the I2C data to the indicated device and location.
+ */
+int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf)
+{
+ struct fw_ldst_cmd ldst;
+
+ if (port >= 4 ||
+ devid >= 256 ||
+ offset >= 256 ||
+ len > sizeof ldst.u.i2c.data)
+ return -EINVAL;
+
+ memset(&ldst, 0, sizeof ldst);
+ ldst.op_to_addrspace =
+ cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
+ ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
+ ldst.u.i2c.pid = (port < 0 ? 0xff : port);
+ ldst.u.i2c.did = devid;
+ ldst.u.i2c.boffset = offset;
+ ldst.u.i2c.blen = len;
+ memcpy(ldst.u.i2c.data, buf, len);
+ return t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
+}
+
+/**
* t4_sge_ctxt_flush - flush the SGE context cache
* @adap: the adapter
* @mbox: mailbox to use for the FW command
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index aa5d4fe..8a7d041 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -7381,16 +7381,14 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports)
return (EINVAL);
- if (i2cd->len > 1) {
- /* XXX: need fw support for longer reads in one go */
- return (ENOTSUP);
- }
+ if (i2cd->len > sizeof(i2cd->data))
+ return (EFBIG);
rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd");
if (rc)
return (rc);
rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr,
- i2cd->offset, &i2cd->data[0]);
+ i2cd->offset, i2cd->len, &i2cd->data[0]);
end_synchronized_op(sc, 0);
return (rc);
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index ed19b12..9bdc446 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -2741,7 +2741,7 @@ alloc_eq(struct adapter *sc, struct port_info *pi, struct sge_eq *eq)
}
if (rc != 0) {
device_printf(sc->dev,
- "failed to allocate egress queue(%d): %d",
+ "failed to allocate egress queue(%d): %d\n",
eq->flags & EQ_TYPEMASK, rc);
}
OpenPOWER on IntegriCloud