Skip to content

Commit e397867

Browse files
isubramadavem330
authored andcommitted
drivers: net: xgene: Fix MSS programming
Current driver programs static value of MSS in hardware register for TSO offload engine to segment the TCP payload regardless the MSS value provided by network stack. This patch fixes this by programming hardware registers with the stack provided MSS value. Since the hardware has the limitation of having only 4 MSS registers, this patch uses reference count of mss values being used. Signed-off-by: Iyappan Subramanian <[email protected]> Signed-off-by: Toan Le <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e12934d commit e397867

File tree

4 files changed

+100
-23
lines changed

4 files changed

+100
-23
lines changed

drivers/net/ethernet/apm/xgene/xgene_enet_hw.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ enum xgene_enet_rm {
237237
#define TCPHDR_LEN 6
238238
#define IPHDR_POS 6
239239
#define IPHDR_LEN 6
240+
#define MSS_POS 20
241+
#define MSS_LEN 2
240242
#define EC_POS 22 /* Enable checksum */
241243
#define EC_LEN 1
242244
#define ET_POS 23 /* Enable TSO */
@@ -253,6 +255,11 @@ enum xgene_enet_rm {
253255

254256
#define LAST_BUFFER (0x7800ULL << BUFDATALEN_POS)
255257

258+
#define TSO_MSS0_POS 0
259+
#define TSO_MSS0_LEN 14
260+
#define TSO_MSS1_POS 16
261+
#define TSO_MSS1_LEN 14
262+
256263
struct xgene_enet_raw_desc {
257264
__le64 m0;
258265
__le64 m1;

drivers/net/ethernet/apm/xgene/xgene_enet_main.c

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,15 @@ static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
137137
static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
138138
struct xgene_enet_raw_desc *raw_desc)
139139
{
140+
struct xgene_enet_pdata *pdata = netdev_priv(cp_ring->ndev);
140141
struct sk_buff *skb;
141142
struct device *dev;
142143
skb_frag_t *frag;
143144
dma_addr_t *frag_dma_addr;
144145
u16 skb_index;
145146
u8 status;
146147
int i, ret = 0;
148+
u8 mss_index;
147149

148150
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
149151
skb = cp_ring->cp_skb[skb_index];
@@ -160,6 +162,13 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
160162
DMA_TO_DEVICE);
161163
}
162164

165+
if (GET_BIT(ET, le64_to_cpu(raw_desc->m3))) {
166+
mss_index = GET_VAL(MSS, le64_to_cpu(raw_desc->m3));
167+
spin_lock(&pdata->mss_lock);
168+
pdata->mss_refcnt[mss_index]--;
169+
spin_unlock(&pdata->mss_lock);
170+
}
171+
163172
/* Checking for error */
164173
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
165174
if (unlikely(status > 2)) {
@@ -178,15 +187,53 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
178187
return ret;
179188
}
180189

181-
static u64 xgene_enet_work_msg(struct sk_buff *skb)
190+
static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
191+
{
192+
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
193+
bool mss_index_found = false;
194+
int mss_index;
195+
int i;
196+
197+
spin_lock(&pdata->mss_lock);
198+
199+
/* Reuse the slot if MSS matches */
200+
for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
201+
if (pdata->mss[i] == mss) {
202+
pdata->mss_refcnt[i]++;
203+
mss_index = i;
204+
mss_index_found = true;
205+
}
206+
}
207+
208+
/* Overwrite the slot with ref_count = 0 */
209+
for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
210+
if (!pdata->mss_refcnt[i]) {
211+
pdata->mss_refcnt[i]++;
212+
pdata->mac_ops->set_mss(pdata, mss, i);
213+
pdata->mss[i] = mss;
214+
mss_index = i;
215+
mss_index_found = true;
216+
}
217+
}
218+
219+
spin_unlock(&pdata->mss_lock);
220+
221+
/* No slots with ref_count = 0 available, return busy */
222+
if (!mss_index_found)
223+
return -EBUSY;
224+
225+
return mss_index;
226+
}
227+
228+
static int xgene_enet_work_msg(struct sk_buff *skb, u64 *hopinfo)
182229
{
183230
struct net_device *ndev = skb->dev;
184231
struct iphdr *iph;
185232
u8 l3hlen = 0, l4hlen = 0;
186233
u8 ethhdr, proto = 0, csum_enable = 0;
187-
u64 hopinfo = 0;
188234
u32 hdr_len, mss = 0;
189235
u32 i, len, nr_frags;
236+
int mss_index;
190237

191238
ethhdr = xgene_enet_hdr_len(skb->data);
192239

@@ -226,23 +273,27 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
226273
if (!mss || ((skb->len - hdr_len) <= mss))
227274
goto out;
228275

229-
hopinfo |= SET_BIT(ET);
276+
mss_index = xgene_enet_setup_mss(ndev, mss);
277+
if (unlikely(mss_index < 0))
278+
return -EBUSY;
279+
280+
*hopinfo |= SET_BIT(ET) | SET_VAL(MSS, mss_index);
230281
}
231282
} else if (iph->protocol == IPPROTO_UDP) {
232283
l4hlen = UDP_HDR_SIZE;
233284
csum_enable = 1;
234285
}
235286
out:
236287
l3hlen = ip_hdrlen(skb) >> 2;
237-
hopinfo |= SET_VAL(TCPHDR, l4hlen) |
238-
SET_VAL(IPHDR, l3hlen) |
239-
SET_VAL(ETHHDR, ethhdr) |
240-
SET_VAL(EC, csum_enable) |
241-
SET_VAL(IS, proto) |
242-
SET_BIT(IC) |
243-
SET_BIT(TYPE_ETH_WORK_MESSAGE);
244-
245-
return hopinfo;
288+
*hopinfo |= SET_VAL(TCPHDR, l4hlen) |
289+
SET_VAL(IPHDR, l3hlen) |
290+
SET_VAL(ETHHDR, ethhdr) |
291+
SET_VAL(EC, csum_enable) |
292+
SET_VAL(IS, proto) |
293+
SET_BIT(IC) |
294+
SET_BIT(TYPE_ETH_WORK_MESSAGE);
295+
296+
return 0;
246297
}
247298

