From ea463f2dc02027deb463b817bfcf4ecec4dc6d95 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Fri, 29 Aug 2014 18:02:58 +0000 Subject: [PATCH] * Add SIOCGI2C driver ioctl used to retrieve i2c info. * Convert ixgbe to use this ioctl * Convert ifconfig to use generic i2c handler for "ix" interfaces. Approved by: Eric Joyner (ixgbe part) MFC after: 2 weeks Sponsored by: Yandex LLC --- sbin/ifconfig/sfp.c | 74 ++++++++++++++++++------------------------- sys/dev/ixgbe/ixgbe.c | 17 +++++++--- sys/dev/ixgbe/ixgbe.h | 12 ------- sys/net/if.h | 13 ++++++++ sys/sys/sockio.h | 1 + 5 files changed, 57 insertions(+), 60 deletions(-) diff --git a/sbin/ifconfig/sfp.c b/sbin/ifconfig/sfp.c index 9647eb31859f..d85d4d857c9d 100644 --- a/sbin/ifconfig/sfp.c +++ b/sbin/ifconfig/sfp.c @@ -624,53 +624,41 @@ get_qsfp_tx_power(struct i2c_info *ii, char *buf, size_t size, int chan) convert_sff_power(ii, buf, size, xbuf); } -/* Intel ixgbe-specific structures and handlers */ -struct ixgbe_i2c_req { - uint8_t dev_addr; - uint8_t offset; - uint8_t len; - uint8_t data[8]; -}; -#define SIOCGI2C SIOCGIFGENERIC - -static int -read_i2c_ixgbe(struct i2c_info *ii, uint8_t addr, uint8_t off, uint8_t len, - caddr_t buf) -{ - struct ixgbe_i2c_req ixreq; - int i; - - if (ii->error != 0) - return (ii->error); - - ii->ifr->ifr_data = (caddr_t)&ixreq; - - memset(&ixreq, 0, sizeof(ixreq)); - ixreq.dev_addr = addr; - - for (i = 0; i < len; i += 1) { - ixreq.offset = off + i; - ixreq.len = 1; - ixreq.data[0] = '\0'; - - if (ioctl(ii->s, SIOCGI2C, ii->ifr) != 0) { - ii->error = errno; - return (errno); - } - memcpy(&buf[i], ixreq.data, 1); - } - - return (0); -} - /* Generic handler */ static int read_i2c_generic(struct i2c_info *ii, uint8_t addr, uint8_t off, uint8_t len, caddr_t buf) { + struct ifi2creq req; + int i, l; - ii->error = EINVAL; - return (-1); + if (ii->error != 0) + return (ii->error); + + ii->ifr->ifr_data = (caddr_t)&req; + + i = 0; + l = 0; + memset(&req, 0, sizeof(req)); + req.dev_addr = addr; + req.offset = off; + req.len = len; + + while (len > 0) { + l = (len > sizeof(req.data)) ? sizeof(req.data) : len; + req.len = l; + if (ioctl(ii->s, SIOCGI2C, ii->ifr) != 0) { + ii->error = errno; + return (errno); + } + + memcpy(&buf[i], req.data, l); + len -= l; + i += l; + req.offset += l; + } + + return (0); } static void @@ -766,6 +754,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose) { struct i2c_info ii; + memset(&ii, 0, sizeof(ii)); /* Prepare necessary into to pass to NIC handler */ ii.s = s; ii.ifr = ifr; @@ -774,9 +763,8 @@ sfp_status(int s, struct ifreq *ifr, int verbose) * Check if we have i2c support for particular driver. * TODO: Determine driver by original name. */ - memset(&ii, 0, sizeof(ii)); if (strncmp(ifr->ifr_name, "ix", 2) == 0) { - ii.f = read_i2c_ixgbe; + ii.f = read_i2c_generic; print_sfp_status(&ii, verbose); } else if (strncmp(ifr->ifr_name, "cxl", 3) == 0) { ii.port_id = atoi(&ifr->ifr_name[3]); diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index c39a63a2afe4..c4148fa1403a 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -1068,17 +1068,24 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data) } case SIOCGI2C: { - struct ixgbe_i2c_req i2c; + struct ifi2creq i2c; + int i; IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)"); error = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); - if (error) + if (error != 0) break; - if ((i2c.dev_addr != 0xA0) || (i2c.dev_addr != 0xA2)){ + if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) { error = EINVAL; break; } - hw->phy.ops.read_i2c_byte(hw, i2c.offset, - i2c.dev_addr, i2c.data); + if (i2c.len > sizeof(i2c.data)) { + error = EINVAL; + break; + } + + for (i = 0; i < i2c.len; i++) + hw->phy.ops.read_i2c_byte(hw, i2c.offset + i, + i2c.dev_addr, &i2c.data[i]); error = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); break; } diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index ab3cc9f86bf3..70f1f873fff6 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -197,9 +197,6 @@ #define IXGBE_BR_SIZE 4096 #define IXGBE_QUEUE_MIN_FREE 32 -/* IOCTL define to gather SFP+ Diagnostic data */ -#define SIOCGI2C SIOCGIFGENERIC - /* Offload bits in mbuf flag */ #if __FreeBSD_version >= 800000 #define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP) @@ -233,15 +230,6 @@ typedef struct _ixgbe_vendor_info_t { unsigned int index; } ixgbe_vendor_info_t; - -/* This is used to get SFP+ module data */ -struct ixgbe_i2c_req { - u8 dev_addr; - u8 offset; - u8 len; - u8 data[8]; -}; - struct ixgbe_tx_buf { union ixgbe_adv_tx_desc *eop; struct mbuf *m_head; diff --git a/sys/net/if.h b/sys/net/if.h index 8482dafa2cf7..792704afd223 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -510,6 +510,19 @@ struct ifgroupreq { #define ifgr_groups ifgr_ifgru.ifgru_groups }; +/* + * Structure used to request i2c data + * from interface transceivers. + */ +struct ifi2creq { + uint8_t dev_addr; /* i2c address (0xA0, 0xA2) */ + uint8_t offset; /* read offset */ + uint8_t len; /* read length */ + uint8_t spare0; + uint32_t spare1; + uint8_t data[8]; /* read buffer */ +}; + #endif /* __BSD_VISIBLE */ #ifdef _KERNEL diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index 3dd68fb5e24e..7b09acfaa779 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -96,6 +96,7 @@ #define SIOCGIFSTATUS _IOWR('i', 59, struct ifstat) /* get IF status */ #define SIOCSIFLLADDR _IOW('i', 60, struct ifreq) /* set linklevel addr */ +#define SIOCGI2C _IOWR('i', 61, struct ifstat) /* get I2C data */ #define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif addres */ #define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */