1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2017-2019 NXP */
6 static void enetc_clean_cbdr(struct enetc_si *si)
8 struct enetc_cbdr *ring = &si->cbd_ring;
9 struct enetc_cbd *dest_cbd;
12 i = ring->next_to_clean;
14 while (enetc_rd_reg(ring->cir) != i) {
15 dest_cbd = ENETC_CBD(*ring, i);
16 status = dest_cbd->status_flags & ENETC_CBD_STATUS_MASK;
18 dev_warn(&si->pdev->dev, "CMD err %04x for cmd %04x\n",
19 status, dest_cbd->cmd);
21 memset(dest_cbd, 0, sizeof(*dest_cbd));
23 i = (i + 1) % ring->bd_count;
26 ring->next_to_clean = i;
29 static int enetc_cbd_unused(struct enetc_cbdr *r)
31 return (r->next_to_clean - r->next_to_use - 1 + r->bd_count) %
35 static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd)
37 struct enetc_cbdr *ring = &si->cbd_ring;
38 int timeout = ENETC_CBDR_TIMEOUT;
39 struct enetc_cbd *dest_cbd;
42 if (unlikely(!ring->bd_base))
45 if (unlikely(!enetc_cbd_unused(ring)))
48 i = ring->next_to_use;
49 dest_cbd = ENETC_CBD(*ring, i);
51 /* copy command to the ring */
53 i = (i + 1) % ring->bd_count;
55 ring->next_to_use = i;
56 /* let H/W know BD ring has been updated */
57 enetc_wr_reg(ring->pir, i);
60 if (enetc_rd_reg(ring->cir) == i)
62 udelay(10); /* cannot sleep, rtnl_lock() */
74 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index)
78 memset(&cbd, 0, sizeof(cbd));
81 cbd.status_flags = ENETC_CBD_FLAGS_SF;
82 cbd.index = cpu_to_le16(index);
84 return enetc_send_cmd(si, &cbd);
87 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
88 char *mac_addr, int si_map)
94 memset(&cbd, 0, sizeof(cbd));
96 /* fill up the "set" descriptor */
98 cbd.status_flags = ENETC_CBD_FLAGS_SF;
99 cbd.index = cpu_to_le16(index);
100 cbd.opt[3] = cpu_to_le32(si_map);
102 cbd.opt[0] = cpu_to_le32(BIT(31));
104 upper = *(const u32 *)mac_addr;
105 lower = *(const u16 *)(mac_addr + 4);
106 cbd.addr[0] = cpu_to_le32(upper);
107 cbd.addr[1] = cpu_to_le32(lower);
109 return enetc_send_cmd(si, &cbd);