diff options
author | Raghu Vatsavayi <rvatsavayi@caviumnetworks.com> | 2016-12-08 16:00:47 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-12-08 18:16:51 -0500 |
commit | f625fe620815403676a012b18c3ddc501c73f03d (patch) | |
tree | 674a5322d4371cf1286442a5a6af95edf092c2ba /drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | |
parent | d8ab848c6b4fc2efee14fd37afdc4d27fc237f4f (diff) |
liquidio VF timestamp
Adds support for VF timestamp.
Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cavium/liquidio/lio_vf_main.c')
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 180 |
1 files changed, 179 insertions, 1 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index 97e9b6b5b082..dc0e1f6c743e 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | |||
@@ -42,6 +42,7 @@ MODULE_PARM_DESC(debug, "NETIF_MSG debug bits"); | |||
42 | #define LIO_IFSTATE_DROQ_OPS 0x01 | 42 | #define LIO_IFSTATE_DROQ_OPS 0x01 |
43 | #define LIO_IFSTATE_REGISTERED 0x02 | 43 | #define LIO_IFSTATE_REGISTERED 0x02 |
44 | #define LIO_IFSTATE_RUNNING 0x04 | 44 | #define LIO_IFSTATE_RUNNING 0x04 |
45 | #define LIO_IFSTATE_RX_TIMESTAMP_ENABLED 0x08 | ||
45 | 46 | ||
46 | struct liquidio_if_cfg_context { | 47 | struct liquidio_if_cfg_context { |
47 | int octeon_id; | 48 | int octeon_id; |
@@ -65,6 +66,12 @@ struct liquidio_rx_ctl_context { | |||
65 | int cond; | 66 | int cond; |
66 | }; | 67 | }; |
67 | 68 | ||
69 | struct oct_timestamp_resp { | ||
70 | u64 rh; | ||
71 | u64 timestamp; | ||
72 | u64 status; | ||
73 | }; | ||
74 | |||
68 | union tx_info { | 75 | union tx_info { |
69 | u64 u64; | 76 | u64 u64; |
70 | struct { | 77 | struct { |
@@ -1894,6 +1901,169 @@ static int liquidio_change_mtu(struct net_device *netdev, int new_mtu) | |||
1894 | return 0; | 1901 | return 0; |
1895 | } | 1902 | } |
1896 | 1903 | ||
1904 | /** | ||
1905 | * \brief Handler for SIOCSHWTSTAMP ioctl | ||
1906 | * @param netdev network device | ||
1907 | * @param ifr interface request | ||
1908 | * @param cmd command | ||
1909 | */ | ||
1910 | static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) | ||
1911 | { | ||
1912 | struct lio *lio = GET_LIO(netdev); | ||
1913 | struct hwtstamp_config conf; | ||
1914 | |||
1915 | if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf))) | ||
1916 | return -EFAULT; | ||
1917 | |||
1918 | if (conf.flags) | ||
1919 | return -EINVAL; | ||
1920 | |||
1921 | switch (conf.tx_type) { | ||
1922 | case HWTSTAMP_TX_ON: | ||
1923 | case HWTSTAMP_TX_OFF: | ||
1924 | break; | ||
1925 | default: | ||
1926 | return -ERANGE; | ||
1927 | } | ||
1928 | |||
1929 | switch (conf.rx_filter) { | ||
1930 | case HWTSTAMP_FILTER_NONE: | ||
1931 | break; | ||
1932 | case HWTSTAMP_FILTER_ALL: | ||
1933 | case HWTSTAMP_FILTER_SOME: | ||
1934 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
1935 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
1936 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
1937 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
1938 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
1939 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
1940 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
1941 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
1942 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
1943 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||
1944 | case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||
1945 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
1946 | conf.rx_filter = HWTSTAMP_FILTER_ALL; | ||
1947 | break; | ||
1948 | default: | ||
1949 | return -ERANGE; | ||
1950 | } | ||
1951 | |||
1952 | if (conf.rx_filter == HWTSTAMP_FILTER_ALL) | ||
1953 | ifstate_set(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED); | ||
1954 | |||
1955 | else | ||
1956 | ifstate_reset(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED); | ||
1957 | |||
1958 | return copy_to_user(ifr->ifr_data, &conf, sizeof(conf)) ? -EFAULT : 0; | ||
1959 | } | ||
1960 | |||
1961 | /** | ||
1962 | * \brief ioctl handler | ||
1963 | * @param netdev network device | ||
1964 | * @param ifr interface request | ||
1965 | * @param cmd command | ||
1966 | */ | ||
1967 | static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||
1968 | { | ||
1969 | switch (cmd) { | ||
1970 | case SIOCSHWTSTAMP: | ||
1971 | return hwtstamp_ioctl(netdev, ifr); | ||
1972 | default: | ||
1973 | return -EOPNOTSUPP; | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | static void handle_timestamp(struct octeon_device *oct, u32 status, void *buf) | ||
1978 | { | ||
1979 | struct sk_buff *skb = (struct sk_buff *)buf; | ||
1980 | struct octnet_buf_free_info *finfo; | ||
1981 | struct oct_timestamp_resp *resp; | ||
1982 | struct octeon_soft_command *sc; | ||
1983 | struct lio *lio; | ||
1984 | |||
1985 | finfo = (struct octnet_buf_free_info *)skb->cb; | ||
1986 | lio = finfo->lio; | ||
1987 | sc = finfo->sc; | ||
1988 | oct = lio->oct_dev; | ||
1989 | resp = (struct oct_timestamp_resp *)sc->virtrptr; | ||
1990 | |||
1991 | if (status != OCTEON_REQUEST_DONE) { | ||
1992 | dev_err(&oct->pci_dev->dev, "Tx timestamp instruction failed. Status: %llx\n", | ||
1993 | CVM_CAST64(status)); | ||
1994 | resp->timestamp = 0; | ||
1995 | } | ||
1996 | |||
1997 | octeon_swap_8B_data(&resp->timestamp, 1); | ||
1998 | |||
1999 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { | ||
2000 | struct skb_shared_hwtstamps ts; | ||
2001 | u64 ns = resp->timestamp; | ||
2002 | |||
2003 | netif_info(lio, tx_done, lio->netdev, | ||
2004 | "Got resulting SKBTX_HW_TSTAMP skb=%p ns=%016llu\n", | ||
2005 | skb, (unsigned long long)ns); | ||
2006 | ts.hwtstamp = ns_to_ktime(ns + lio->ptp_adjust); | ||
2007 | skb_tstamp_tx(skb, &ts); | ||
2008 | } | ||
2009 | |||
2010 | octeon_free_soft_command(oct, sc); | ||
2011 | tx_buffer_free(skb); | ||
2012 | } | ||
2013 | |||
2014 | /* \brief Send a data packet that will be timestamped | ||
2015 | * @param oct octeon device | ||
2016 | * @param ndata pointer to network data | ||
2017 | * @param finfo pointer to private network data | ||
2018 | */ | ||
2019 | static int send_nic_timestamp_pkt(struct octeon_device *oct, | ||
2020 | struct octnic_data_pkt *ndata, | ||
2021 | struct octnet_buf_free_info *finfo) | ||
2022 | { | ||
2023 | struct octeon_soft_command *sc; | ||
2024 | int ring_doorbell; | ||
2025 | struct lio *lio; | ||
2026 | int retval; | ||
2027 | u32 len; | ||
2028 | |||
2029 | lio = finfo->lio; | ||
2030 | |||
2031 | sc = octeon_alloc_soft_command_resp(oct, &ndata->cmd, | ||
2032 | sizeof(struct oct_timestamp_resp)); | ||
2033 | finfo->sc = sc; | ||
2034 | |||
2035 | if (!sc) { | ||
2036 | dev_err(&oct->pci_dev->dev, "No memory for timestamped data packet\n"); | ||
2037 | return IQ_SEND_FAILED; | ||
2038 | } | ||
2039 | |||
2040 | if (ndata->reqtype == REQTYPE_NORESP_NET) | ||
2041 | ndata->reqtype = REQTYPE_RESP_NET; | ||
2042 | else if (ndata->reqtype == REQTYPE_NORESP_NET_SG) | ||
2043 | ndata->reqtype = REQTYPE_RESP_NET_SG; | ||
2044 | |||
2045 | sc->callback = handle_timestamp; | ||
2046 | sc->callback_arg = finfo->skb; | ||
2047 | sc->iq_no = ndata->q_no; | ||
2048 | |||
2049 | len = (u32)((struct octeon_instr_ih3 *)(&sc->cmd.cmd3.ih3))->dlengsz; | ||
2050 | |||
2051 | ring_doorbell = 1; | ||
2052 | |||
2053 | retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd, | ||
2054 | sc, len, ndata->reqtype); | ||
2055 | |||
2056 | if (retval == IQ_SEND_FAILED) { | ||
2057 | dev_err(&oct->pci_dev->dev, "timestamp data packet failed status: %x\n", | ||
2058 | retval); | ||
2059 | octeon_free_soft_command(oct, sc); | ||
2060 | } else { | ||
2061 | netif_info(lio, tx_queued, lio->netdev, "Queued timestamp packet\n"); | ||
2062 | } | ||
2063 | |||
2064 | return retval; | ||
2065 | } | ||
2066 | |||
1897 | /** \brief Transmit networks packets to the Octeon interface | 2067 | /** \brief Transmit networks packets to the Octeon interface |
1898 | * @param skbuff skbuff struct to be passed to network layer. | 2068 | * @param skbuff skbuff struct to be passed to network layer. |
1899 | * @param netdev pointer to network device | 2069 | * @param netdev pointer to network device |
@@ -1986,6 +2156,10 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
1986 | cmdsetup.s.transport_csum = 1; | 2156 | cmdsetup.s.transport_csum = 1; |
1987 | } | 2157 | } |
1988 | } | 2158 | } |
2159 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { | ||
2160 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | ||
2161 | cmdsetup.s.timestamp = 1; | ||
2162 | } | ||
1989 | 2163 | ||
1990 | if (!skb_shinfo(skb)->nr_frags) { | 2164 | if (!skb_shinfo(skb)->nr_frags) { |
1991 | cmdsetup.s.u.datasize = skb->len; | 2165 | cmdsetup.s.u.datasize = skb->len; |
@@ -2110,7 +2284,10 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
2110 | irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK; | 2284 | irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK; |
2111 | } | 2285 | } |
2112 | 2286 | ||
2113 | status = octnet_send_nic_data_pkt(oct, &ndata); | 2287 | if (unlikely(cmdsetup.s.timestamp)) |
2288 | status = send_nic_timestamp_pkt(oct, &ndata, finfo); | ||
2289 | else | ||
2290 | status = octnet_send_nic_data_pkt(oct, &ndata); | ||
2114 | if (status == IQ_SEND_FAILED) | 2291 | if (status == IQ_SEND_FAILED) |
2115 | goto lio_xmit_failed; | 2292 | goto lio_xmit_failed; |
2116 | 2293 | ||
@@ -2382,6 +2559,7 @@ static const struct net_device_ops lionetdevops = { | |||
2382 | .ndo_vlan_rx_add_vid = liquidio_vlan_rx_add_vid, | 2559 | .ndo_vlan_rx_add_vid = liquidio_vlan_rx_add_vid, |
2383 | .ndo_vlan_rx_kill_vid = liquidio_vlan_rx_kill_vid, | 2560 | .ndo_vlan_rx_kill_vid = liquidio_vlan_rx_kill_vid, |
2384 | .ndo_change_mtu = liquidio_change_mtu, | 2561 | .ndo_change_mtu = liquidio_change_mtu, |
2562 | .ndo_do_ioctl = liquidio_ioctl, | ||
2385 | .ndo_fix_features = liquidio_fix_features, | 2563 | .ndo_fix_features = liquidio_fix_features, |
2386 | .ndo_set_features = liquidio_set_features, | 2564 | .ndo_set_features = liquidio_set_features, |
2387 | .ndo_udp_tunnel_add = liquidio_add_vxlan_port, | 2565 | .ndo_udp_tunnel_add = liquidio_add_vxlan_port, |