X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ffm10k%2Fbase%2Ffm10k_pf.c;h=105babf4a00f07f0003140ec227f4af78eaf43b3;hb=281ccccb1a867f48beb6d357fdd73c4949c90121;hp=cc4923503adcdab980744004e4102502eda4837a;hpb=14d2d7d475655157904c09dfc053fedb0610b1ff;p=dpdk.git diff --git a/drivers/net/fm10k/base/fm10k_pf.c b/drivers/net/fm10k/base/fm10k_pf.c index cc4923503a..105babf4a0 100644 --- a/drivers/net/fm10k/base/fm10k_pf.c +++ b/drivers/net/fm10k/base/fm10k_pf.c @@ -169,19 +169,26 @@ STATIC s32 fm10k_init_hw_pf(struct fm10k_hw *hw) FM10K_TPH_RXCTRL_HDR_WROEN); } - /* set max hold interval to align with 1.024 usec in all modes */ + /* set max hold interval to align with 1.024 usec in all modes and + * store ITR scale + */ switch (hw->bus.speed) { case fm10k_bus_speed_2500: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1; + hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN1; break; case fm10k_bus_speed_5000: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2; + hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN2; break; case fm10k_bus_speed_8000: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3; + hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3; break; default: dma_ctrl = 0; + /* just in case, assume Gen3 ITR scale */ + hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3; break; } @@ -209,6 +216,7 @@ STATIC s32 fm10k_init_hw_pf(struct fm10k_hw *hw) return FM10K_SUCCESS; } +#ifndef NO_IS_SLOT_APPROPRIATE_CHECK /** * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU * @hw: pointer to hardware structure @@ -224,6 +232,7 @@ STATIC bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw) (hw->bus.width == hw->bus_caps.width); } +#endif /** * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table * @hw: pointer to hardware structure @@ -293,7 +302,6 @@ STATIC s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw) { u8 perm_addr[ETH_ALEN]; u32 serial_num; - int i; DEBUGFUNC("fm10k_read_mac_addr_pf"); @@ -317,10 +325,8 @@ STATIC s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw) perm_addr[4] = (u8)(serial_num >> 8); perm_addr[5] = (u8)(serial_num); - for (i = 0; i < ETH_ALEN; i++) { - hw->mac.perm_addr[i] = perm_addr[i]; - hw->mac.addr[i] = perm_addr[i]; - } + memcpy(hw->mac.perm_addr, perm_addr, ETH_ALEN); + memcpy(hw->mac.addr, perm_addr, ETH_ALEN); return FM10K_SUCCESS; } @@ -360,6 +366,9 @@ STATIC s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, DEBUGFUNC("fm10k_update_xc_addr_pf"); + /* clear set bit from VLAN ID */ + vid &= ~FM10K_VLAN_CLEAR; + /* if glort or VLAN are not valid return error */ if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; @@ -369,8 +378,8 @@ STATIC s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, ((u32)mac[3] << 16) | ((u32)mac[4] << 8) | ((u32)mac[5])); - mac_update.mac_upper = FM10K_CPU_TO_LE16(((u32)mac[0] << 8) | - ((u32)mac[1])); + mac_update.mac_upper = FM10K_CPU_TO_LE16(((u16)mac[0] << 8) | + ((u16)mac[1])); mac_update.vlan = FM10K_CPU_TO_LE16(vid); mac_update.glort = FM10K_CPU_TO_LE16(glort); mac_update.action = add ? 0 : 1; @@ -566,8 +575,8 @@ STATIC s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, return FM10K_ERR_PARAM; /* determine count of VSIs and queues */ - queue_count = 1 << (dglort->rss_l + dglort->pc_l); - vsi_count = 1 << (dglort->vsi_l + dglort->queue_l); + queue_count = BIT(dglort->rss_l + dglort->pc_l); + vsi_count = BIT(dglort->vsi_l + dglort->queue_l); glort = dglort->glort; q_idx = dglort->queue_b; @@ -583,8 +592,8 @@ STATIC s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, } /* determine count of PCs and queues */ - queue_count = 1 << (dglort->queue_l + dglort->rss_l + dglort->vsi_l); - pc_count = 1 << dglort->pc_l; + queue_count = BIT(dglort->queue_l + dglort->rss_l + dglort->vsi_l); + pc_count = BIT(dglort->pc_l); /* configure PC for Tx queues */ for (pc = 0; pc < pc_count; pc++) { @@ -716,7 +725,8 @@ STATIC s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, /* loop through unallocated rings assigning them back to PF */ for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) { FM10K_WRITE_REG(hw, FM10K_TXDCTL(i), 0); - FM10K_WRITE_REG(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF | vid); + FM10K_WRITE_REG(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF | + FM10K_TXQCTL_UNLIMITED_BW | vid); FM10K_WRITE_REG(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF); } @@ -749,8 +759,8 @@ STATIC s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | FM10K_RXDCTL_DROP_ON_EMPTY); FM10K_WRITE_REG(hw, FM10K_RXQCTL(vf_q_idx), - FM10K_RXQCTL_VF | - (i << FM10K_RXQCTL_VF_SHIFT)); + (i << FM10K_RXQCTL_VF_SHIFT) | + FM10K_RXQCTL_VF); /* map queue pair to VF */ FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); @@ -946,6 +956,13 @@ STATIC s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, FM10K_WRITE_REG(hw, FM10K_TDBAL(vf_q_idx), tdbal); FM10K_WRITE_REG(hw, FM10K_TDBAH(vf_q_idx), tdbah); + /* Provide the VF the ITR scale, using software-defined fields in TDLEN + * to pass the information during VF initialization. See definition of + * FM10K_TDLEN_ITR_SCALE_SHIFT for more details. + */ + FM10K_WRITE_REG(hw, FM10K_TDLEN(vf_q_idx), hw->mac.itr_scale << + FM10K_TDLEN_ITR_SCALE_SHIFT); + err_out: /* configure Queue control register */ txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) & @@ -953,7 +970,7 @@ err_out: txqctl |= (vf_idx << FM10K_TXQCTL_TC_SHIFT) | FM10K_TXQCTL_VF | vf_idx; - /* assign VID */ + /* assign VLAN ID */ for (i = 0; i < queues_per_pool; i++) FM10K_WRITE_REG(hw, FM10K_TXQCTL(vf_q_idx + i), txqctl); @@ -983,7 +1000,7 @@ STATIC s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, return FM10K_ERR_PARAM; /* clear event notification of VF FLR */ - FM10K_WRITE_REG(hw, FM10K_PFVFLREC(vf_idx / 32), 1 << (vf_idx % 32)); + FM10K_WRITE_REG(hw, FM10K_PFVFLREC(vf_idx / 32), BIT(vf_idx % 32)); /* force timeout and then disconnect the mailbox */ vf_info->mbx.timeout = 0; @@ -1018,7 +1035,7 @@ STATIC s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) | (vf_idx << FM10K_TXQCTL_TC_SHIFT) | FM10K_TXQCTL_VF | vf_idx; - rxqctl = FM10K_RXQCTL_VF | (vf_idx << FM10K_RXQCTL_VF_SHIFT); + rxqctl = (vf_idx << FM10K_RXQCTL_VF_SHIFT) | FM10K_RXQCTL_VF; /* stop further DMA and reset queue ownership back to VF */ for (i = vf_q_idx; i < (queues_per_pool + vf_q_idx); i++) { @@ -1078,10 +1095,22 @@ STATIC s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, for (i = queues_per_pool; i--;) { FM10K_WRITE_REG(hw, FM10K_TDBAL(vf_q_idx + i), tdbal); FM10K_WRITE_REG(hw, FM10K_TDBAH(vf_q_idx + i), tdbah); + /* See definition of FM10K_TDLEN_ITR_SCALE_SHIFT for an + * explanation of how TDLEN is used. + */ + FM10K_WRITE_REG(hw, FM10K_TDLEN(vf_q_idx + i), + hw->mac.itr_scale << + FM10K_TDLEN_ITR_SCALE_SHIFT); FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i); FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i); } + /* repeat the first ring for all the remaining VF rings */ + for (i = queues_per_pool; i < qmap_stride; i++) { + FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx); + FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx); + } + return FM10K_SUCCESS; } @@ -1163,19 +1192,6 @@ STATIC void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, fm10k_update_hw_stats_q(hw, q, idx, qpp); } -STATIC s32 fm10k_iov_report_timestamp_pf(struct fm10k_hw *hw, - struct fm10k_vf_info *vf_info, - u64 timestamp) -{ - u32 msg[4]; - - /* generate port state response to notify VF it is not ready */ - fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588); - fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_TIMESTAMP, timestamp); - - return vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); -} - /** * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF * @hw: Pointer to hardware structure @@ -1198,6 +1214,24 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, return hw->iov.ops.assign_int_moderator(hw, vf_idx); } +/** + * fm10k_iov_select_vid - Select correct default VLAN ID + * @hw: Pointer to hardware structure + * @vid: VLAN ID to correct + * + * Will report an error if the VLAN ID is out of range. For VID = 0, it will + * return either the pf_vid or sw_vid depending on which one is set. + */ +STATIC s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid) +{ + if (!vid) + return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid; + else if (vf_info->pf_vid && vid != vf_info->pf_vid) + return FM10K_ERR_PARAM; + else + return vid; +} + /** * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF * @hw: Pointer to hardware structure @@ -1212,9 +1246,10 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; - int err = FM10K_SUCCESS; u8 mac[ETH_ALEN]; u32 *result; + int err = FM10K_SUCCESS; + bool set; u16 vlan; u32 vid; @@ -1232,19 +1267,21 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (err) return err; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vid || (vid == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vid |= vf_info->pf_vid; - else - vid |= vf_info->sw_vid; - } else if (vid != vf_info->pf_vid) { + /* verify upper 16 bits are zero */ + if (vid >> 16) return FM10K_ERR_PARAM; - } + + set = !(vid & FM10K_VLAN_CLEAR); + vid &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, (u16)vid); + if (err < 0) + return err; + + vid = err; /* update VSI info for VF in regards to VLAN table */ - err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, - !(vid & FM10K_VLAN_CLEAR)); + err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) { @@ -1260,19 +1297,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, memcmp(mac, vf_info->mac, ETH_ALEN)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + + vlan = (u16)err; /* notify switch of request for new unicast address */ - err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, mac, vlan, - !(vlan & FM10K_VLAN_CLEAR), 0); + err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, + mac, vlan, set, 0); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) { @@ -1287,19 +1323,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + + vlan = (u16)err; /* notify switch of request for new multicast address */ - err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, - !(vlan & FM10K_VLAN_CLEAR), 0); + err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, + mac, vlan, set); } return err; @@ -1381,7 +1416,7 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, mode = fm10k_iov_supported_xcast_mode_pf(vf_info, mode); /* if mode is not currently enabled, enable it */ - if (!(FM10K_VF_FLAG_ENABLED(vf_info) & (1 << mode))) + if (!(FM10K_VF_FLAG_ENABLED(vf_info) & BIT(mode))) fm10k_update_xcast_mode_pf(hw, vf_info->glort, mode); /* swap mode back to a bit flag */ @@ -1392,6 +1427,14 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false); + /* we need to clear VF_FLAG_ENABLED flags in order to ensure + * that we actually re-enable the LPORT state below. Note that + * this has no impact if the VF is already disabled, as the + * flags are already cleared. + */ + if (!err) + vf_info->vf_flags = FM10K_VF_FLAG_CAPABLE(vf_info); + /* when enabling the port we should reset the rate limiters */ hw->iov.ops.configure_tc(hw, vf_info->vf_idx, vf_info->rate); @@ -1417,6 +1460,7 @@ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, return err; } +#ifndef NO_DEFAULT_SRIOV_MSG_HANDLERS const struct fm10k_msg_data fm10k_iov_msg_data_pf[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MSIX_HANDLER(fm10k_iov_msg_msix_pf), @@ -1425,6 +1469,7 @@ const struct fm10k_msg_data fm10k_iov_msg_data_pf[] = { FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; +#endif /** * fm10k_update_stats_hw_pf - Updates hardware related statistics of PF * @hw: pointer to hardware structure @@ -1454,9 +1499,10 @@ STATIC void fm10k_update_hw_stats_pf(struct fm10k_hw *hw, xec = fm10k_read_hw_stats_32b(hw, FM10K_STATS_XEC, &stats->xec); vlan_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_VLAN_DROP, &stats->vlan_drop); - loopback_drop = fm10k_read_hw_stats_32b(hw, - FM10K_STATS_LOOPBACK_DROP, - &stats->loopback_drop); + loopback_drop = + fm10k_read_hw_stats_32b(hw, + FM10K_STATS_LOOPBACK_DROP, + &stats->loopback_drop); nodesc_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_NODESC_DROP, &stats->nodesc_drop); @@ -1714,8 +1760,8 @@ const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = { * * This handler configures the default VLAN for the PF **/ -s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, - struct fm10k_mbx_info *mbx) +static s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, + struct fm10k_mbx_info *mbx) { u16 glort, pvid; u32 pvid_update; @@ -1737,7 +1783,7 @@ s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; - /* verify VID is valid */ + /* verify VLAN ID is valid */ if (pvid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; @@ -1804,57 +1850,81 @@ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, return FM10K_SUCCESS; } +/* currently there is no shared 1588 timestamp handler */ + const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[] = { FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_TIMESTAMP, sizeof(struct fm10k_swapi_1588_timestamp)), FM10K_TLV_ATTR_LAST }; -const struct fm10k_tlv_attr fm10k_tx_timestamp_mode_attr[] = { - FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_TIMESTAMP_MODE_RESP, - sizeof(struct fm10k_swapi_tx_timestamp_mode)), +const struct fm10k_tlv_attr fm10k_1588_clock_owner_attr[] = { + FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_CLOCK_OWNER, + sizeof(struct fm10k_swapi_1588_clock_owner)), FM10K_TLV_ATTR_LAST }; -/* currently there is no shared 1588 timestamp handler */ +const struct fm10k_tlv_attr fm10k_master_clk_offset_attr[] = { + FM10K_TLV_ATTR_U64(FM10K_PF_ATTR_ID_MASTER_CLK_OFFSET), + FM10K_TLV_ATTR_LAST +}; /** - * fm10k_request_tx_timestamp_mode_pf - Request a specific Tx timestamping mode + * fm10k_iov_notify_offset_pf - Notify VF of change in PTP offset * @hw: pointer to hardware structure - * @glort: base resource tag for this request - * @mode: integer value indicating the requested mode + * @vf_info: pointer to the vf info structure + * @offset: 64bit unsigned offset from hardware SYSTIME * - * This function will attempt to request a specific timestamp mode for the - * port so that it can receive Tx timestamp messages. + * This function sends a message to a given VF to notify it of PTP offset + * changes. **/ -STATIC s32 fm10k_request_tx_timestamp_mode_pf(struct fm10k_hw *hw, - u16 glort, - u8 mode) +STATIC void fm10k_iov_notify_offset_pf(struct fm10k_hw *hw, + struct fm10k_vf_info *vf_info, + u64 offset) { - struct fm10k_mbx_info *mbx = &hw->mbx; - u32 msg[3], timestamp_mode; + u32 msg[4]; - DEBUGFUNC("fm10k_request_timestamp_mode_pf"); + fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588); + fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_CLK_OFFSET, offset); - if (mode > FM10K_TIMESTAMP_MODE_PEP_TO_ANY) - return FM10K_ERR_PARAM; + if (vf_info->mbx.ops.enqueue_tx) + vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); +} - /* if glort is not valid return error */ - if (!fm10k_glort_valid_pf(hw, glort)) - return FM10K_ERR_PARAM; +/** + * fm10k_msg_1588_clock_owner_pf - Message handler for clock ownership from SM + * @hw: pointer to hardware structure + * @results: pointer to array containing parsed data, + * @mbx: Pointer to mailbox information structure + * + * This handler configures the FM10K_HW_FLAG_CLOCK_OWNER field for the PF + */ +s32 fm10k_msg_1588_clock_owner_pf(struct fm10k_hw *hw, u32 **results, + struct fm10k_mbx_info *mbx) +{ + struct fm10k_swapi_1588_clock_owner msg; + u16 glort; + s32 err; - /* write timestamp mode as a single u32 value, - * lower 16 bits: glort - * upper 16 bits: mode - */ - timestamp_mode = ((u32)mode << 16) | glort; + UNREFERENCED_1PARAMETER(mbx); + DEBUGFUNC("fm10k_msg_1588_clock_owner"); - /* generate message requesting change to xcast mode */ - fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_TX_TIMESTAMP_MODE); - fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_TIMESTAMP_MODE_REQ, timestamp_mode); + err = fm10k_tlv_attr_get_le_struct( + results[FM10K_PF_ATTR_ID_1588_CLOCK_OWNER], + &msg, sizeof(msg)); + if (err) + return err; - /* load onto outgoing mailbox */ - return mbx->ops.enqueue_tx(hw, mbx, msg); + /* We own the clock iff the glort matches us and the enabled field is + * true. Otherwise, the clock must belong to some other port. + */ + glort = le16_to_cpu(msg.glort); + if (fm10k_glort_valid_pf(hw, glort) && msg.enabled) + hw->flags |= FM10K_HW_FLAG_CLOCK_OWNER; + else + hw->flags &= ~FM10K_HW_FLAG_CLOCK_OWNER; + + return FM10K_SUCCESS; } /** @@ -1876,6 +1946,10 @@ STATIC s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb) DEBUGFUNC("fm10k_adjust_systime_pf"); + /* ensure that we control the clock */ + if (!(hw->flags & FM10K_HW_FLAG_CLOCK_OWNER)) + return FM10K_ERR_DEVICE_NOT_SUPPORTED; + /* if sw_addr is not set we don't have switch register access */ if (!hw->sw_addr) return ppb ? FM10K_ERR_PARAM : FM10K_SUCCESS; @@ -1901,14 +1975,41 @@ STATIC s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb) if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK) return FM10K_ERR_PARAM; - if (ppb < 0) - systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE; + if (ppb > 0) + systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE; FM10K_WRITE_SW_REG(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust); return FM10K_SUCCESS; } +/** + * fm10k_notify_offset_pf - Notify switch of change in PTP offset + * @hw: pointer to hardware structure + * @offset: 64bit unsigned offset of SYSTIME + * + * This function sends a message to the switch to indicate a change in the + * offset of the hardware SYSTIME registers. The switch manager is + * responsible for transmitting this message to other hosts. + */ +STATIC s32 fm10k_notify_offset_pf(struct fm10k_hw *hw, u64 offset) +{ + struct fm10k_mbx_info *mbx = &hw->mbx; + u32 msg[4]; + + DEBUGFUNC("fm10k_notify_offset_pf"); + + /* ensure that we control the clock */ + if (!(hw->flags & FM10K_HW_FLAG_CLOCK_OWNER)) + return FM10K_ERR_DEVICE_NOT_SUPPORTED; + + fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_MASTER_CLK_OFFSET); + fm10k_tlv_attr_put_u64(msg, FM10K_PF_ATTR_ID_MASTER_CLK_OFFSET, offset); + + /* load onto outgoing mailbox */ + return mbx->ops.enqueue_tx(hw, mbx, msg); +} + /** * fm10k_read_systime_pf - Reads value of systime registers * @hw: pointer to the hardware structure @@ -1941,6 +2042,7 @@ static const struct fm10k_msg_data fm10k_msg_data_pf[] = { FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf), + FM10K_PF_MSG_1588_CLOCK_OWNER_HANDLER(fm10k_msg_1588_clock_owner_pf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; @@ -1964,7 +2066,9 @@ s32 fm10k_init_ops_pf(struct fm10k_hw *hw) mac->ops.init_hw = &fm10k_init_hw_pf; mac->ops.start_hw = &fm10k_start_hw_generic; mac->ops.stop_hw = &fm10k_stop_hw_generic; +#ifndef NO_IS_SLOT_APPROPRIATE_CHECK mac->ops.is_slot_appropriate = &fm10k_is_slot_appropriate_pf; +#endif mac->ops.update_vlan = &fm10k_update_vlan_pf; mac->ops.read_mac_addr = &fm10k_read_mac_addr_pf; mac->ops.update_uc_addr = &fm10k_update_uc_addr_pf; @@ -1979,8 +2083,8 @@ s32 fm10k_init_ops_pf(struct fm10k_hw *hw) mac->ops.get_fault = &fm10k_get_fault_pf; mac->ops.get_host_state = &fm10k_get_host_state_pf; mac->ops.adjust_systime = &fm10k_adjust_systime_pf; + mac->ops.notify_offset = &fm10k_notify_offset_pf; mac->ops.read_systime = &fm10k_read_systime_pf; - mac->ops.request_tx_timestamp_mode = &fm10k_request_tx_timestamp_mode_pf; mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw); @@ -1992,7 +2096,7 @@ s32 fm10k_init_ops_pf(struct fm10k_hw *hw) iov->ops.set_lport = &fm10k_iov_set_lport_pf; iov->ops.reset_lport = &fm10k_iov_reset_lport_pf; iov->ops.update_stats = &fm10k_iov_update_stats_pf; - iov->ops.report_timestamp = &fm10k_iov_report_timestamp_pf; + iov->ops.notify_offset = &fm10k_iov_notify_offset_pf; return fm10k_sm_mbx_init(hw, &hw->mbx, fm10k_msg_data_pf); }