248299
static u16 xgene_enet_encode_len(u16 len)
@@ -282,20 +333,22 @@ static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
282333
dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr;
283334
skb_frag_t *frag;
284335
u16 tail = tx_ring->tail;
285-
u64 hopinfo;
336+
u64 hopinfo = 0;
286337
u32 len, hw_len;
287338
u8 ll = 0, nv = 0, idx = 0;
288339
bool split = false;
289340
u32 size, offset, ell_bytes = 0;
290341
u32 i, fidx, nr_frags, count = 1;
342+
int ret;
291343

292344
raw_desc = &tx_ring->raw_desc[tail];
293345
tail = (tail + 1) & (tx_ring->slots - 1);
294346
memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
295347

296-
hopinfo = xgene_enet_work_msg(skb);
297-
if (!hopinfo)
298-
return -EINVAL;
348+
ret = xgene_enet_work_msg(skb, &hopinfo);
349+
if (ret)
350+
return ret;
351+
299352
raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
300353
hopinfo);
301354

@@ -435,6 +488,9 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
435488
return NETDEV_TX_OK;
436489

437490
count = xgene_enet_setup_tx_desc(tx_ring, skb);
491+
if (count == -EBUSY)
492+
return NETDEV_TX_BUSY;
493+
438494
if (count <= 0) {
439495
dev_kfree_skb_any(skb);
440496
return NETDEV_TX_OK;
@@ -1669,7 +1725,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
16691725

16701726
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
16711727
ndev->features |= NETIF_F_TSO;
1672-
pdata->mss = XGENE_ENET_MSS;
1728+
spin_lock_init(&pdata->mss_lock);
16731729
}
16741730
ndev->hw_features = ndev->features;
16751731

drivers/net/ethernet/apm/xgene/xgene_enet_main.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
#define NUM_PKT_BUF 64
4848
#define NUM_BUFPOOL 32
4949
#define MAX_EXP_BUFFS 256
50-
#define XGENE_ENET_MSS 1448
50+
#define NUM_MSS_REG 4
5151
#define XGENE_MIN_ENET_FRAME_SIZE 60
5252

5353
#define XGENE_MAX_ENET_IRQ 16
@@ -143,7 +143,7 @@ struct xgene_mac_ops {
143143
void (*rx_disable)(struct xgene_enet_pdata *pdata);
144144
void (*set_speed)(struct xgene_enet_pdata *pdata);
145145
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
146-
void (*set_mss)(struct xgene_enet_pdata *pdata);
146+
void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
147147
void (*link_state)(struct work_struct *work);
148148
};
149149

@@ -212,7 +212,9 @@ struct xgene_enet_pdata {
212212
u8 eth_bufnum;
213213
u8 bp_bufnum;
214214
u16 ring_num;
215-
u32 mss;
215+
u32 mss[NUM_MSS_REG];
216+
u32 mss_refcnt[NUM_MSS_REG];
217+
spinlock_t mss_lock; /* mss lock */
216218
u8 tx_delay;
217219
u8 rx_delay;
218220
bool mdio_driver;

drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,22 @@ static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
232232
xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
233233
}
234234

235-
static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata)
235+
static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata,
236+
u16 mss, u8 index)
236237
{
237-
xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR, pdata->mss);
238+
u8 offset;
239+
u32 data;
240+
241+
offset = (index < 2) ? 0 : 4;
242+
xgene_enet_rd_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, &data);
243+
244+
if (!(index & 0x1))
245+
data = SET_VAL(TSO_MSS1, data >> TSO_MSS1_POS) |
246+
SET_VAL(TSO_MSS0, mss);
247+
else
248+
data = SET_VAL(TSO_MSS1, mss) | SET_VAL(TSO_MSS0, data);
249+
250+
xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, data);
238251
}
239252

240253
static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
@@ -258,7 +271,6 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
258271
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
259272

260273
xgene_xgmac_set_mac_addr(pdata);
261-
xgene_xgmac_set_mss(pdata);
262274

263275
xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
264276
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;

0 commit comments

Comments
 (0)