Author: np
Date: Tue Jul 15 01:03:29 2014
New Revision: 268640
URL: http://svnweb.freebsd.org/changeset/base/268640

Log:
  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.
  
  MFC after:    1 week

Modified:
  head/sys/dev/cxgbe/common/common.h
  head/sys/dev/cxgbe/common/t4_hw.c
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/common/common.h
==============================================================================
--- head/sys/dev/cxgbe/common/common.h  Tue Jul 15 00:27:08 2014        
(r268639)
+++ head/sys/dev/cxgbe/common/common.h  Tue Jul 15 01:03:29 2014        
(r268640)
@@ -585,12 +585,18 @@ int t4_enable_vi_ns(struct adapter *adap
                 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);

Modified: head/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.c   Tue Jul 15 00:27:08 2014        
(r268639)
+++ head/sys/dev/cxgbe/common/t4_hw.c   Tue Jul 15 01:03:29 2014        
(r268640)
@@ -4148,36 +4148,6 @@ int t4_fwaddrspace_write(struct adapter 
 }
 
 /**
- *     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
@@ -4237,6 +4207,87 @@ int t4_mdio_wr(struct adapter *adap, uns
 }
 
 /**
+ *     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

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c        Tue Jul 15 00:27:08 2014        
(r268639)
+++ head/sys/dev/cxgbe/t4_main.c        Tue Jul 15 01:03:29 2014        
(r268640)
@@ -7535,16 +7535,14 @@ read_i2c(struct adapter *sc, struct t4_i
        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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to