qlcnic: Fix endian issues in 83xx driver

o Split mailbox structure elements on boundary of adapter
  register size i.e. 32bit.
o Shuffle the position of structure elements based on CPU endianness.

Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Shahed Shaikh 2013-03-08 09:53:49 +00:00 committed by David S. Miller
parent 23bdbc80e1
commit a96227e66f
3 changed files with 130 additions and 26 deletions

View File

@ -15,36 +15,57 @@
#define RSS_HASHTYPE_IP_TCP 0x3
/* status descriptor mailbox data
* @phy_addr: physical address of buffer
* @phy_addr_{low|high}: physical address of buffer
* @sds_ring_size: buffer size
* @intrpt_id: interrupt id
* @intrpt_val: source of interrupt
*/
struct qlcnic_sds_mbx {
u64 phy_addr;
u8 rsvd1[16];
u32 phy_addr_low;
u32 phy_addr_high;
u32 rsvd1[4];
#if defined(__LITTLE_ENDIAN)
u16 sds_ring_size;
u16 rsvd2[3];
u16 rsvd2;
u16 rsvd3[2];
u16 intrpt_id;
u8 intrpt_val;
u8 rsvd3[5];
u8 rsvd4;
#elif defined(__BIG_ENDIAN)
u16 rsvd2;
u16 sds_ring_size;
u16 rsvd3[2];
u8 rsvd4;
u8 intrpt_val;
u16 intrpt_id;
#endif
u32 rsvd5;
} __packed;
/* receive descriptor buffer data
* phy_addr_reg: physical address of regular buffer
* phy_addr_jmb: physical address of jumbo buffer
* phy_addr_reg_{low|high}: physical address of regular buffer
* phy_addr_jmb_{low|high}: physical address of jumbo buffer
* reg_ring_sz: size of regular buffer
* reg_ring_len: no. of entries in regular buffer
* jmb_ring_len: no. of entries in jumbo buffer
* jmb_ring_sz: size of jumbo buffer
*/
struct qlcnic_rds_mbx {
u64 phy_addr_reg;
u64 phy_addr_jmb;
u32 phy_addr_reg_low;
u32 phy_addr_reg_high;
u32 phy_addr_jmb_low;
u32 phy_addr_jmb_high;
#if defined(__LITTLE_ENDIAN)
u16 reg_ring_sz;
u16 reg_ring_len;
u16 jmb_ring_sz;
u16 jmb_ring_len;
#elif defined(__BIG_ENDIAN)
u16 reg_ring_len;
u16 reg_ring_sz;
u16 jmb_ring_len;
u16 jmb_ring_sz;
#endif
} __packed;
/* host producers for regular and jumbo rings */
@ -61,6 +82,7 @@ struct __host_producer_mbx {
* @phy_port: physical port id
*/
struct qlcnic_rcv_mbx_out {
#if defined(__LITTLE_ENDIAN)
u8 rcv_num;
u8 sts_num;
u16 ctx_id;
@ -68,32 +90,56 @@ struct qlcnic_rcv_mbx_out {
u8 num_pci_func;
u8 phy_port;
u8 vport_id;
#elif defined(__BIG_ENDIAN)
u16 ctx_id;
u8 sts_num;
u8 rcv_num;
u8 vport_id;
u8 phy_port;
u8 num_pci_func;
u8 state;
#endif
u32 host_csmr[QLCNIC_MAX_RING_SETS];
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
} __packed;
struct qlcnic_add_rings_mbx_out {
#if defined(__LITTLE_ENDIAN)
u8 rcv_num;
u8 sts_num;
u16 ctx_id;
u16 ctx_id;
#elif defined(__BIG_ENDIAN)
u16 ctx_id;
u8 sts_num;
u8 rcv_num;
#endif
u32 host_csmr[QLCNIC_MAX_RING_SETS];
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
} __packed;
/* Transmit context mailbox inbox registers
* @phys_addr: DMA address of the transmit buffer
* @cnsmr_index: host consumer index
* @phys_addr_{low|high}: DMA address of the transmit buffer
* @cnsmr_index_{low|high}: host consumer index
* @size: legth of transmit buffer ring
* @intr_id: interrput id
* @src: src of interrupt
*/
struct qlcnic_tx_mbx {
u64 phys_addr;
u64 cnsmr_index;
u32 phys_addr_low;
u32 phys_addr_high;
u32 cnsmr_index_low;
u32 cnsmr_index_high;
#if defined(__LITTLE_ENDIAN)
u16 size;
u16 intr_id;
u8 src;
u8 rsvd[3];
#elif defined(__BIG_ENDIAN)
u16 intr_id;
u16 size;
u8 rsvd[3];
u8 src;
#endif
} __packed;
/* Transmit context mailbox outbox registers
@ -101,11 +147,18 @@ struct qlcnic_tx_mbx {
* @ctx_id: transmit context id
* @state: state of the transmit context
*/
struct qlcnic_tx_mbx_out {
u32 host_prod;
#if defined(__LITTLE_ENDIAN)
u16 ctx_id;
u8 state;
u8 rsvd;
#elif defined(__BIG_ENDIAN)
u8 rsvd;
u8 state;
u16 ctx_id;
#endif
} __packed;
static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
@ -1004,7 +1057,8 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
sds = &recv_ctx->sds_rings[i];
sds->consumer = 0;
memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
sds_mbx.phy_addr = sds->phys_addr;
sds_mbx.phy_addr_low = LSD(sds->phys_addr);
sds_mbx.phy_addr_high = MSD(sds->phys_addr);
sds_mbx.sds_ring_size = sds->num_desc;
if (adapter->flags & QLCNIC_MSIX_ENABLED)
@ -1090,7 +1144,8 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
sds = &recv_ctx->sds_rings[i];
sds->consumer = 0;
memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
sds_mbx.phy_addr = sds->phys_addr;
sds_mbx.phy_addr_low = LSD(sds->phys_addr);
sds_mbx.phy_addr_high = MSD(sds->phys_addr);
sds_mbx.sds_ring_size = sds->num_desc;
if (adapter->flags & QLCNIC_MSIX_ENABLED)
intrpt_id = ahw->intr_tbl[i].id;
@ -1110,13 +1165,15 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
rds = &recv_ctx->rds_rings[0];
rds->producer = 0;
memset(&rds_mbx, 0, rds_mbx_size);
rds_mbx.phy_addr_reg = rds->phys_addr;
rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr);
rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);
rds_mbx.reg_ring_sz = rds->dma_size;
rds_mbx.reg_ring_len = rds->num_desc;
/* Jumbo ring */
rds = &recv_ctx->rds_rings[1];
rds->producer = 0;
rds_mbx.phy_addr_jmb = rds->phys_addr;
rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr);
rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);
rds_mbx.jmb_ring_sz = rds->dma_size;
rds_mbx.jmb_ring_len = rds->num_desc;
buf = &cmd.req.arg[index];
@ -1182,8 +1239,10 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
/* setup mailbox inbox registerss */
mbx.phys_addr = tx->phys_addr;
mbx.cnsmr_index = tx->hw_cons_phys_addr;
mbx.phys_addr_low = LSD(tx->phys_addr);
mbx.phys_addr_high = MSD(tx->phys_addr);
mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
mbx.size = tx->num_desc;
if (adapter->flags & QLCNIC_MSIX_ENABLED)
msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
@ -1713,7 +1772,12 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
(adapter->recv_ctx->context_id << 16);
mv.vlan = le16_to_cpu(vlan_id);
memcpy(&mv.mac, addr, ETH_ALEN);
mv.mac_addr0 = addr[0];
mv.mac_addr1 = addr[1];
mv.mac_addr2 = addr[2];
mv.mac_addr3 = addr[3];
mv.mac_addr4 = addr[4];
mv.mac_addr5 = addr[5];
buf = &cmd.req.arg[2];
memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
err = qlcnic_issue_cmd(adapter, &cmd);

View File

@ -94,8 +94,23 @@ struct qlcnic_intrpt_config {
};
struct qlcnic_macvlan_mbx {
u8 mac[ETH_ALEN];
#if defined(__LITTLE_ENDIAN)
u8 mac_addr0;
u8 mac_addr1;
u8 mac_addr2;
u8 mac_addr3;
u8 mac_addr4;
u8 mac_addr5;
u16 vlan;
#elif defined(__BIG_ENDIAN)
u8 mac_addr3;
u8 mac_addr2;
u8 mac_addr1;
u8 mac_addr0;
u16 vlan;
u8 mac_addr5;
u8 mac_addr4;
#endif
};
struct qlc_83xx_fw_info {

View File

@ -31,6 +31,7 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);
/* Template header */
struct qlc_83xx_reset_hdr {
#if defined(__LITTLE_ENDIAN)
u16 version;
u16 signature;
u16 size;
@ -39,14 +40,31 @@ struct qlc_83xx_reset_hdr {
u16 checksum;
u16 init_offset;
u16 start_offset;
#elif defined(__BIG_ENDIAN)
u16 signature;
u16 version;
u16 entries;
u16 size;
u16 checksum;
u16 hdr_size;
u16 start_offset;
u16 init_offset;
#endif
} __packed;
/* Command entry header. */
struct qlc_83xx_entry_hdr {
u16 cmd;
u16 size;
u16 count;
u16 delay;
#if defined(__LITTLE_ENDIAN)
u16 cmd;
u16 size;
u16 count;
u16 delay;
#elif defined(__BIG_ENDIAN)
u16 size;
u16 cmd;
u16 delay;
u16 count;
#endif
} __packed;
/* Generic poll command */
@ -60,10 +78,17 @@ struct qlc_83xx_rmw {
u32 mask;
u32 xor_value;
u32 or_value;
#if defined(__LITTLE_ENDIAN)
u8 shl;
u8 shr;
u8 index_a;
u8 rsvd;
#elif defined(__BIG_ENDIAN)
u8 rsvd;
u8 index_a;
u8 shr;
u8 shl;
#endif
} __packed;
/* Generic command with 2 DWORD */