* 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
This commit is contained in:
parent
a10816090b
commit
ea463f2dc0
@ -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]);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
13
sys/net/if.h
13
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
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user