|
@@ -117,7 +117,7 @@ struct veth_msg {
|
|
struct veth_msg *next;
|
|
struct veth_msg *next;
|
|
struct VethFramesData data;
|
|
struct VethFramesData data;
|
|
int token;
|
|
int token;
|
|
- unsigned long in_use;
|
|
|
|
|
|
+ int in_use;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
struct device *dev;
|
|
struct device *dev;
|
|
};
|
|
};
|
|
@@ -957,6 +957,8 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
|
|
goto drop;
|
|
goto drop;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ msg->in_use = 1;
|
|
|
|
+
|
|
dma_length = skb->len;
|
|
dma_length = skb->len;
|
|
dma_address = dma_map_single(port->dev, skb->data,
|
|
dma_address = dma_map_single(port->dev, skb->data,
|
|
dma_length, DMA_TO_DEVICE);
|
|
dma_length, DMA_TO_DEVICE);
|
|
@@ -971,7 +973,6 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
|
|
msg->data.addr[0] = dma_address;
|
|
msg->data.addr[0] = dma_address;
|
|
msg->data.len[0] = dma_length;
|
|
msg->data.len[0] = dma_length;
|
|
msg->data.eofmask = 1 << VETH_EOF_SHIFT;
|
|
msg->data.eofmask = 1 << VETH_EOF_SHIFT;
|
|
- set_bit(0, &(msg->in_use));
|
|
|
|
rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data);
|
|
rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data);
|
|
|
|
|
|
if (rc != HvLpEvent_Rc_Good)
|
|
if (rc != HvLpEvent_Rc_Good)
|
|
@@ -981,10 +982,8 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
recycle_and_drop:
|
|
recycle_and_drop:
|
|
|
|
+ /* we free the skb below, so tell veth_recycle_msg() not to. */
|
|
msg->skb = NULL;
|
|
msg->skb = NULL;
|
|
- /* need to set in use to make veth_recycle_msg in case this
|
|
|
|
- * was a mapping failure */
|
|
|
|
- set_bit(0, &msg->in_use);
|
|
|
|
veth_recycle_msg(cnx, msg);
|
|
veth_recycle_msg(cnx, msg);
|
|
drop:
|
|
drop:
|
|
port->stats.tx_errors++;
|
|
port->stats.tx_errors++;
|
|
@@ -1066,12 +1065,14 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* You must hold the connection's lock when you call this function. */
|
|
static void veth_recycle_msg(struct veth_lpar_connection *cnx,
|
|
static void veth_recycle_msg(struct veth_lpar_connection *cnx,
|
|
struct veth_msg *msg)
|
|
struct veth_msg *msg)
|
|
{
|
|
{
|
|
u32 dma_address, dma_length;
|
|
u32 dma_address, dma_length;
|
|
|
|
|
|
- if (test_and_clear_bit(0, &msg->in_use)) {
|
|
|
|
|
|
+ if (msg->in_use) {
|
|
|
|
+ msg->in_use = 0;
|
|
dma_address = msg->data.addr[0];
|
|
dma_address = msg->data.addr[0];
|
|
dma_length = msg->data.len[0];
|
|
dma_length = msg->data.len[0];
|
|
|
|
|