Commit 115924b6 authored by Shreyas Bhatewara's avatar Shreyas Bhatewara Committed by David S. Miller

net: Getting rid of the x86 dependency to built vmxnet3

This patch removes config dependency on x86 to build vmxnet3 driver. Thus
the driver can be built on big endian architectures now. Although vmxnet3
is not supported on VMs other than x86 architecture, all this code goes in
to ensure correctness. If the code is not dependent on x86, it should not
assume little endian architecture in any of its operations.
Signed-off-by: default avatarShreyas Bhatewara <sbhatewara@vmware.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 649300b9
...@@ -3235,7 +3235,7 @@ config VIRTIO_NET ...@@ -3235,7 +3235,7 @@ config VIRTIO_NET
config VMXNET3 config VMXNET3
tristate "VMware VMXNET3 ethernet driver" tristate "VMware VMXNET3 ethernet driver"
depends on PCI && X86 && INET depends on PCI && INET
help help
This driver supports VMware's vmxnet3 virtual ethernet NIC. This driver supports VMware's vmxnet3 virtual ethernet NIC.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
......
...@@ -90,16 +90,52 @@ enum { ...@@ -90,16 +90,52 @@ enum {
VMXNET3_CMD_GET_CONF_INTR VMXNET3_CMD_GET_CONF_INTR
}; };
/*
* Little Endian layout of bitfields -
* Byte 0 : 7.....len.....0
* Byte 1 : rsvd gen 13.len.8
* Byte 2 : 5.msscof.0 ext1 dtype
* Byte 3 : 13...msscof...6
*
* Big Endian layout of bitfields -
* Byte 0: 13...msscof...6
* Byte 1 : 5.msscof.0 ext1 dtype
* Byte 2 : rsvd gen 13.len.8
* Byte 3 : 7.....len.....0
*
* Thus, le32_to_cpu on the dword will allow the big endian driver to read
* the bit fields correctly. And cpu_to_le32 will convert bitfields
* bit fields written by big endian driver to format required by device.
*/
struct Vmxnet3_TxDesc { struct Vmxnet3_TxDesc {
u64 addr; __le64 addr;
#ifdef __BIG_ENDIAN_BITFIELD
u32 msscof:14; /* MSS, checksum offset, flags */
u32 ext1:1;
u32 dtype:1; /* descriptor type */
u32 rsvd:1;
u32 gen:1; /* generation bit */
u32 len:14;
#else
u32 len:14; u32 len:14;
u32 gen:1; /* generation bit */ u32 gen:1; /* generation bit */
u32 rsvd:1; u32 rsvd:1;
u32 dtype:1; /* descriptor type */ u32 dtype:1; /* descriptor type */
u32 ext1:1; u32 ext1:1;
u32 msscof:14; /* MSS, checksum offset, flags */ u32 msscof:14; /* MSS, checksum offset, flags */
#endif /* __BIG_ENDIAN_BITFIELD */
#ifdef __BIG_ENDIAN_BITFIELD
u32 tci:16; /* Tag to Insert */
u32 ti:1; /* VLAN Tag Insertion */
u32 ext2:1;
u32 cq:1; /* completion request */
u32 eop:1; /* End Of Packet */
u32 om:2; /* offload mode */
u32 hlen:10; /* header len */
#else
u32 hlen:10; /* header len */ u32 hlen:10; /* header len */
u32 om:2; /* offload mode */ u32 om:2; /* offload mode */
u32 eop:1; /* End Of Packet */ u32 eop:1; /* End Of Packet */
...@@ -107,6 +143,7 @@ struct Vmxnet3_TxDesc { ...@@ -107,6 +143,7 @@ struct Vmxnet3_TxDesc {
u32 ext2:1; u32 ext2:1;
u32 ti:1; /* VLAN Tag Insertion */ u32 ti:1; /* VLAN Tag Insertion */
u32 tci:16; /* Tag to Insert */ u32 tci:16; /* Tag to Insert */
#endif /* __BIG_ENDIAN_BITFIELD */
}; };
/* TxDesc.OM values */ /* TxDesc.OM values */
...@@ -118,6 +155,8 @@ struct Vmxnet3_TxDesc { ...@@ -118,6 +155,8 @@ struct Vmxnet3_TxDesc {
#define VMXNET3_TXD_EOP_SHIFT 12 #define VMXNET3_TXD_EOP_SHIFT 12
#define VMXNET3_TXD_CQ_SHIFT 13 #define VMXNET3_TXD_CQ_SHIFT 13
#define VMXNET3_TXD_GEN_SHIFT 14 #define VMXNET3_TXD_GEN_SHIFT 14
#define VMXNET3_TXD_EOP_DWORD_SHIFT 3
#define VMXNET3_TXD_GEN_DWORD_SHIFT 2
#define VMXNET3_TXD_CQ (1 << VMXNET3_TXD_CQ_SHIFT) #define VMXNET3_TXD_CQ (1 << VMXNET3_TXD_CQ_SHIFT)
#define VMXNET3_TXD_EOP (1 << VMXNET3_TXD_EOP_SHIFT) #define VMXNET3_TXD_EOP (1 << VMXNET3_TXD_EOP_SHIFT)
...@@ -130,29 +169,40 @@ struct Vmxnet3_TxDataDesc { ...@@ -130,29 +169,40 @@ struct Vmxnet3_TxDataDesc {
u8 data[VMXNET3_HDR_COPY_SIZE]; u8 data[VMXNET3_HDR_COPY_SIZE];
}; };
#define VMXNET3_TCD_GEN_SHIFT 31
#define VMXNET3_TCD_GEN_SIZE 1
#define VMXNET3_TCD_TXIDX_SHIFT 0
#define VMXNET3_TCD_TXIDX_SIZE 12
#define VMXNET3_TCD_GEN_DWORD_SHIFT 3
struct Vmxnet3_TxCompDesc { struct Vmxnet3_TxCompDesc {
u32 txdIdx:12; /* Index of the EOP TxDesc */ u32 txdIdx:12; /* Index of the EOP TxDesc */
u32 ext1:20; u32 ext1:20;
u32 ext2; __le32 ext2;
u32 ext3; __le32 ext3;
u32 rsvd:24; u32 rsvd:24;
u32 type:7; /* completion type */ u32 type:7; /* completion type */
u32 gen:1; /* generation bit */ u32 gen:1; /* generation bit */
}; };
struct Vmxnet3_RxDesc { struct Vmxnet3_RxDesc {
u64 addr; __le64 addr;
#ifdef __BIG_ENDIAN_BITFIELD
u32 gen:1; /* Generation bit */
u32 rsvd:15;
u32 dtype:1; /* Descriptor type */
u32 btype:1; /* Buffer Type */
u32 len:14;
#else
u32 len:14; u32 len:14;
u32 btype:1; /* Buffer Type */ u32 btype:1; /* Buffer Type */
u32 dtype:1; /* Descriptor type */ u32 dtype:1; /* Descriptor type */
u32 rsvd:15; u32 rsvd:15;
u32 gen:1; /* Generation bit */ u32 gen:1; /* Generation bit */
#endif
u32 ext1; u32 ext1;
}; };
...@@ -164,8 +214,17 @@ struct Vmxnet3_RxDesc { ...@@ -164,8 +214,17 @@ struct Vmxnet3_RxDesc {
#define VMXNET3_RXD_BTYPE_SHIFT 14 #define VMXNET3_RXD_BTYPE_SHIFT 14
#define VMXNET3_RXD_GEN_SHIFT 31 #define VMXNET3_RXD_GEN_SHIFT 31
struct Vmxnet3_RxCompDesc { struct Vmxnet3_RxCompDesc {
#ifdef __BIG_ENDIAN_BITFIELD
u32 ext2:1;
u32 cnc:1; /* Checksum Not Calculated */
u32 rssType:4; /* RSS hash type used */
u32 rqID:10; /* rx queue/ring ID */
u32 sop:1; /* Start of Packet */
u32 eop:1; /* End of Packet */
u32 ext1:2;
u32 rxdIdx:12; /* Index of the RxDesc */
#else
u32 rxdIdx:12; /* Index of the RxDesc */ u32 rxdIdx:12; /* Index of the RxDesc */
u32 ext1:2; u32 ext1:2;
u32 eop:1; /* End of Packet */ u32 eop:1; /* End of Packet */
...@@ -174,14 +233,36 @@ struct Vmxnet3_RxCompDesc { ...@@ -174,14 +233,36 @@ struct Vmxnet3_RxCompDesc {
u32 rssType:4; /* RSS hash type used */ u32 rssType:4; /* RSS hash type used */
u32 cnc:1; /* Checksum Not Calculated */ u32 cnc:1; /* Checksum Not Calculated */
u32 ext2:1; u32 ext2:1;
#endif /* __BIG_ENDIAN_BITFIELD */
u32 rssHash; /* RSS hash value */ __le32 rssHash; /* RSS hash value */
#ifdef __BIG_ENDIAN_BITFIELD
u32 tci:16; /* Tag stripped */
u32 ts:1; /* Tag is stripped */
u32 err:1; /* Error */
u32 len:14; /* data length */
#else
u32 len:14; /* data length */ u32 len:14; /* data length */
u32 err:1; /* Error */ u32 err:1; /* Error */
u32 ts:1; /* Tag is stripped */ u32 ts:1; /* Tag is stripped */
u32 tci:16; /* Tag stripped */ u32 tci:16; /* Tag stripped */
#endif /* __BIG_ENDIAN_BITFIELD */
#ifdef __BIG_ENDIAN_BITFIELD
u32 gen:1; /* generation bit */
u32 type:7; /* completion type */
u32 fcs:1; /* Frame CRC correct */
u32 frg:1; /* IP Fragment */
u32 v4:1; /* IPv4 */
u32 v6:1; /* IPv6 */
u32 ipc:1; /* IP Checksum Correct */
u32 tcp:1; /* TCP packet */
u32 udp:1; /* UDP packet */
u32 tuc:1; /* TCP/UDP Checksum Correct */
u32 csum:16;
#else
u32 csum:16; u32 csum:16;
u32 tuc:1; /* TCP/UDP Checksum Correct */ u32 tuc:1; /* TCP/UDP Checksum Correct */
u32 udp:1; /* UDP packet */ u32 udp:1; /* UDP packet */
...@@ -193,6 +274,7 @@ struct Vmxnet3_RxCompDesc { ...@@ -193,6 +274,7 @@ struct Vmxnet3_RxCompDesc {
u32 fcs:1; /* Frame CRC correct */ u32 fcs:1; /* Frame CRC correct */
u32 type:7; /* completion type */ u32 type:7; /* completion type */
u32 gen:1; /* generation bit */ u32 gen:1; /* generation bit */
#endif /* __BIG_ENDIAN_BITFIELD */
}; };
/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */ /* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
...@@ -206,6 +288,8 @@ struct Vmxnet3_RxCompDesc { ...@@ -206,6 +288,8 @@ struct Vmxnet3_RxCompDesc {
/* csum OK for TCP/UDP pkts over IP */ /* csum OK for TCP/UDP pkts over IP */
#define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | \ #define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | \
1 << VMXNET3_RCD_IPC_SHIFT) 1 << VMXNET3_RCD_IPC_SHIFT)
#define VMXNET3_TXD_GEN_SIZE 1
#define VMXNET3_TXD_EOP_SIZE 1
/* value of RxCompDesc.rssType */ /* value of RxCompDesc.rssType */
enum { enum {
...@@ -219,9 +303,9 @@ enum { ...@@ -219,9 +303,9 @@ enum {
/* a union for accessing all cmd/completion descriptors */ /* a union for accessing all cmd/completion descriptors */
union Vmxnet3_GenericDesc { union Vmxnet3_GenericDesc {
u64 qword[2]; __le64 qword[2];
u32 dword[4]; __le32 dword[4];
u16 word[8]; __le16 word[8];
struct Vmxnet3_TxDesc txd; struct Vmxnet3_TxDesc txd;
struct Vmxnet3_RxDesc rxd; struct Vmxnet3_RxDesc rxd;
struct Vmxnet3_TxCompDesc tcd; struct Vmxnet3_TxCompDesc tcd;
...@@ -287,18 +371,24 @@ enum { ...@@ -287,18 +371,24 @@ enum {
struct Vmxnet3_GOSInfo { struct Vmxnet3_GOSInfo {
#ifdef __BIG_ENDIAN_BITFIELD
u32 gosMisc:10; /* other info about gos */
u32 gosVer:16; /* gos version */
u32 gosType:4; /* which guest */
u32 gosBits:2; /* 32-bit or 64-bit? */
#else
u32 gosBits:2; /* 32-bit or 64-bit? */ u32 gosBits:2; /* 32-bit or 64-bit? */
u32 gosType:4; /* which guest */ u32 gosType:4; /* which guest */
u32 gosVer:16; /* gos version */ u32 gosVer:16; /* gos version */
u32 gosMisc:10; /* other info about gos */ u32 gosMisc:10; /* other info about gos */
#endif /* __BIG_ENDIAN_BITFIELD */
}; };
struct Vmxnet3_DriverInfo { struct Vmxnet3_DriverInfo {
u32 version; __le32 version;
struct Vmxnet3_GOSInfo gos; struct Vmxnet3_GOSInfo gos;
u32 vmxnet3RevSpt; __le32 vmxnet3RevSpt;
u32 uptVerSpt; __le32 uptVerSpt;
}; };
...@@ -315,42 +405,42 @@ struct Vmxnet3_DriverInfo { ...@@ -315,42 +405,42 @@ struct Vmxnet3_DriverInfo {
struct Vmxnet3_MiscConf { struct Vmxnet3_MiscConf {
struct Vmxnet3_DriverInfo driverInfo; struct Vmxnet3_DriverInfo driverInfo;
u64 uptFeatures; __le64 uptFeatures;
u64 ddPA; /* driver data PA */ __le64 ddPA; /* driver data PA */
u64 queueDescPA; /* queue descriptor table PA */ __le64 queueDescPA; /* queue descriptor table PA */
u32 ddLen; /* driver data len */ __le32 ddLen; /* driver data len */
u32 queueDescLen; /* queue desc. table len in bytes */ __le32 queueDescLen; /* queue desc. table len in bytes */
u32 mtu; __le32 mtu;
u16 maxNumRxSG; __le16 maxNumRxSG;
u8 numTxQueues; u8 numTxQueues;
u8 numRxQueues; u8 numRxQueues;
u32 reserved[4]; __le32 reserved[4];
}; };
struct Vmxnet3_TxQueueConf { struct Vmxnet3_TxQueueConf {
u64 txRingBasePA; __le64 txRingBasePA;
u64 dataRingBasePA; __le64 dataRingBasePA;
u64 compRingBasePA; __le64 compRingBasePA;
u64 ddPA; /* driver data */ __le64 ddPA; /* driver data */
u64 reserved; __le64 reserved;
u32 txRingSize; /* # of tx desc */ __le32 txRingSize; /* # of tx desc */
u32 dataRingSize; /* # of data desc */ __le32 dataRingSize; /* # of data desc */
u32 compRingSize; /* # of comp desc */ __le32 compRingSize; /* # of comp desc */
u32 ddLen; /* size of driver data */ __le32 ddLen; /* size of driver data */
u8 intrIdx; u8 intrIdx;
u8 _pad[7]; u8 _pad[7];
}; };
struct Vmxnet3_RxQueueConf { struct Vmxnet3_RxQueueConf {
u64 rxRingBasePA[2]; __le64 rxRingBasePA[2];
u64 compRingBasePA; __le64 compRingBasePA;
u64 ddPA; /* driver data */ __le64 ddPA; /* driver data */
u64 reserved; __le64 reserved;
u32 rxRingSize[2]; /* # of rx desc */ __le32 rxRingSize[2]; /* # of rx desc */
u32 compRingSize; /* # of rx comp desc */ __le32 compRingSize; /* # of rx comp desc */
u32 ddLen; /* size of driver data */ __le32 ddLen; /* size of driver data */
u8 intrIdx; u8 intrIdx;
u8 _pad[7]; u8 _pad[7];
}; };
...@@ -381,7 +471,7 @@ struct Vmxnet3_IntrConf { ...@@ -381,7 +471,7 @@ struct Vmxnet3_IntrConf {
u8 eventIntrIdx; u8 eventIntrIdx;
u8 modLevels[VMXNET3_MAX_INTRS]; /* moderation level for u8 modLevels[VMXNET3_MAX_INTRS]; /* moderation level for
* each intr */ * each intr */
u32 reserved[3]; __le32 reserved[3];
}; };
/* one bit per VLAN ID, the size is in the units of u32 */ /* one bit per VLAN ID, the size is in the units of u32 */
...@@ -391,21 +481,21 @@ struct Vmxnet3_IntrConf { ...@@ -391,21 +481,21 @@ struct Vmxnet3_IntrConf {
struct Vmxnet3_QueueStatus { struct Vmxnet3_QueueStatus {
bool stopped; bool stopped;
u8 _pad[3]; u8 _pad[3];
u32 error; __le32 error;
}; };
struct Vmxnet3_TxQueueCtrl { struct Vmxnet3_TxQueueCtrl {
u32 txNumDeferred; __le32 txNumDeferred;
u32 txThreshold; __le32 txThreshold;
u64 reserved; __le64 reserved;
}; };
struct Vmxnet3_RxQueueCtrl { struct Vmxnet3_RxQueueCtrl {
bool updateRxProd; bool updateRxProd;
u8 _pad[7]; u8 _pad[7];
u64 reserved; __le64 reserved;
}; };
enum { enum {
...@@ -417,11 +507,11 @@ enum { ...@@ -417,11 +507,11 @@ enum {
}; };
struct Vmxnet3_RxFilterConf { struct Vmxnet3_RxFilterConf {
u32 rxMode; /* VMXNET3_RXM_xxx */ __le32 rxMode; /* VMXNET3_RXM_xxx */
u16 mfTableLen; /* size of the multicast filter table */ __le16 mfTableLen; /* size of the multicast filter table */
u16 _pad1; __le16 _pad1;
u64 mfTablePA; /* PA of the multicast filters table */ __le64 mfTablePA; /* PA of the multicast filters table */
u32 vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */ __le32 vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */
}; };
...@@ -444,7 +534,7 @@ struct Vmxnet3_PM_PktFilter { ...@@ -444,7 +534,7 @@ struct Vmxnet3_PM_PktFilter {
struct Vmxnet3_PMConf { struct Vmxnet3_PMConf {
u16 wakeUpEvents; /* VMXNET3_PM_WAKEUP_xxx */ __le16 wakeUpEvents; /* VMXNET3_PM_WAKEUP_xxx */
u8 numFilters; u8 numFilters;
u8 pad[5]; u8 pad[5];
struct Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS]; struct Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS];
...@@ -452,9 +542,9 @@ struct Vmxnet3_PMConf { ...@@ -452,9 +542,9 @@ struct Vmxnet3_PMConf {
struct Vmxnet3_VariableLenConfDesc { struct Vmxnet3_VariableLenConfDesc {
u32 confVer; __le32 confVer;
u32 confLen; __le32 confLen;
u64 confPA; __le64 confPA;
}; };
...@@ -491,12 +581,12 @@ struct Vmxnet3_DSDevRead { ...@@ -491,12 +581,12 @@ struct Vmxnet3_DSDevRead {
/* All structures in DriverShared are padded to multiples of 8 bytes */ /* All structures in DriverShared are padded to multiples of 8 bytes */
struct Vmxnet3_DriverShared { struct Vmxnet3_DriverShared {
u32 magic; __le32 magic;
/* make devRead start at 64bit boundaries */ /* make devRead start at 64bit boundaries */
u32 pad; __le32 pad;
struct Vmxnet3_DSDevRead devRead; struct Vmxnet3_DSDevRead devRead;
u32 ecr; __le32 ecr;
u32 reserved[5]; __le32 reserved[5];
}; };
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
char vmxnet3_driver_name[] = "vmxnet3"; char vmxnet3_driver_name[] = "vmxnet3";
#define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver" #define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver"
/* /*
* PCI Device ID Table * PCI Device ID Table
* Last entry must be all 0s * Last entry must be all 0s
...@@ -151,11 +150,10 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter) ...@@ -151,11 +150,10 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter)
} }
} }
static void static void
vmxnet3_process_events(struct vmxnet3_adapter *adapter) vmxnet3_process_events(struct vmxnet3_adapter *adapter)
{ {
u32 events = adapter->shared->ecr; u32 events = le32_to_cpu(adapter->shared->ecr);
if (!events) if (!events)
return; return;
...@@ -173,7 +171,7 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter) ...@@ -173,7 +171,7 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter)
if (adapter->tqd_start->status.stopped) { if (adapter->tqd_start->status.stopped) {
printk(KERN_ERR "%s: tq error 0x%x\n", printk(KERN_ERR "%s: tq error 0x%x\n",
adapter->netdev->name, adapter->netdev->name,
adapter->tqd_start->status.error); le32_to_cpu(adapter->tqd_start->status.error));
} }
if (adapter->rqd_start->status.stopped) { if (adapter->rqd_start->status.stopped) {
printk(KERN_ERR "%s: rq error 0x%x\n", printk(KERN_ERR "%s: rq error 0x%x\n",
...@@ -185,6 +183,106 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter) ...@@ -185,6 +183,106 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter)
} }
} }
#ifdef __BIG_ENDIAN_BITFIELD
/*
* The device expects the bitfields in shared structures to be written in
* little endian. When CPU is big endian, the following routines are used to
* correctly read and write into ABI.
* The general technique used here is : double word bitfields are defined in
* opposite order for big endian architecture. Then before reading them in
* driver the complete double word is translated using le32_to_cpu. Similarly
* After the driver writes into bitfields, cpu_to_le32 is used to translate the
* double words into required format.
* In order to avoid touching bits in shared structure more than once, temporary
* descriptors are used. These are passed as srcDesc to following functions.
*/
static void vmxnet3_RxDescToCPU(const struct Vmxnet3_RxDesc *srcDesc,
struct Vmxnet3_RxDesc *dstDesc)
{
u32 *src = (u32 *)srcDesc + 2;
u32 *dst = (u32 *)dstDesc + 2;
dstDesc->addr = le64_to_cpu(srcDesc->addr);
*dst = le32_to_cpu(*src);
dstDesc->ext1 = le32_to_cpu(srcDesc->ext1);
}
static void vmxnet3_TxDescToLe(const struct Vmxnet3_TxDesc *srcDesc,
struct Vmxnet3_TxDesc *dstDesc)
{
int i;
u32 *src = (u32 *)(srcDesc + 1);
u32 *dst = (u32 *)(dstDesc + 1);
/* Working backwards so that the gen bit is set at the end. */
for (i = 2; i > 0; i--) {
src--;
dst--;
*dst = cpu_to_le32(*src);
}
}
static void vmxnet3_RxCompToCPU(const struct Vmxnet3_RxCompDesc *srcDesc,
struct Vmxnet3_RxCompDesc *dstDesc)
{
int i = 0;
u32 *src = (u32 *)srcDesc;
u32 *dst = (u32 *)dstDesc;
for (i = 0; i < sizeof(struct Vmxnet3_RxCompDesc) / sizeof(u32); i++) {
*dst = le32_to_cpu(*src);
src++;
dst++;
}
}
/* Used to read bitfield values from double words. */
static u32 get_bitfield32(const __le32 *bitfield, u32 pos, u32 size)
{
u32 temp = le32_to_cpu(*bitfield);
u32 mask = ((1 << size) - 1) << pos;
temp &= mask;
temp >>= pos;
return temp;
}
#endif /* __BIG_ENDIAN_BITFIELD */
#ifdef __BIG_ENDIAN_BITFIELD
# define VMXNET3_TXDESC_GET_GEN(txdesc) get_bitfield32(((const __le32 *) \
txdesc) + VMXNET3_TXD_GEN_DWORD_SHIFT, \
VMXNET3_TXD_GEN_SHIFT, VMXNET3_TXD_GEN_SIZE)
# define VMXNET3_TXDESC_GET_EOP(txdesc) get_bitfield32(((const __le32 *) \
txdesc) + VMXNET3_TXD_EOP_DWORD_SHIFT, \
VMXNET3_TXD_EOP_SHIFT, VMXNET3_TXD_EOP_SIZE)
# define VMXNET3_TCD_GET_GEN(tcd) get_bitfield32(((const __le32 *)tcd) + \
VMXNET3_TCD_GEN_DWORD_SHIFT, VMXNET3_TCD_GEN_SHIFT, \
VMXNET3_TCD_GEN_SIZE)
# define VMXNET3_TCD_GET_TXIDX(tcd) get_bitfield32((const __le32 *)tcd, \
VMXNET3_TCD_TXIDX_SHIFT, VMXNET3_TCD_TXIDX_SIZE)
# define vmxnet3_getRxComp(dstrcd, rcd, tmp) do { \
(dstrcd) = (tmp); \
vmxnet3_RxCompToCPU((rcd), (tmp)); \
} while (0)
# define vmxnet3_getRxDesc(dstrxd, rxd, tmp) do { \
(dstrxd) = (tmp); \
vmxnet3_RxDescToCPU((rxd), (tmp)); \
} while (0)
#else
# define VMXNET3_TXDESC_GET_GEN(txdesc) ((txdesc)->gen)
# define VMXNET3_TXDESC_GET_EOP(txdesc) ((txdesc)->eop)
# define VMXNET3_TCD_GET_GEN(tcd) ((tcd)->gen)
# define VMXNET3_TCD_GET_TXIDX(tcd) ((tcd)->txdIdx)
# define vmxnet3_getRxComp(dstrcd, rcd, tmp) (dstrcd) = (rcd)
# define vmxnet3_getRxDesc(dstrxd, rxd, tmp) (dstrxd) = (rxd)
#endif /* __BIG_ENDIAN_BITFIELD */
static void static void
vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi, vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi,
...@@ -212,7 +310,7 @@ vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq, ...@@ -212,7 +310,7 @@ vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq,
/* no out of order completion */ /* no out of order completion */
BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp); BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp);
BUG_ON(tq->tx_ring.base[eop_idx].txd.eop != 1); BUG_ON(VMXNET3_TXDESC_GET_EOP(&(tq->tx_ring.base[eop_idx].txd)) != 1);
skb = tq->buf_info[eop_idx].skb; skb = tq->buf_info[eop_idx].skb;
BUG_ON(skb == NULL); BUG_ON(skb == NULL);
...@@ -246,9 +344,10 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq, ...@@ -246,9 +344,10 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
union Vmxnet3_GenericDesc *gdesc; union Vmxnet3_GenericDesc *gdesc;
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
while (gdesc->tcd.gen == tq->comp_ring.gen) { while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) {
completed += vmxnet3_unmap_pkt(gdesc->tcd.txdIdx, tq, completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX(
adapter->pdev, adapter); &gdesc->tcd), tq, adapter->pdev,
adapter);
vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring); vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring);
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
...@@ -472,9 +571,9 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, ...@@ -472,9 +571,9 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
} }
BUG_ON(rbi->dma_addr == 0); BUG_ON(rbi->dma_addr == 0);
gd->rxd.addr = rbi->dma_addr; gd->rxd.addr = cpu_to_le64(rbi->dma_addr);
gd->dword[2] = (ring->gen << VMXNET3_RXD_GEN_SHIFT) | val | gd->dword[2] = cpu_to_le32((ring->gen << VMXNET3_RXD_GEN_SHIFT)
rbi->len; | val | rbi->len);
num_allocated++; num_allocated++;
vmxnet3_cmd_ring_adv_next2fill(ring); vmxnet3_cmd_ring_adv_next2fill(ring);
...@@ -531,10 +630,10 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, ...@@ -531,10 +630,10 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
/* no need to map the buffer if headers are copied */ /* no need to map the buffer if headers are copied */
if (ctx->copy_size) { if (ctx->copy_size) {
ctx->sop_txd->txd.addr = tq->data_ring.basePA + ctx->sop_txd->txd.addr = cpu_to_le64(tq->data_ring.basePA +
tq->tx_ring.next2fill * tq->tx_ring.next2fill *
sizeof(struct Vmxnet3_TxDataDesc); sizeof(struct Vmxnet3_TxDataDesc));
ctx->sop_txd->dword[2] = dw2 | ctx->copy_size; ctx->sop_txd->dword[2] = cpu_to_le32(dw2 | ctx->copy_size);
ctx->sop_txd->dword[3] = 0; ctx->sop_txd->dword[3] = 0;
tbi = tq->buf_info + tq->tx_ring.next2fill; tbi = tq->buf_info + tq->tx_ring.next2fill;
...@@ -542,7 +641,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, ...@@ -542,7 +641,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
dev_dbg(&adapter->netdev->dev, dev_dbg(&adapter->netdev->dev,
"txd[%u]: 0x%Lx 0x%x 0x%x\n", "txd[%u]: 0x%Lx 0x%x 0x%x\n",
tq->tx_ring.next2fill, ctx->sop_txd->txd.addr, tq->tx_ring.next2fill,
le64_to_cpu(ctx->sop_txd->txd.addr),
ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]); ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
...@@ -570,14 +670,14 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, ...@@ -570,14 +670,14 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
gdesc->txd.addr = tbi->dma_addr; gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
gdesc->dword[2] = dw2 | buf_size; gdesc->dword[2] = cpu_to_le32(dw2 | buf_size);
gdesc->dword[3] = 0; gdesc->dword[3] = 0;
dev_dbg(&adapter->netdev->dev, dev_dbg(&adapter->netdev->dev,
"txd[%u]: 0x%Lx 0x%x 0x%x\n", "txd[%u]: 0x%Lx 0x%x 0x%x\n",
tq->tx_ring.next2fill, gdesc->txd.addr, tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
gdesc->dword[2], gdesc->dword[3]); le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
...@@ -599,14 +699,14 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, ...@@ -599,14 +699,14 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
gdesc->txd.addr = tbi->dma_addr; gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
gdesc->dword[2] = dw2 | frag->size; gdesc->dword[2] = cpu_to_le32(dw2 | frag->size);
gdesc->dword[3] = 0; gdesc->dword[3] = 0;
dev_dbg(&adapter->netdev->dev, dev_dbg(&adapter->netdev->dev,
"txd[%u]: 0x%llu %u %u\n", "txd[%u]: 0x%llu %u %u\n",
tq->tx_ring.next2fill, gdesc->txd.addr, tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
gdesc->dword[2], gdesc->dword[3]); le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
} }
...@@ -751,6 +851,10 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ...@@ -751,6 +851,10 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
unsigned long flags; unsigned long flags;
struct vmxnet3_tx_ctx ctx; struct vmxnet3_tx_ctx ctx;
union Vmxnet3_GenericDesc *gdesc; union Vmxnet3_GenericDesc *gdesc;
#ifdef __BIG_ENDIAN_BITFIELD
/* Use temporary descriptor to avoid touching bits multiple times */
union Vmxnet3_GenericDesc tempTxDesc;
#endif
/* conservatively estimate # of descriptors to use */ /* conservatively estimate # of descriptors to use */
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
...@@ -827,16 +931,22 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ...@@ -827,16 +931,22 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter); vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter);
/* setup the EOP desc */ /* setup the EOP desc */
ctx.eop_txd->dword[3] = VMXNET3_TXD_CQ | VMXNET3_TXD_EOP; ctx.eop_txd->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP);
/* setup the SOP desc */ /* setup the SOP desc */
#ifdef __BIG_ENDIAN_BITFIELD
gdesc = &tempTxDesc;
gdesc->dword[2] = ctx.sop_txd->dword[2];
gdesc->dword[3] = ctx.sop_txd->dword[3];
#else
gdesc = ctx.sop_txd; gdesc = ctx.sop_txd;
#endif
if (ctx.mss) { if (ctx.mss) {
gdesc->txd.hlen = ctx.eth_ip_hdr_size + ctx.l4_hdr_size; gdesc->txd.hlen = ctx.eth_ip_hdr_size + ctx.l4_hdr_size;
gdesc->txd.om = VMXNET3_OM_TSO; gdesc->txd.om = VMXNET3_OM_TSO;
gdesc->txd.msscof = ctx.mss; gdesc->txd.msscof = ctx.mss;
tq->shared->txNumDeferred += (skb->len - gdesc->txd.hlen + le32_add_cpu(&tq->shared->txNumDeferred, (skb->len -
ctx.mss - 1) / ctx.mss; gdesc->txd.hlen + ctx.mss - 1) / ctx.mss);
} else { } else {
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
gdesc->txd.hlen = ctx.eth_ip_hdr_size; gdesc->txd.hlen = ctx.eth_ip_hdr_size;
...@@ -847,7 +957,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ...@@ -847,7 +957,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
gdesc->txd.om = 0; gdesc->txd.om = 0;
gdesc->txd.msscof = 0; gdesc->txd.msscof = 0;
} }
tq->shared->txNumDeferred++; le32_add_cpu(&tq->shared->txNumDeferred, 1);
} }
if (vlan_tx_tag_present(skb)) { if (vlan_tx_tag_present(skb)) {
...@@ -855,19 +965,27 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, ...@@ -855,19 +965,27 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
gdesc->txd.tci = vlan_tx_tag_get(skb); gdesc->txd.tci = vlan_tx_tag_get(skb);
} }
wmb(); /* finally flips the GEN bit of the SOP desc. */
gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
/* finally flips the GEN bit of the SOP desc */ VMXNET3_TXD_GEN);
gdesc->dword[2] ^= VMXNET3_TXD_GEN; #ifdef __BIG_ENDIAN_BITFIELD
/* Finished updating in bitfields of Tx Desc, so write them in original
* place.
*/
vmxnet3_TxDescToLe((struct Vmxnet3_TxDesc *)gdesc,
(struct Vmxnet3_TxDesc *)ctx.sop_txd);
gdesc = ctx.sop_txd;
#endif
dev_dbg(&adapter->netdev->dev, dev_dbg(&adapter->netdev->dev,
"txd[%u]: SOP 0x%Lx 0x%x 0x%x\n", "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n",
(u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd - (u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd -
tq->tx_ring.base), gdesc->txd.addr, gdesc->dword[2], tq->tx_ring.base), le64_to_cpu(gdesc->txd.addr),
gdesc->dword[3]); le32_to_cpu(gdesc->dword[2]), le32_to_cpu(gdesc->dword[3]));
spin_unlock_irqrestore(&tq->tx_lock, flags); spin_unlock_irqrestore(&tq->tx_lock, flags);
if (tq->shared->txNumDeferred >= tq->shared->txThreshold) { if (le32_to_cpu(tq->shared->txNumDeferred) >=
le32_to_cpu(tq->shared->txThreshold)) {
tq->shared->txNumDeferred = 0; tq->shared->txNumDeferred = 0;
VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD, VMXNET3_WRITE_BAR0_REG(adapter, VMXNET3_REG_TXPROD,
tq->tx_ring.next2fill); tq->tx_ring.next2fill);
...@@ -889,9 +1007,8 @@ static netdev_tx_t ...@@ -889,9 +1007,8 @@ static netdev_tx_t
vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev) vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct vmxnet3_adapter *adapter = netdev_priv(netdev); struct vmxnet3_adapter *adapter = netdev_priv(netdev);
struct vmxnet3_tx_queue *tq = &adapter->tx_queue;
return vmxnet3_tq_xmit(skb, tq, adapter, netdev); return vmxnet3_tq_xmit(skb, &adapter->tx_queue, adapter, netdev);
} }
...@@ -902,7 +1019,7 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, ...@@ -902,7 +1019,7 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
{ {
if (!gdesc->rcd.cnc && adapter->rxcsum) { if (!gdesc->rcd.cnc && adapter->rxcsum) {
/* typical case: TCP/UDP over IP and both csums are correct */ /* typical case: TCP/UDP over IP and both csums are correct */
if ((gdesc->dword[3] & VMXNET3_RCD_CSUM_OK) == if ((le32_to_cpu(gdesc->dword[3]) & VMXNET3_RCD_CSUM_OK) ==
VMXNET3_RCD_CSUM_OK) { VMXNET3_RCD_CSUM_OK) {
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
BUG_ON(!(gdesc->rcd.tcp || gdesc->rcd.udp)); BUG_ON(!(gdesc->rcd.tcp || gdesc->rcd.udp));
...@@ -957,8 +1074,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, ...@@ -957,8 +1074,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
u32 num_rxd = 0; u32 num_rxd = 0;
struct Vmxnet3_RxCompDesc *rcd; struct Vmxnet3_RxCompDesc *rcd;
struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx; struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
#ifdef __BIG_ENDIAN_BITFIELD
rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd; struct Vmxnet3_RxDesc rxCmdDesc;
struct Vmxnet3_RxCompDesc rxComp;
#endif
vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd,
&rxComp);
while (rcd->gen == rq->comp_ring.gen) { while (rcd->gen == rq->comp_ring.gen) {
struct vmxnet3_rx_buf_info *rbi; struct vmxnet3_rx_buf_info *rbi;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -976,11 +1097,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, ...@@ -976,11 +1097,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
idx = rcd->rxdIdx; idx = rcd->rxdIdx;
ring_idx = rcd->rqID == rq->qid ? 0 : 1; ring_idx = rcd->rqID == rq->qid ? 0 : 1;
vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd,
rxd = &rq->rx_ring[ring_idx].base[idx].rxd; &rxCmdDesc);
rbi = rq->buf_info[ring_idx] + idx; rbi = rq->buf_info[ring_idx] + idx;
BUG_ON(rxd->addr != rbi->dma_addr || rxd->len != rbi->len); BUG_ON(rxd->addr != rbi->dma_addr ||
rxd->len != rbi->len);
if (unlikely(rcd->eop && rcd->err)) { if (unlikely(rcd->eop && rcd->err)) {
vmxnet3_rx_error(rq, rcd, ctx, adapter); vmxnet3_rx_error(rq, rcd, ctx, adapter);
...@@ -1078,7 +1200,8 @@ rcd_done: ...@@ -1078,7 +1200,8 @@ rcd_done:
} }
vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring); vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
rcd = &rq->comp_ring.base[rq->comp_ring.next2proc].rcd; vmxnet3_getRxComp(rcd,
&rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
} }
return num_rxd; return num_rxd;
...@@ -1094,7 +1217,11 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq, ...@@ -1094,7 +1217,11 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
for (ring_idx = 0; ring_idx < 2; ring_idx++) { for (ring_idx = 0; ring_idx < 2; ring_idx++) {
for (i = 0; i < rq->rx_ring[ring_idx].size; i++) { for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
rxd = &rq->rx_ring[ring_idx].base[i].rxd; #ifdef __BIG_ENDIAN_BITFIELD
struct Vmxnet3_RxDesc rxDesc;
#endif
vmxnet3_getRxDesc(rxd,
&rq->rx_ring[ring_idx].base[i].rxd, &rxDesc);
if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD && if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD &&
rq->buf_info[ring_idx][i].skb) { rq->buf_info[ring_idx][i].skb) {
...@@ -1346,12 +1473,12 @@ vmxnet3_request_irqs(struct vmxnet3_adapter *adapter) ...@@ -1346,12 +1473,12 @@ vmxnet3_request_irqs(struct vmxnet3_adapter *adapter)
err = request_irq(adapter->intr.msix_entries[0].vector, err = request_irq(adapter->intr.msix_entries[0].vector,
vmxnet3_intr, 0, adapter->netdev->name, vmxnet3_intr, 0, adapter->netdev->name,
adapter->netdev); adapter->netdev);
} else } else if (adapter->intr.type == VMXNET3_IT_MSI) {
#endif
if (adapter->intr.type == VMXNET3_IT_MSI) {
err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0, err = request_irq(adapter->pdev->irq, vmxnet3_intr, 0,
adapter->netdev->name, adapter->netdev); adapter->netdev->name, adapter->netdev);
} else { } else
#endif
{
err = request_irq(adapter->pdev->irq, vmxnet3_intr, err = request_irq(adapter->pdev->irq, vmxnet3_intr,
IRQF_SHARED, adapter->netdev->name, IRQF_SHARED, adapter->netdev->name,
adapter->netdev); adapter->netdev);
...@@ -1412,6 +1539,22 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter) ...@@ -1412,6 +1539,22 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
} }
inline void set_flag_le16(__le16 *data, u16 flag)
{
*data = cpu_to_le16(le16_to_cpu(*data) | flag);
}
inline void set_flag_le64(__le64 *data, u64 flag)
{
*data = cpu_to_le64(le64_to_cpu(*data) | flag);
}
inline void reset_flag_le64(__le64 *data, u64 flag)
{
*data = cpu_to_le64(le64_to_cpu(*data) & ~flag);
}
static void static void
vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{ {
...@@ -1427,7 +1570,8 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ...@@ -1427,7 +1570,8 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
adapter->vlan_grp = grp; adapter->vlan_grp = grp;
/* update FEATURES to device */ /* update FEATURES to device */
devRead->misc.uptFeatures |= UPT1_F_RXVLAN; set_flag_le64(&devRead->misc.uptFeatures,
UPT1_F_RXVLAN);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE); VMXNET3_CMD_UPDATE_FEATURE);
/* /*
...@@ -1450,7 +1594,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ...@@ -1450,7 +1594,7 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
struct Vmxnet3_DSDevRead *devRead = &shared->devRead; struct Vmxnet3_DSDevRead *devRead = &shared->devRead;
adapter->vlan_grp = NULL; adapter->vlan_grp = NULL;
if (devRead->misc.uptFeatures & UPT1_F_RXVLAN) { if (le64_to_cpu(devRead->misc.uptFeatures) & UPT1_F_RXVLAN) {
int i; int i;
for (i = 0; i < VMXNET3_VFT_SIZE; i++) { for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
...@@ -1463,7 +1607,8 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ...@@ -1463,7 +1607,8 @@ vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
VMXNET3_CMD_UPDATE_VLAN_FILTERS); VMXNET3_CMD_UPDATE_VLAN_FILTERS);
/* update FEATURES to device */ /* update FEATURES to device */
devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN; reset_flag_le64(&devRead->misc.uptFeatures,
UPT1_F_RXVLAN);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE); VMXNET3_CMD_UPDATE_FEATURE);
} }
...@@ -1565,9 +1710,10 @@ vmxnet3_set_mc(struct net_device *netdev) ...@@ -1565,9 +1710,10 @@ vmxnet3_set_mc(struct net_device *netdev)
new_table = vmxnet3_copy_mc(netdev); new_table = vmxnet3_copy_mc(netdev);
if (new_table) { if (new_table) {
new_mode |= VMXNET3_RXM_MCAST; new_mode |= VMXNET3_RXM_MCAST;
rxConf->mfTableLen = netdev->mc_count * rxConf->mfTableLen = cpu_to_le16(
ETH_ALEN; netdev->mc_count * ETH_ALEN);
rxConf->mfTablePA = virt_to_phys(new_table); rxConf->mfTablePA = cpu_to_le64(virt_to_phys(
new_table));
} else { } else {
printk(KERN_INFO "%s: failed to copy mcast list" printk(KERN_INFO "%s: failed to copy mcast list"
", setting ALL_MULTI\n", netdev->name); ", setting ALL_MULTI\n", netdev->name);
...@@ -1582,7 +1728,7 @@ vmxnet3_set_mc(struct net_device *netdev) ...@@ -1582,7 +1728,7 @@ vmxnet3_set_mc(struct net_device *netdev)
} }
if (new_mode != rxConf->rxMode) { if (new_mode != rxConf->rxMode) {
rxConf->rxMode = new_mode; rxConf->rxMode = cpu_to_le32(new_mode);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_RX_MODE); VMXNET3_CMD_UPDATE_RX_MODE);
} }
...@@ -1610,63 +1756,69 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) ...@@ -1610,63 +1756,69 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
memset(shared, 0, sizeof(*shared)); memset(shared, 0, sizeof(*shared));
/* driver settings */ /* driver settings */
shared->magic = VMXNET3_REV1_MAGIC; shared->magic = cpu_to_le32(VMXNET3_REV1_MAGIC);
devRead->misc.driverInfo.version = VMXNET3_DRIVER_VERSION_NUM; devRead->misc.driverInfo.version = cpu_to_le32(
VMXNET3_DRIVER_VERSION_NUM);
devRead->misc.driverInfo.gos.gosBits = (sizeof(void *) == 4 ? devRead->misc.driverInfo.gos.gosBits = (sizeof(void *) == 4 ?
VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64); VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64);
devRead->misc.driverInfo.gos.gosType = VMXNET3_GOS_TYPE_LINUX; devRead->misc.driverInfo.gos.gosType = VMXNET3_GOS_TYPE_LINUX;
devRead->misc.driverInfo.vmxnet3RevSpt = 1; *((u32 *)&devRead->misc.driverInfo.gos) = cpu_to_le32(
devRead->misc.driverInfo.uptVerSpt = 1; *((u32 *)&devRead->misc.driverInfo.gos));
devRead->misc.driverInfo.vmxnet3RevSpt = cpu_to_le32(1);
devRead->misc.driverInfo.uptVerSpt = cpu_to_le32(1);
devRead->misc.ddPA = virt_to_phys(adapter); devRead->misc.ddPA = cpu_to_le64(virt_to_phys(adapter));
devRead->misc.ddLen = sizeof(struct vmxnet3_adapter); devRead->misc.ddLen = cpu_to_le32(sizeof(struct vmxnet3_adapter));
/* set up feature flags */ /* set up feature flags */
if (adapter->rxcsum) if (adapter->rxcsum)
devRead->misc.uptFeatures |= UPT1_F_RXCSUM; set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_RXCSUM);
if (adapter->lro) { if (adapter->lro) {
devRead->misc.uptFeatures |= UPT1_F_LRO; set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_LRO);
devRead->misc.maxNumRxSG = 1 + MAX_SKB_FRAGS; devRead->misc.maxNumRxSG = cpu_to_le16(1 + MAX_SKB_FRAGS);
} }
if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX) if ((adapter->netdev->features & NETIF_F_HW_VLAN_RX)
&& adapter->vlan_grp) { && adapter->vlan_grp) {
devRead->misc.uptFeatures |= UPT1_F_RXVLAN; set_flag_le64(&devRead->misc.uptFeatures, UPT1_F_RXVLAN);
} }
devRead->misc.mtu = adapter->netdev->mtu; devRead->misc.mtu = cpu_to_le32(adapter->netdev->mtu);
devRead->misc.queueDescPA = adapter->queue_desc_pa; devRead->misc.queueDescPA = cpu_to_le64(adapter->queue_desc_pa);
devRead->misc.queueDescLen = sizeof(struct Vmxnet3_TxQueueDesc) + devRead->misc.queueDescLen = cpu_to_le32(
sizeof(struct Vmxnet3_RxQueueDesc); sizeof(struct Vmxnet3_TxQueueDesc) +
sizeof(struct Vmxnet3_RxQueueDesc));
/* tx queue settings */ /* tx queue settings */
BUG_ON(adapter->tx_queue.tx_ring.base == NULL); BUG_ON(adapter->tx_queue.tx_ring.base == NULL);
devRead->misc.numTxQueues = 1; devRead->misc.numTxQueues = 1;
tqc = &adapter->tqd_start->conf; tqc = &adapter->tqd_start->conf;
tqc->txRingBasePA = adapter->tx_queue.tx_ring.basePA; tqc->txRingBasePA = cpu_to_le64(adapter->tx_queue.tx_ring.basePA);
tqc->dataRingBasePA = adapter->tx_queue.data_ring.basePA; tqc->dataRingBasePA = cpu_to_le64(adapter->tx_queue.data_ring.basePA);
tqc->compRingBasePA = adapter->tx_queue.comp_ring.basePA; tqc->compRingBasePA = cpu_to_le64(adapter->tx_queue.comp_ring.basePA);
tqc->ddPA = virt_to_phys(adapter->tx_queue.buf_info); tqc->ddPA = cpu_to_le64(virt_to_phys(
tqc->txRingSize = adapter->tx_queue.tx_ring.size; adapter->tx_queue.buf_info));
tqc->dataRingSize = adapter->tx_queue.data_ring.size; tqc->txRingSize = cpu_to_le32(adapter->tx_queue.tx_ring.size);
tqc->compRingSize = adapter->tx_queue.comp_ring.size; tqc->dataRingSize = cpu_to_le32(adapter->tx_queue.data_ring.size);
tqc->ddLen = sizeof(struct vmxnet3_tx_buf_info) * tqc->compRingSize = cpu_to_le32(adapter->tx_queue.comp_ring.size);
tqc->txRingSize; tqc->ddLen = cpu_to_le32(sizeof(struct vmxnet3_tx_buf_info) *
tqc->txRingSize);
tqc->intrIdx = adapter->tx_queue.comp_ring.intr_idx; tqc->intrIdx = adapter->tx_queue.comp_ring.intr_idx;
/* rx queue settings */ /* rx queue settings */
devRead->misc.numRxQueues = 1; devRead->misc.numRxQueues = 1;
rqc = &adapter->rqd_start->conf; rqc = &adapter->rqd_start->conf;
rqc->rxRingBasePA[0] = adapter->rx_queue.rx_ring[0].basePA; rqc->rxRingBasePA[0] = cpu_to_le64(adapter->rx_queue.rx_ring[0].basePA);
rqc->rxRingBasePA[1] = adapter->rx_queue.rx_ring[1].basePA; rqc->rxRingBasePA[1] = cpu_to_le64(adapter->rx_queue.rx_ring[1].basePA);
rqc->compRingBasePA = adapter->rx_queue.comp_ring.basePA; rqc->compRingBasePA = cpu_to_le64(adapter->rx_queue.comp_ring.basePA);
rqc->ddPA = virt_to_phys(adapter->rx_queue.buf_info); rqc->ddPA = cpu_to_le64(virt_to_phys(
rqc->rxRingSize[0] = adapter->rx_queue.rx_ring[0].size; adapter->rx_queue.buf_info));
rqc->rxRingSize[1] = adapter->rx_queue.rx_ring[1].size; rqc->rxRingSize[0] = cpu_to_le32(adapter->rx_queue.rx_ring[0].size);
rqc->compRingSize = adapter->rx_queue.comp_ring.size; rqc->rxRingSize[1] = cpu_to_le32(adapter->rx_queue.rx_ring[1].size);
rqc->ddLen = sizeof(struct vmxnet3_rx_buf_info) * rqc->compRingSize = cpu_to_le32(adapter->rx_queue.comp_ring.size);
(rqc->rxRingSize[0] + rqc->rxRingSize[1]); rqc->ddLen = cpu_to_le32(sizeof(struct vmxnet3_rx_buf_info) *
(rqc->rxRingSize[0] + rqc->rxRingSize[1]));
rqc->intrIdx = adapter->rx_queue.comp_ring.intr_idx; rqc->intrIdx = adapter->rx_queue.comp_ring.intr_idx;
/* intr settings */ /* intr settings */
...@@ -1715,11 +1867,10 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) ...@@ -1715,11 +1867,10 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
vmxnet3_setup_driver_shared(adapter); vmxnet3_setup_driver_shared(adapter);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAL, VMXNET3_GET_ADDR_LO(
VMXNET3_GET_ADDR_LO(adapter->shared_pa)); adapter->shared_pa));
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_DSAH, VMXNET3_GET_ADDR_HI(
VMXNET3_GET_ADDR_HI(adapter->shared_pa)); adapter->shared_pa));
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_ACTIVATE_DEV); VMXNET3_CMD_ACTIVATE_DEV);
ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); ret = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
...@@ -2425,7 +2576,7 @@ vmxnet3_suspend(struct device *device) ...@@ -2425,7 +2576,7 @@ vmxnet3_suspend(struct device *device)
memcpy(pmConf->filters[i].pattern, netdev->dev_addr, ETH_ALEN); memcpy(pmConf->filters[i].pattern, netdev->dev_addr, ETH_ALEN);
pmConf->filters[i].mask[0] = 0x3F; /* LSB ETH_ALEN bits */ pmConf->filters[i].mask[0] = 0x3F; /* LSB ETH_ALEN bits */
pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER; set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_FILTER);
i++; i++;
} }
...@@ -2467,19 +2618,21 @@ vmxnet3_suspend(struct device *device) ...@@ -2467,19 +2618,21 @@ vmxnet3_suspend(struct device *device)
pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */ pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */
in_dev_put(in_dev); in_dev_put(in_dev);
pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER; set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_FILTER);
i++; i++;
} }
skip_arp: skip_arp:
if (adapter->wol & WAKE_MAGIC) if (adapter->wol & WAKE_MAGIC)
pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_MAGIC; set_flag_le16(&pmConf->wakeUpEvents, VMXNET3_PM_WAKEUP_MAGIC);
pmConf->numFilters = i; pmConf->numFilters = i;
adapter->shared->devRead.pmConfDesc.confVer = 1; adapter->shared->devRead.pmConfDesc.confVer = cpu_to_le32(1);
adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf); adapter->shared->devRead.pmConfDesc.confLen = cpu_to_le32(sizeof(
adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf); *pmConf));
adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le64(virt_to_phys(
pmConf));
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_PMCFG); VMXNET3_CMD_UPDATE_PMCFG);
...@@ -2510,9 +2663,11 @@ vmxnet3_resume(struct device *device) ...@@ -2510,9 +2663,11 @@ vmxnet3_resume(struct device *device)
pmConf = adapter->pm_conf; pmConf = adapter->pm_conf;
memset(pmConf, 0, sizeof(*pmConf)); memset(pmConf, 0, sizeof(*pmConf));
adapter->shared->devRead.pmConfDesc.confVer = 1; adapter->shared->devRead.pmConfDesc.confVer = cpu_to_le32(1);
adapter->shared->devRead.pmConfDesc.confLen = sizeof(*pmConf); adapter->shared->devRead.pmConfDesc.confLen = cpu_to_le32(sizeof(
adapter->shared->devRead.pmConfDesc.confPA = virt_to_phys(pmConf); *pmConf));
adapter->shared->devRead.pmConfDesc.confPA = cpu_to_le32(virt_to_phys(
pmConf));
netif_device_attach(netdev); netif_device_attach(netdev);
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
......
...@@ -50,11 +50,13 @@ vmxnet3_set_rx_csum(struct net_device *netdev, u32 val) ...@@ -50,11 +50,13 @@ vmxnet3_set_rx_csum(struct net_device *netdev, u32 val)
adapter->rxcsum = val; adapter->rxcsum = val;
if (netif_running(netdev)) { if (netif_running(netdev)) {
if (val) if (val)
adapter->shared->devRead.misc.uptFeatures |= set_flag_le64(
UPT1_F_RXCSUM; &adapter->shared->devRead.misc.uptFeatures,
UPT1_F_RXCSUM);
else else
adapter->shared->devRead.misc.uptFeatures &= reset_flag_le64(
~UPT1_F_RXCSUM; &adapter->shared->devRead.misc.uptFeatures,
UPT1_F_RXCSUM);
VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
VMXNET3_CMD_UPDATE_FEATURE); VMXNET3_CMD_UPDATE_FEATURE);
......
...@@ -330,14 +330,14 @@ struct vmxnet3_adapter { ...@@ -330,14 +330,14 @@ struct vmxnet3_adapter {
}; };
#define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \
writel((val), (adapter)->hw_addr0 + (reg)) writel(cpu_to_le32(val), (adapter)->hw_addr0 + (reg))
#define VMXNET3_READ_BAR0_REG(adapter, reg) \ #define VMXNET3_READ_BAR0_REG(adapter, reg) \
readl((adapter)->hw_addr0 + (reg)) le32_to_cpu(readl((adapter)->hw_addr0 + (reg)))
#define VMXNET3_WRITE_BAR1_REG(adapter, reg, val) \ #define VMXNET3_WRITE_BAR1_REG(adapter, reg, val) \
writel((val), (adapter)->hw_addr1 + (reg)) writel(cpu_to_le32(val), (adapter)->hw_addr1 + (reg))
#define VMXNET3_READ_BAR1_REG(adapter, reg) \ #define VMXNET3_READ_BAR1_REG(adapter, reg) \
readl((adapter)->hw_addr1 + (reg)) le32_to_cpu(readl((adapter)->hw_addr1 + (reg)))
#define VMXNET3_WAKE_QUEUE_THRESHOLD(tq) (5) #define VMXNET3_WAKE_QUEUE_THRESHOLD(tq) (5)
#define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \ #define VMXNET3_RX_ALLOC_THRESHOLD(rq, ring_idx, adapter) \
...@@ -353,6 +353,10 @@ struct vmxnet3_adapter { ...@@ -353,6 +353,10 @@ struct vmxnet3_adapter {
#define VMXNET3_MAX_ETH_HDR_SIZE 22 #define VMXNET3_MAX_ETH_HDR_SIZE 22
#define VMXNET3_MAX_SKB_BUF_SIZE (3*1024) #define VMXNET3_MAX_SKB_BUF_SIZE (3*1024)
void set_flag_le16(__le16 *data, u16 flag);
void set_flag_le64(__le64 *data, u64 flag);
void reset_flag_le64(__le64 *data, u64 flag);
int int
vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter); vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment