diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 288 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 150 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 609 |
10 files changed, 994 insertions, 175 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 78d1db686bdf..e5f7695e8443 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1584,6 +1584,9 @@ struct qlcnic_hardware_ops { | |||
1584 | int (*create_rx_ctx) (struct qlcnic_adapter *); | 1584 | int (*create_rx_ctx) (struct qlcnic_adapter *); |
1585 | int (*create_tx_ctx) (struct qlcnic_adapter *, | 1585 | int (*create_tx_ctx) (struct qlcnic_adapter *, |
1586 | struct qlcnic_host_tx_ring *, int); | 1586 | struct qlcnic_host_tx_ring *, int); |
1587 | void (*del_rx_ctx) (struct qlcnic_adapter *); | ||
1588 | void (*del_tx_ctx) (struct qlcnic_adapter *, | ||
1589 | struct qlcnic_host_tx_ring *); | ||
1587 | int (*setup_link_event) (struct qlcnic_adapter *, int); | 1590 | int (*setup_link_event) (struct qlcnic_adapter *, int); |
1588 | int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8); | 1591 | int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8); |
1589 | int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *); | 1592 | int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *); |
@@ -1703,6 +1706,17 @@ static inline int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
1703 | return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring); | 1706 | return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring); |
1704 | } | 1707 | } |
1705 | 1708 | ||
1709 | static inline void qlcnic_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter) | ||
1710 | { | ||
1711 | return adapter->ahw->hw_ops->del_rx_ctx(adapter); | ||
1712 | } | ||
1713 | |||
1714 | static inline void qlcnic_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter, | ||
1715 | struct qlcnic_host_tx_ring *ptr) | ||
1716 | { | ||
1717 | return adapter->ahw->hw_ops->del_tx_ctx(adapter, ptr); | ||
1718 | } | ||
1719 | |||
1706 | static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, | 1720 | static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, |
1707 | int enable) | 1721 | int enable) |
1708 | { | 1722 | { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 89dcea593646..374fa8a3791b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -16,153 +16,6 @@ | |||
16 | #define RSS_HASHTYPE_IP_TCP 0x3 | 16 | #define RSS_HASHTYPE_IP_TCP 0x3 |
17 | #define QLC_83XX_FW_MBX_CMD 0 | 17 | #define QLC_83XX_FW_MBX_CMD 0 |
18 | 18 | ||
19 | /* status descriptor mailbox data | ||
20 | * @phy_addr_{low|high}: physical address of buffer | ||
21 | * @sds_ring_size: buffer size | ||
22 | * @intrpt_id: interrupt id | ||
23 | * @intrpt_val: source of interrupt | ||
24 | */ | ||
25 | struct qlcnic_sds_mbx { | ||
26 | u32 phy_addr_low; | ||
27 | u32 phy_addr_high; | ||
28 | u32 rsvd1[4]; | ||
29 | #if defined(__LITTLE_ENDIAN) | ||
30 | u16 sds_ring_size; | ||
31 | u16 rsvd2; | ||
32 | u16 rsvd3[2]; | ||
33 | u16 intrpt_id; | ||
34 | u8 intrpt_val; | ||
35 | u8 rsvd4; | ||
36 | #elif defined(__BIG_ENDIAN) | ||
37 | u16 rsvd2; | ||
38 | u16 sds_ring_size; | ||
39 | u16 rsvd3[2]; | ||
40 | u8 rsvd4; | ||
41 | u8 intrpt_val; | ||
42 | u16 intrpt_id; | ||
43 | #endif | ||
44 | u32 rsvd5; | ||
45 | } __packed; | ||
46 | |||
47 | /* receive descriptor buffer data | ||
48 | * phy_addr_reg_{low|high}: physical address of regular buffer | ||
49 | * phy_addr_jmb_{low|high}: physical address of jumbo buffer | ||
50 | * reg_ring_sz: size of regular buffer | ||
51 | * reg_ring_len: no. of entries in regular buffer | ||
52 | * jmb_ring_len: no. of entries in jumbo buffer | ||
53 | * jmb_ring_sz: size of jumbo buffer | ||
54 | */ | ||
55 | struct qlcnic_rds_mbx { | ||
56 | u32 phy_addr_reg_low; | ||
57 | u32 phy_addr_reg_high; | ||
58 | u32 phy_addr_jmb_low; | ||
59 | u32 phy_addr_jmb_high; | ||
60 | #if defined(__LITTLE_ENDIAN) | ||
61 | u16 reg_ring_sz; | ||
62 | u16 reg_ring_len; | ||
63 | u16 jmb_ring_sz; | ||
64 | u16 jmb_ring_len; | ||
65 | #elif defined(__BIG_ENDIAN) | ||
66 | u16 reg_ring_len; | ||
67 | u16 reg_ring_sz; | ||
68 | u16 jmb_ring_len; | ||
69 | u16 jmb_ring_sz; | ||
70 | #endif | ||
71 | } __packed; | ||
72 | |||
73 | /* host producers for regular and jumbo rings */ | ||
74 | struct __host_producer_mbx { | ||
75 | u32 reg_buf; | ||
76 | u32 jmb_buf; | ||
77 | } __packed; | ||
78 | |||
79 | /* Receive context mailbox data outbox registers | ||
80 | * @state: state of the context | ||
81 | * @vport_id: virtual port id | ||
82 | * @context_id: receive context id | ||
83 | * @num_pci_func: number of pci functions of the port | ||
84 | * @phy_port: physical port id | ||
85 | */ | ||
86 | struct qlcnic_rcv_mbx_out { | ||
87 | #if defined(__LITTLE_ENDIAN) | ||
88 | u8 rcv_num; | ||
89 | u8 sts_num; | ||
90 | u16 ctx_id; | ||
91 | u8 state; | ||
92 | u8 num_pci_func; | ||
93 | u8 phy_port; | ||
94 | u8 vport_id; | ||
95 | #elif defined(__BIG_ENDIAN) | ||
96 | u16 ctx_id; | ||
97 | u8 sts_num; | ||
98 | u8 rcv_num; | ||
99 | u8 vport_id; | ||
100 | u8 phy_port; | ||
101 | u8 num_pci_func; | ||
102 | u8 state; | ||
103 | #endif | ||
104 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
105 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
106 | } __packed; | ||
107 | |||
108 | struct qlcnic_add_rings_mbx_out { | ||
109 | #if defined(__LITTLE_ENDIAN) | ||
110 | u8 rcv_num; | ||
111 | u8 sts_num; | ||
112 | u16 ctx_id; | ||
113 | #elif defined(__BIG_ENDIAN) | ||
114 | u16 ctx_id; | ||
115 | u8 sts_num; | ||
116 | u8 rcv_num; | ||
117 | #endif | ||
118 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
119 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
120 | } __packed; | ||
121 | |||
122 | /* Transmit context mailbox inbox registers | ||
123 | * @phys_addr_{low|high}: DMA address of the transmit buffer | ||
124 | * @cnsmr_index_{low|high}: host consumer index | ||
125 | * @size: legth of transmit buffer ring | ||
126 | * @intr_id: interrput id | ||
127 | * @src: src of interrupt | ||
128 | */ | ||
129 | struct qlcnic_tx_mbx { | ||
130 | u32 phys_addr_low; | ||
131 | u32 phys_addr_high; | ||
132 | u32 cnsmr_index_low; | ||
133 | u32 cnsmr_index_high; | ||
134 | #if defined(__LITTLE_ENDIAN) | ||
135 | u16 size; | ||
136 | u16 intr_id; | ||
137 | u8 src; | ||
138 | u8 rsvd[3]; | ||
139 | #elif defined(__BIG_ENDIAN) | ||
140 | u16 intr_id; | ||
141 | u16 size; | ||
142 | u8 rsvd[3]; | ||
143 | u8 src; | ||
144 | #endif | ||
145 | } __packed; | ||
146 | |||
147 | /* Transmit context mailbox outbox registers | ||
148 | * @host_prod: host producer index | ||
149 | * @ctx_id: transmit context id | ||
150 | * @state: state of the transmit context | ||
151 | */ | ||
152 | |||
153 | struct qlcnic_tx_mbx_out { | ||
154 | u32 host_prod; | ||
155 | #if defined(__LITTLE_ENDIAN) | ||
156 | u16 ctx_id; | ||
157 | u8 state; | ||
158 | u8 rsvd; | ||
159 | #elif defined(__BIG_ENDIAN) | ||
160 | u8 rsvd; | ||
161 | u8 state; | ||
162 | u16 ctx_id; | ||
163 | #endif | ||
164 | } __packed; | ||
165 | |||
166 | static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { | 19 | static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { |
167 | {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1}, | 20 | {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1}, |
168 | {QLCNIC_CMD_CONFIG_INTRPT, 18, 34}, | 21 | {QLCNIC_CMD_CONFIG_INTRPT, 18, 34}, |
@@ -304,6 +157,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
304 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, | 157 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, |
305 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, | 158 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, |
306 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, | 159 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, |
160 | .del_rx_ctx = qlcnic_83xx_del_rx_ctx, | ||
161 | .del_tx_ctx = qlcnic_83xx_del_tx_ctx, | ||
307 | .setup_link_event = qlcnic_83xx_setup_link_event, | 162 | .setup_link_event = qlcnic_83xx_setup_link_event, |
308 | .get_nic_info = qlcnic_83xx_get_nic_info, | 163 | .get_nic_info = qlcnic_83xx_get_nic_info, |
309 | .get_pci_info = qlcnic_83xx_get_pci_info, | 164 | .get_pci_info = qlcnic_83xx_get_pci_info, |
@@ -1126,6 +981,32 @@ out: | |||
1126 | return err; | 981 | return err; |
1127 | } | 982 | } |
1128 | 983 | ||
984 | void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *adapter) | ||
985 | { | ||
986 | int err; | ||
987 | u32 temp = 0; | ||
988 | struct qlcnic_cmd_args cmd; | ||
989 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
990 | |||
991 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX)) | ||
992 | return; | ||
993 | |||
994 | if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) | ||
995 | cmd.req.arg[0] |= (0x3 << 29); | ||
996 | |||
997 | if (qlcnic_sriov_pf_check(adapter)) | ||
998 | qlcnic_pf_set_interface_id_del_rx_ctx(adapter, &temp); | ||
999 | |||
1000 | cmd.req.arg[1] = recv_ctx->context_id | temp; | ||
1001 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1002 | if (err) | ||
1003 | dev_err(&adapter->pdev->dev, | ||
1004 | "Failed to destroy rx ctx in firmware\n"); | ||
1005 | |||
1006 | recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED; | ||
1007 | qlcnic_free_mbx_args(&cmd); | ||
1008 | } | ||
1009 | |||
1129 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) | 1010 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) |
1130 | { | 1011 | { |
1131 | int i, err, index, sds_mbx_size, rds_mbx_size; | 1012 | int i, err, index, sds_mbx_size, rds_mbx_size; |
@@ -1156,9 +1037,17 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
1156 | /* set mailbox hdr and capabilities */ | 1037 | /* set mailbox hdr and capabilities */ |
1157 | qlcnic_alloc_mbx_args(&cmd, adapter, | 1038 | qlcnic_alloc_mbx_args(&cmd, adapter, |
1158 | QLCNIC_CMD_CREATE_RX_CTX); | 1039 | QLCNIC_CMD_CREATE_RX_CTX); |
1040 | |||
1041 | if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) | ||
1042 | cmd.req.arg[0] |= (0x3 << 29); | ||
1043 | |||
1159 | cmd.req.arg[1] = cap; | 1044 | cmd.req.arg[1] = cap; |
1160 | cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) | | 1045 | cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) | |
1161 | (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16); | 1046 | (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16); |
1047 | |||
1048 | if (qlcnic_sriov_pf_check(adapter)) | ||
1049 | qlcnic_pf_set_interface_id_create_rx_ctx(adapter, | ||
1050 | &cmd.req.arg[6]); | ||
1162 | /* set up status rings, mbx 8-57/87 */ | 1051 | /* set up status rings, mbx 8-57/87 */ |
1163 | index = QLC_83XX_HOST_SDS_MBX_IDX; | 1052 | index = QLC_83XX_HOST_SDS_MBX_IDX; |
1164 | for (i = 0; i < num_sds; i++) { | 1053 | for (i = 0; i < num_sds; i++) { |
@@ -1242,12 +1131,34 @@ out: | |||
1242 | return err; | 1131 | return err; |
1243 | } | 1132 | } |
1244 | 1133 | ||
1134 | void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *adapter, | ||
1135 | struct qlcnic_host_tx_ring *tx_ring) | ||
1136 | { | ||
1137 | struct qlcnic_cmd_args cmd; | ||
1138 | u32 temp = 0; | ||
1139 | |||
1140 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX)) | ||
1141 | return; | ||
1142 | |||
1143 | if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) | ||
1144 | cmd.req.arg[0] |= (0x3 << 29); | ||
1145 | |||
1146 | if (qlcnic_sriov_pf_check(adapter)) | ||
1147 | qlcnic_pf_set_interface_id_del_tx_ctx(adapter, &temp); | ||
1148 | |||
1149 | cmd.req.arg[1] = tx_ring->ctx_id | temp; | ||
1150 | if (qlcnic_issue_cmd(adapter, &cmd)) | ||
1151 | dev_err(&adapter->pdev->dev, | ||
1152 | "Failed to destroy tx ctx in firmware\n"); | ||
1153 | qlcnic_free_mbx_args(&cmd); | ||
1154 | } | ||
1155 | |||
1245 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | 1156 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, |
1246 | struct qlcnic_host_tx_ring *tx, int ring) | 1157 | struct qlcnic_host_tx_ring *tx, int ring) |
1247 | { | 1158 | { |
1248 | int err; | 1159 | int err; |
1249 | u16 msix_id; | 1160 | u16 msix_id; |
1250 | u32 *buf, intr_mask; | 1161 | u32 *buf, intr_mask, temp = 0; |
1251 | struct qlcnic_cmd_args cmd; | 1162 | struct qlcnic_cmd_args cmd; |
1252 | struct qlcnic_tx_mbx mbx; | 1163 | struct qlcnic_tx_mbx mbx; |
1253 | struct qlcnic_tx_mbx_out *mbx_out; | 1164 | struct qlcnic_tx_mbx_out *mbx_out; |
@@ -1284,8 +1195,15 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
1284 | mbx.src = 0; | 1195 | mbx.src = 0; |
1285 | 1196 | ||
1286 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); | 1197 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); |
1198 | |||
1199 | if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) | ||
1200 | cmd.req.arg[0] |= (0x3 << 29); | ||
1201 | |||
1202 | if (qlcnic_sriov_pf_check(adapter)) | ||
1203 | qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp); | ||
1204 | |||
1287 | cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT; | 1205 | cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT; |
1288 | cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES; | 1206 | cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES | temp; |
1289 | buf = &cmd.req.arg[6]; | 1207 | buf = &cmd.req.arg[6]; |
1290 | memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx)); | 1208 | memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx)); |
1291 | /* send the mailbox command*/ | 1209 | /* send the mailbox command*/ |
@@ -1578,24 +1496,35 @@ int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable) | |||
1578 | return err; | 1496 | return err; |
1579 | } | 1497 | } |
1580 | 1498 | ||
1499 | static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter, | ||
1500 | u32 *interface_id) | ||
1501 | { | ||
1502 | if (qlcnic_sriov_pf_check(adapter)) { | ||
1503 | qlcnic_pf_set_interface_id_promisc(adapter, interface_id); | ||
1504 | } else { | ||
1505 | if (!qlcnic_sriov_vf_check(adapter)) | ||
1506 | *interface_id = adapter->recv_ctx->context_id << 16; | ||
1507 | } | ||
1508 | } | ||
1509 | |||
1581 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | 1510 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) |
1582 | { | 1511 | { |
1583 | int err; | 1512 | int err; |
1584 | u32 temp; | 1513 | u32 temp = 0; |
1585 | struct qlcnic_cmd_args cmd; | 1514 | struct qlcnic_cmd_args cmd; |
1586 | 1515 | ||
1587 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | 1516 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) |
1588 | return -EIO; | 1517 | return -EIO; |
1589 | 1518 | ||
1590 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); | 1519 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); |
1591 | temp = adapter->recv_ctx->context_id << 16; | 1520 | qlcnic_83xx_set_interface_id_promisc(adapter, &temp); |
1592 | cmd.req.arg[1] = (mode ? 1 : 0) | temp; | 1521 | cmd.req.arg[1] = (mode ? 1 : 0) | temp; |
1593 | err = qlcnic_issue_cmd(adapter, &cmd); | 1522 | err = qlcnic_issue_cmd(adapter, &cmd); |
1594 | if (err) | 1523 | if (err) |
1595 | dev_info(&adapter->pdev->dev, | 1524 | dev_info(&adapter->pdev->dev, |
1596 | "Promiscous mode config failed\n"); | 1525 | "Promiscous mode config failed\n"); |
1597 | qlcnic_free_mbx_args(&cmd); | ||
1598 | 1526 | ||
1527 | qlcnic_free_mbx_args(&cmd); | ||
1599 | return err; | 1528 | return err; |
1600 | } | 1529 | } |
1601 | 1530 | ||
@@ -1735,21 +1664,31 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
1735 | return status; | 1664 | return status; |
1736 | } | 1665 | } |
1737 | 1666 | ||
1667 | static void qlcnic_83xx_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, | ||
1668 | u32 *interface_id) | ||
1669 | { | ||
1670 | if (qlcnic_sriov_pf_check(adapter)) { | ||
1671 | qlcnic_pf_set_interface_id_ipaddr(adapter, interface_id); | ||
1672 | } else { | ||
1673 | if (!qlcnic_sriov_vf_check(adapter)) | ||
1674 | *interface_id = adapter->recv_ctx->context_id << 16; | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1738 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, | 1678 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, |
1739 | int mode) | 1679 | int mode) |
1740 | { | 1680 | { |
1741 | int err; | 1681 | int err; |
1742 | u32 temp, temp_ip; | 1682 | u32 temp = 0, temp_ip; |
1743 | struct qlcnic_cmd_args cmd; | 1683 | struct qlcnic_cmd_args cmd; |
1744 | 1684 | ||
1745 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR); | 1685 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR); |
1746 | if (mode == QLCNIC_IP_UP) { | 1686 | qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp); |
1747 | temp = adapter->recv_ctx->context_id << 16; | 1687 | |
1688 | if (mode == QLCNIC_IP_UP) | ||
1748 | cmd.req.arg[1] = 1 | temp; | 1689 | cmd.req.arg[1] = 1 | temp; |
1749 | } else { | 1690 | else |
1750 | temp = adapter->recv_ctx->context_id << 16; | ||
1751 | cmd.req.arg[1] = 2 | temp; | 1691 | cmd.req.arg[1] = 2 | temp; |
1752 | } | ||
1753 | 1692 | ||
1754 | /* | 1693 | /* |
1755 | * Adapter needs IP address in network byte order. | 1694 | * Adapter needs IP address in network byte order. |
@@ -1766,6 +1705,7 @@ void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, | |||
1766 | dev_err(&adapter->netdev->dev, | 1705 | dev_err(&adapter->netdev->dev, |
1767 | "could not notify %s IP 0x%x request\n", | 1706 | "could not notify %s IP 0x%x request\n", |
1768 | (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip); | 1707 | (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip); |
1708 | |||
1769 | qlcnic_free_mbx_args(&cmd); | 1709 | qlcnic_free_mbx_args(&cmd); |
1770 | } | 1710 | } |
1771 | 1711 | ||
@@ -1832,11 +1772,22 @@ int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable) | |||
1832 | 1772 | ||
1833 | } | 1773 | } |
1834 | 1774 | ||
1775 | static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter, | ||
1776 | u32 *interface_id) | ||
1777 | { | ||
1778 | if (qlcnic_sriov_pf_check(adapter)) { | ||
1779 | qlcnic_pf_set_interface_id_macaddr(adapter, interface_id); | ||
1780 | } else { | ||
1781 | if (!qlcnic_sriov_vf_check(adapter)) | ||
1782 | *interface_id = adapter->recv_ctx->context_id << 16; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1835 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | 1786 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, |
1836 | __le16 vlan_id, u8 op) | 1787 | __le16 vlan_id, u8 op) |
1837 | { | 1788 | { |
1838 | int err; | 1789 | int err; |
1839 | u32 *buf; | 1790 | u32 *buf, temp = 0; |
1840 | struct qlcnic_cmd_args cmd; | 1791 | struct qlcnic_cmd_args cmd; |
1841 | struct qlcnic_macvlan_mbx mv; | 1792 | struct qlcnic_macvlan_mbx mv; |
1842 | 1793 | ||
@@ -1846,9 +1797,10 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | |||
1846 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | 1797 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); |
1847 | if (err) | 1798 | if (err) |
1848 | return err; | 1799 | return err; |
1849 | cmd.req.arg[1] = op | (1 << 8) | | ||
1850 | (adapter->recv_ctx->context_id << 16); | ||
1851 | 1800 | ||
1801 | cmd.req.arg[1] = op | (1 << 8); | ||
1802 | qlcnic_83xx_set_interface_id_macaddr(adapter, &temp); | ||
1803 | cmd.req.arg[1] |= temp; | ||
1852 | mv.vlan = le16_to_cpu(vlan_id); | 1804 | mv.vlan = le16_to_cpu(vlan_id); |
1853 | mv.mac_addr0 = addr[0]; | 1805 | mv.mac_addr0 = addr[0]; |
1854 | mv.mac_addr1 = addr[1]; | 1806 | mv.mac_addr1 = addr[1]; |
@@ -2151,6 +2103,10 @@ int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type) | |||
2151 | max_ints = adapter->ahw->num_msix - 1; | 2103 | max_ints = adapter->ahw->num_msix - 1; |
2152 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); | 2104 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); |
2153 | cmd.req.arg[1] = max_ints; | 2105 | cmd.req.arg[1] = max_ints; |
2106 | |||
2107 | if (qlcnic_sriov_vf_check(adapter)) | ||
2108 | cmd.req.arg[1] |= (adapter->ahw->pci_func << 8) | BIT_16; | ||
2109 | |||
2154 | for (i = 0, index = 2; i < max_ints; i++) { | 2110 | for (i = 0, index = 2; i < max_ints; i++) { |
2155 | type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; | 2111 | type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; |
2156 | val = type | (adapter->ahw->intr_tbl[i].type << 4); | 2112 | val = type | (adapter->ahw->intr_tbl[i].type << 4); |
@@ -2757,13 +2713,19 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr, | |||
2757 | 2713 | ||
2758 | int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) | 2714 | int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) |
2759 | { | 2715 | { |
2716 | u8 pci_func; | ||
2760 | int err; | 2717 | int err; |
2761 | u32 config = 0, state; | 2718 | u32 config = 0, state; |
2762 | struct qlcnic_cmd_args cmd; | 2719 | struct qlcnic_cmd_args cmd; |
2763 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 2720 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
2764 | 2721 | ||
2765 | state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func)); | 2722 | if (qlcnic_sriov_vf_check(adapter)) |
2766 | if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) { | 2723 | pci_func = adapter->portnum; |
2724 | else | ||
2725 | pci_func = ahw->pci_func; | ||
2726 | |||
2727 | state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(pci_func)); | ||
2728 | if (!QLC_83xx_FUNC_VAL(state, pci_func)) { | ||
2767 | dev_info(&adapter->pdev->dev, "link state down\n"); | 2729 | dev_info(&adapter->pdev->dev, "link state down\n"); |
2768 | return config; | 2730 | return config; |
2769 | } | 2731 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 3e8dc0b136e6..32ed4b4c4976 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -88,6 +88,153 @@ | |||
88 | 88 | ||
89 | #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 | 89 | #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 |
90 | 90 | ||
91 | /* status descriptor mailbox data | ||
92 | * @phy_addr_{low|high}: physical address of buffer | ||
93 | * @sds_ring_size: buffer size | ||
94 | * @intrpt_id: interrupt id | ||
95 | * @intrpt_val: source of interrupt | ||
96 | */ | ||
97 | struct qlcnic_sds_mbx { | ||
98 | u32 phy_addr_low; | ||
99 | u32 phy_addr_high; | ||
100 | u32 rsvd1[4]; | ||
101 | #if defined(__LITTLE_ENDIAN) | ||
102 | u16 sds_ring_size; | ||
103 | u16 rsvd2; | ||
104 | u16 rsvd3[2]; | ||
105 | u16 intrpt_id; | ||
106 | u8 intrpt_val; | ||
107 | u8 rsvd4; | ||
108 | #elif defined(__BIG_ENDIAN) | ||
109 | u16 rsvd2; | ||
110 | u16 sds_ring_size; | ||
111 | u16 rsvd3[2]; | ||
112 | u8 rsvd4; | ||
113 | u8 intrpt_val; | ||
114 | u16 intrpt_id; | ||
115 | #endif | ||
116 | u32 rsvd5; | ||
117 | } __packed; | ||
118 | |||
119 | /* receive descriptor buffer data | ||
120 | * phy_addr_reg_{low|high}: physical address of regular buffer | ||
121 | * phy_addr_jmb_{low|high}: physical address of jumbo buffer | ||
122 | * reg_ring_sz: size of regular buffer | ||
123 | * reg_ring_len: no. of entries in regular buffer | ||
124 | * jmb_ring_len: no. of entries in jumbo buffer | ||
125 | * jmb_ring_sz: size of jumbo buffer | ||
126 | */ | ||
127 | struct qlcnic_rds_mbx { | ||
128 | u32 phy_addr_reg_low; | ||
129 | u32 phy_addr_reg_high; | ||
130 | u32 phy_addr_jmb_low; | ||
131 | u32 phy_addr_jmb_high; | ||
132 | #if defined(__LITTLE_ENDIAN) | ||
133 | u16 reg_ring_sz; | ||
134 | u16 reg_ring_len; | ||
135 | u16 jmb_ring_sz; | ||
136 | u16 jmb_ring_len; | ||
137 | #elif defined(__BIG_ENDIAN) | ||
138 | u16 reg_ring_len; | ||
139 | u16 reg_ring_sz; | ||
140 | u16 jmb_ring_len; | ||
141 | u16 jmb_ring_sz; | ||
142 | #endif | ||
143 | } __packed; | ||
144 | |||
145 | /* host producers for regular and jumbo rings */ | ||
146 | struct __host_producer_mbx { | ||
147 | u32 reg_buf; | ||
148 | u32 jmb_buf; | ||
149 | } __packed; | ||
150 | |||
151 | /* Receive context mailbox data outbox registers | ||
152 | * @state: state of the context | ||
153 | * @vport_id: virtual port id | ||
154 | * @context_id: receive context id | ||
155 | * @num_pci_func: number of pci functions of the port | ||
156 | * @phy_port: physical port id | ||
157 | */ | ||
158 | struct qlcnic_rcv_mbx_out { | ||
159 | #if defined(__LITTLE_ENDIAN) | ||
160 | u8 rcv_num; | ||
161 | u8 sts_num; | ||
162 | u16 ctx_id; | ||
163 | u8 state; | ||
164 | u8 num_pci_func; | ||
165 | u8 phy_port; | ||
166 | u8 vport_id; | ||
167 | #elif defined(__BIG_ENDIAN) | ||
168 | u16 ctx_id; | ||
169 | u8 sts_num; | ||
170 | u8 rcv_num; | ||
171 | u8 vport_id; | ||
172 | u8 phy_port; | ||
173 | u8 num_pci_func; | ||
174 | u8 state; | ||
175 | #endif | ||
176 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
177 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
178 | } __packed; | ||
179 | |||
180 | struct qlcnic_add_rings_mbx_out { | ||
181 | #if defined(__LITTLE_ENDIAN) | ||
182 | u8 rcv_num; | ||
183 | u8 sts_num; | ||
184 | u16 ctx_id; | ||
185 | #elif defined(__BIG_ENDIAN) | ||
186 | u16 ctx_id; | ||
187 | u8 sts_num; | ||
188 | u8 rcv_num; | ||
189 | #endif | ||
190 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
191 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
192 | } __packed; | ||
193 | |||
194 | /* Transmit context mailbox inbox registers | ||
195 | * @phys_addr_{low|high}: DMA address of the transmit buffer | ||
196 | * @cnsmr_index_{low|high}: host consumer index | ||
197 | * @size: legth of transmit buffer ring | ||
198 | * @intr_id: interrput id | ||
199 | * @src: src of interrupt | ||
200 | */ | ||
201 | struct qlcnic_tx_mbx { | ||
202 | u32 phys_addr_low; | ||
203 | u32 phys_addr_high; | ||
204 | u32 cnsmr_index_low; | ||
205 | u32 cnsmr_index_high; | ||
206 | #if defined(__LITTLE_ENDIAN) | ||
207 | u16 size; | ||
208 | u16 intr_id; | ||
209 | u8 src; | ||
210 | u8 rsvd[3]; | ||
211 | #elif defined(__BIG_ENDIAN) | ||
212 | u16 intr_id; | ||
213 | u16 size; | ||
214 | u8 rsvd[3]; | ||
215 | u8 src; | ||
216 | #endif | ||
217 | } __packed; | ||
218 | |||
219 | /* Transmit context mailbox outbox registers | ||
220 | * @host_prod: host producer index | ||
221 | * @ctx_id: transmit context id | ||
222 | * @state: state of the transmit context | ||
223 | */ | ||
224 | |||
225 | struct qlcnic_tx_mbx_out { | ||
226 | u32 host_prod; | ||
227 | #if defined(__LITTLE_ENDIAN) | ||
228 | u16 ctx_id; | ||
229 | u8 state; | ||
230 | u8 rsvd; | ||
231 | #elif defined(__BIG_ENDIAN) | ||
232 | u8 rsvd; | ||
233 | u8 state; | ||
234 | u16 ctx_id; | ||
235 | #endif | ||
236 | } __packed; | ||
237 | |||
91 | struct qlcnic_intrpt_config { | 238 | struct qlcnic_intrpt_config { |
92 | u8 type; | 239 | u8 type; |
93 | u8 enabled; | 240 | u8 enabled; |
@@ -369,6 +516,9 @@ int qlcnic_ind_rd(struct qlcnic_adapter *, u32); | |||
369 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *); | 516 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *); |
370 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *, | 517 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *, |
371 | struct qlcnic_host_tx_ring *, int); | 518 | struct qlcnic_host_tx_ring *, int); |
519 | void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *); | ||
520 | void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *, | ||
521 | struct qlcnic_host_tx_ring *); | ||
372 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | 522 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); |
373 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int); | 523 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int); |
374 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); | 524 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index c645c94b072d..43562c256379 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -382,8 +382,7 @@ out_free_rq: | |||
382 | return err; | 382 | return err; |
383 | } | 383 | } |
384 | 384 | ||
385 | static void | 385 | void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter) |
386 | qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) | ||
387 | { | 386 | { |
388 | int err; | 387 | int err; |
389 | struct qlcnic_cmd_args cmd; | 388 | struct qlcnic_cmd_args cmd; |
@@ -484,13 +483,13 @@ out_free_rq: | |||
484 | return err; | 483 | return err; |
485 | } | 484 | } |
486 | 485 | ||
487 | static void | 486 | void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter, |
488 | qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter, | 487 | struct qlcnic_host_tx_ring *tx_ring) |
489 | struct qlcnic_host_tx_ring *tx_ring) | ||
490 | { | 488 | { |
491 | struct qlcnic_cmd_args cmd; | 489 | struct qlcnic_cmd_args cmd; |
492 | 490 | ||
493 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX); | 491 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX); |
492 | |||
494 | cmd.req.arg[1] = tx_ring->ctx_id; | 493 | cmd.req.arg[1] = tx_ring->ctx_id; |
495 | if (qlcnic_issue_cmd(adapter, &cmd)) | 494 | if (qlcnic_issue_cmd(adapter, &cmd)) |
496 | dev_err(&adapter->pdev->dev, | 495 | dev_err(&adapter->pdev->dev, |
@@ -605,13 +604,12 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev) | |||
605 | &dev->tx_ring[ring], | 604 | &dev->tx_ring[ring], |
606 | ring); | 605 | ring); |
607 | if (err) { | 606 | if (err) { |
608 | qlcnic_fw_cmd_destroy_rx_ctx(dev); | 607 | qlcnic_fw_cmd_del_rx_ctx(dev); |
609 | if (ring == 0) | 608 | if (ring == 0) |
610 | goto err_out; | 609 | goto err_out; |
611 | 610 | ||
612 | for (i = 0; i < ring; i++) | 611 | for (i = 0; i < ring; i++) |
613 | qlcnic_fw_cmd_destroy_tx_ctx(dev, | 612 | qlcnic_fw_cmd_del_tx_ctx(dev, &dev->tx_ring[i]); |
614 | &dev->tx_ring[i]); | ||
615 | 613 | ||
616 | goto err_out; | 614 | goto err_out; |
617 | } | 615 | } |
@@ -633,10 +631,10 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) | |||
633 | int ring; | 631 | int ring; |
634 | 632 | ||
635 | if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { | 633 | if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { |
636 | qlcnic_fw_cmd_destroy_rx_ctx(adapter); | 634 | qlcnic_fw_cmd_del_rx_ctx(adapter); |
637 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) | 635 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) |
638 | qlcnic_fw_cmd_destroy_tx_ctx(adapter, | 636 | qlcnic_fw_cmd_del_tx_ctx(adapter, |
639 | &adapter->tx_ring[ring]); | 637 | &adapter->tx_ring[ring]); |
640 | 638 | ||
641 | if (qlcnic_83xx_check(adapter) && | 639 | if (qlcnic_83xx_check(adapter) && |
642 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | 640 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index d606e50d8902..e862a77a626b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -178,6 +178,9 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, | |||
178 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); | 178 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); |
179 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, | 179 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, |
180 | struct qlcnic_host_tx_ring *tx_ring, int); | 180 | struct qlcnic_host_tx_ring *tx_ring, int); |
181 | void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *); | ||
182 | void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *, | ||
183 | struct qlcnic_host_tx_ring *); | ||
181 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8); | 184 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8); |
182 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*); | 185 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*); |
183 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | 186 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 25b61884585a..a85ca63a2c9e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -147,7 +147,10 @@ static inline u8 qlcnic_mac_hash(u64 mac) | |||
147 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, | 147 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, |
148 | u16 handle, u8 ring_id) | 148 | u16 handle, u8 ring_id) |
149 | { | 149 | { |
150 | if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) | 150 | unsigned short device = adapter->pdev->device; |
151 | |||
152 | if ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) || | ||
153 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) | ||
151 | return handle | (ring_id << 15); | 154 | return handle | (ring_id << 15); |
152 | else | 155 | else |
153 | return handle; | 156 | return handle; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index f67e8c65350e..7d5727c80b41 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -226,6 +226,9 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) | |||
226 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 226 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
227 | struct sockaddr *addr = p; | 227 | struct sockaddr *addr = p; |
228 | 228 | ||
229 | if (qlcnic_sriov_vf_check(adapter)) | ||
230 | return -EINVAL; | ||
231 | |||
229 | if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED)) | 232 | if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED)) |
230 | return -EOPNOTSUPP; | 233 | return -EOPNOTSUPP; |
231 | 234 | ||
@@ -379,6 +382,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { | |||
379 | .process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag, | 382 | .process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag, |
380 | .create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx, | 383 | .create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx, |
381 | .create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx, | 384 | .create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx, |
385 | .del_rx_ctx = qlcnic_82xx_fw_cmd_del_rx_ctx, | ||
386 | .del_tx_ctx = qlcnic_82xx_fw_cmd_del_tx_ctx, | ||
382 | .setup_link_event = qlcnic_82xx_linkevent_request, | 387 | .setup_link_event = qlcnic_82xx_linkevent_request, |
383 | .get_nic_info = qlcnic_82xx_get_nic_info, | 388 | .get_nic_info = qlcnic_82xx_get_nic_info, |
384 | .get_pci_info = qlcnic_82xx_get_pci_info, | 389 | .get_pci_info = qlcnic_82xx_get_pci_info, |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index 00053ad8bc3c..3c05f170801d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | |||
@@ -119,6 +119,8 @@ struct qlcnic_vport { | |||
119 | 119 | ||
120 | struct qlcnic_vf_info { | 120 | struct qlcnic_vf_info { |
121 | u8 pci_func; | 121 | u8 pci_func; |
122 | u16 rx_ctx_id; | ||
123 | u16 tx_ctx_id; | ||
122 | unsigned long state; | 124 | unsigned long state; |
123 | struct completion ch_free_cmpl; | 125 | struct completion ch_free_cmpl; |
124 | struct work_struct trans_work; | 126 | struct work_struct trans_work; |
@@ -167,9 +169,37 @@ void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *, | |||
167 | void qlcnic_sriov_pf_disable(struct qlcnic_adapter *); | 169 | void qlcnic_sriov_pf_disable(struct qlcnic_adapter *); |
168 | void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *); | 170 | void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *); |
169 | int qlcnic_pci_sriov_configure(struct pci_dev *, int); | 171 | int qlcnic_pci_sriov_configure(struct pci_dev *, int); |
172 | void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *, u32 *); | ||
173 | void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *, u32 *); | ||
174 | void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *, u32 *); | ||
175 | void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *); | ||
176 | void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *); | ||
177 | void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *); | ||
178 | void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *); | ||
170 | #else | 179 | #else |
171 | static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {} | 180 | static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {} |
172 | static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {} | 181 | static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {} |
182 | static inline void | ||
183 | qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter, | ||
184 | u32 *int_id) {} | ||
185 | static inline void | ||
186 | qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter, | ||
187 | u32 *int_id) {} | ||
188 | static inline void | ||
189 | qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter, | ||
190 | u32 *int_id) {} | ||
191 | static inline void | ||
192 | qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter, | ||
193 | u32 *int_id) {} | ||
194 | static inline void | ||
195 | qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, u32 *int_id) | ||
196 | {} | ||
197 | static inline void | ||
198 | qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id) | ||
199 | {} | ||
200 | static inline void | ||
201 | qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id) | ||
202 | {} | ||
173 | #endif | 203 | #endif |
174 | 204 | ||
175 | #endif | 205 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 0615086f4526..6e927f2eb3c7 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #define QLC_BC_HDR_SZ 16 | 21 | #define QLC_BC_HDR_SZ 16 |
22 | #define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ) | 22 | #define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ) |
23 | 23 | ||
24 | #define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF 2048 | ||
25 | #define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF 512 | ||
26 | |||
24 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, | 27 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, |
25 | struct qlcnic_cmd_args *); | 28 | struct qlcnic_cmd_args *); |
26 | 29 | ||
@@ -39,6 +42,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { | |||
39 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, | 42 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, |
40 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, | 43 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, |
41 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, | 44 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, |
45 | .del_rx_ctx = qlcnic_83xx_del_rx_ctx, | ||
46 | .del_tx_ctx = qlcnic_83xx_del_tx_ctx, | ||
42 | .setup_link_event = qlcnic_83xx_setup_link_event, | 47 | .setup_link_event = qlcnic_83xx_setup_link_event, |
43 | .get_nic_info = qlcnic_83xx_get_nic_info, | 48 | .get_nic_info = qlcnic_83xx_get_nic_info, |
44 | .get_pci_info = qlcnic_83xx_get_pci_info, | 49 | .get_pci_info = qlcnic_83xx_get_pci_info, |
@@ -305,6 +310,42 @@ out: | |||
305 | return rsp; | 310 | return rsp; |
306 | } | 311 | } |
307 | 312 | ||
313 | static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter) | ||
314 | { | ||
315 | adapter->num_rxd = QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF; | ||
316 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G; | ||
317 | adapter->num_jumbo_rxd = QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF; | ||
318 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; | ||
319 | adapter->num_txd = MAX_CMD_DESCRIPTORS; | ||
320 | adapter->max_rds_rings = MAX_RDS_RINGS; | ||
321 | } | ||
322 | |||
323 | static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) | ||
324 | { | ||
325 | struct qlcnic_info nic_info; | ||
326 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
327 | int err; | ||
328 | |||
329 | err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func); | ||
330 | if (err) | ||
331 | return -EIO; | ||
332 | |||
333 | if (qlcnic_83xx_get_port_info(adapter)) | ||
334 | return -EIO; | ||
335 | |||
336 | qlcnic_sriov_vf_cfg_buff_desc(adapter); | ||
337 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; | ||
338 | dev_info(&adapter->pdev->dev, "HAL Version: %d\n", | ||
339 | adapter->ahw->fw_hal_version); | ||
340 | |||
341 | ahw->physical_port = (u8) nic_info.phys_port; | ||
342 | ahw->switch_mode = nic_info.switch_mode; | ||
343 | ahw->max_mtu = nic_info.max_mtu; | ||
344 | ahw->op_mode = nic_info.op_mode; | ||
345 | ahw->capabilities = nic_info.capabilities; | ||
346 | return 0; | ||
347 | } | ||
348 | |||
308 | static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, | 349 | static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, |
309 | int pci_using_dac) | 350 | int pci_using_dac) |
310 | { | 351 | { |
@@ -336,6 +377,10 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, | |||
336 | if (err) | 377 | if (err) |
337 | goto err_out_disable_bc_intr; | 378 | goto err_out_disable_bc_intr; |
338 | 379 | ||
380 | err = qlcnic_sriov_vf_init_driver(adapter); | ||
381 | if (err) | ||
382 | goto err_out_send_channel_term; | ||
383 | |||
339 | err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); | 384 | err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); |
340 | if (err) | 385 | if (err) |
341 | goto err_out_send_channel_term; | 386 | goto err_out_send_channel_term; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 87ff58d29155..d6ac7dcef1e4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | |||
@@ -17,6 +17,11 @@ struct qlcnic_sriov_cmd_handler { | |||
17 | int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *); | 17 | int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *); |
18 | }; | 18 | }; |
19 | 19 | ||
20 | struct qlcnic_sriov_fw_cmd_handler { | ||
21 | u32 cmd; | ||
22 | int (*fn) (struct qlcnic_bc_trans *, struct qlcnic_cmd_args *); | ||
23 | }; | ||
24 | |||
20 | static int qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter *adapter, | 25 | static int qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter *adapter, |
21 | struct qlcnic_info *npar_info, | 26 | struct qlcnic_info *npar_info, |
22 | u16 vport_id) | 27 | u16 vport_id) |
@@ -542,11 +547,528 @@ err_out: | |||
542 | return err; | 547 | return err; |
543 | } | 548 | } |
544 | 549 | ||
550 | static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, | ||
551 | struct qlcnic_vport *vp, | ||
552 | u16 func, __le16 vlan, u8 op) | ||
553 | { | ||
554 | struct qlcnic_cmd_args cmd; | ||
555 | struct qlcnic_macvlan_mbx mv; | ||
556 | u8 *addr; | ||
557 | int err; | ||
558 | u32 *buf; | ||
559 | int vpid; | ||
560 | |||
561 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN)) | ||
562 | return -ENOMEM; | ||
563 | |||
564 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func); | ||
565 | if (vpid < 0) { | ||
566 | err = -EINVAL; | ||
567 | goto out; | ||
568 | } | ||
569 | |||
570 | if (vlan) | ||
571 | op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? | ||
572 | QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL); | ||
573 | |||
574 | cmd.req.arg[1] = op | (1 << 8) | (3 << 6); | ||
575 | cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31; | ||
576 | |||
577 | addr = vp->mac; | ||
578 | mv.vlan = le16_to_cpu(vlan); | ||
579 | mv.mac_addr0 = addr[0]; | ||
580 | mv.mac_addr1 = addr[1]; | ||
581 | mv.mac_addr2 = addr[2]; | ||
582 | mv.mac_addr3 = addr[3]; | ||
583 | mv.mac_addr4 = addr[4]; | ||
584 | mv.mac_addr5 = addr[5]; | ||
585 | buf = &cmd.req.arg[2]; | ||
586 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); | ||
587 | |||
588 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
589 | |||
590 | if (err) | ||
591 | dev_err(&adapter->pdev->dev, | ||
592 | "MAC-VLAN %s to CAM failed, err=%d.\n", | ||
593 | ((op == 1) ? "add " : "delete "), err); | ||
594 | |||
595 | out: | ||
596 | qlcnic_free_mbx_args(&cmd); | ||
597 | return err; | ||
598 | } | ||
599 | |||
600 | static int qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args *cmd) | ||
601 | { | ||
602 | if ((cmd->req.arg[0] >> 29) != 0x3) | ||
603 | return -EINVAL; | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran, | ||
609 | struct qlcnic_cmd_args *cmd) | ||
610 | { | ||
611 | struct qlcnic_vf_info *vf = tran->vf; | ||
612 | struct qlcnic_adapter *adapter = vf->adapter; | ||
613 | struct qlcnic_rcv_mbx_out *mbx_out; | ||
614 | int err; | ||
615 | |||
616 | err = qlcnic_sriov_validate_create_rx_ctx(cmd); | ||
617 | if (err) { | ||
618 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
619 | return err; | ||
620 | } | ||
621 | |||
622 | cmd->req.arg[6] = vf->vp->handle; | ||
623 | err = qlcnic_issue_cmd(adapter, cmd); | ||
624 | |||
625 | if (!err) { | ||
626 | mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd->rsp.arg[1]; | ||
627 | vf->rx_ctx_id = mbx_out->ctx_id; | ||
628 | qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func, | ||
629 | 0, QLCNIC_MAC_ADD); | ||
630 | } else { | ||
631 | vf->rx_ctx_id = 0; | ||
632 | } | ||
633 | |||
634 | return err; | ||
635 | } | ||
636 | |||
637 | static int qlcnic_sriov_pf_mac_address_cmd(struct qlcnic_bc_trans *trans, | ||
638 | struct qlcnic_cmd_args *cmd) | ||
639 | { | ||
640 | struct qlcnic_vf_info *vf = trans->vf; | ||
641 | u8 type, *mac; | ||
642 | |||
643 | type = cmd->req.arg[1]; | ||
644 | switch (type) { | ||
645 | case QLCNIC_SET_STATION_MAC: | ||
646 | case QLCNIC_SET_FAC_DEF_MAC: | ||
647 | cmd->rsp.arg[0] = (2 << 25); | ||
648 | break; | ||
649 | case QLCNIC_GET_CURRENT_MAC: | ||
650 | cmd->rsp.arg[0] = (1 << 25); | ||
651 | mac = vf->vp->mac; | ||
652 | cmd->rsp.arg[2] = mac[1] | ((mac[0] << 8) & 0xff00); | ||
653 | cmd->rsp.arg[1] = mac[5] | ((mac[4] << 8) & 0xff00) | | ||
654 | ((mac[3]) << 16 & 0xff0000) | | ||
655 | ((mac[2]) << 24 & 0xff000000); | ||
656 | } | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int qlcnic_sriov_validate_create_tx_ctx(struct qlcnic_cmd_args *cmd) | ||
662 | { | ||
663 | if ((cmd->req.arg[0] >> 29) != 0x3) | ||
664 | return -EINVAL; | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | static int qlcnic_sriov_pf_create_tx_ctx_cmd(struct qlcnic_bc_trans *trans, | ||
670 | struct qlcnic_cmd_args *cmd) | ||
671 | { | ||
672 | struct qlcnic_vf_info *vf = trans->vf; | ||
673 | struct qlcnic_adapter *adapter = vf->adapter; | ||
674 | struct qlcnic_tx_mbx_out *mbx_out; | ||
675 | int err; | ||
676 | |||
677 | err = qlcnic_sriov_validate_create_tx_ctx(cmd); | ||
678 | if (err) { | ||
679 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
680 | return err; | ||
681 | } | ||
682 | |||
683 | cmd->req.arg[5] |= vf->vp->handle << 16; | ||
684 | err = qlcnic_issue_cmd(adapter, cmd); | ||
685 | if (!err) { | ||
686 | mbx_out = (struct qlcnic_tx_mbx_out *)&cmd->rsp.arg[2]; | ||
687 | vf->tx_ctx_id = mbx_out->ctx_id; | ||
688 | } else { | ||
689 | vf->tx_ctx_id = 0; | ||
690 | } | ||
691 | |||
692 | return err; | ||
693 | } | ||
694 | |||
695 | static int qlcnic_sriov_validate_del_rx_ctx(struct qlcnic_vf_info *vf, | ||
696 | struct qlcnic_cmd_args *cmd) | ||
697 | { | ||
698 | if ((cmd->req.arg[0] >> 29) != 0x3) | ||
699 | return -EINVAL; | ||
700 | |||
701 | if ((cmd->req.arg[1] & 0xffff) != vf->rx_ctx_id) | ||
702 | return -EINVAL; | ||
703 | |||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans, | ||
708 | struct qlcnic_cmd_args *cmd) | ||
709 | { | ||
710 | struct qlcnic_vf_info *vf = trans->vf; | ||
711 | struct qlcnic_adapter *adapter = vf->adapter; | ||
712 | int err; | ||
713 | |||
714 | err = qlcnic_sriov_validate_del_rx_ctx(vf, cmd); | ||
715 | if (err) { | ||
716 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
717 | return err; | ||
718 | } | ||
719 | |||
720 | qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func, | ||
721 | 0, QLCNIC_MAC_DEL); | ||
722 | cmd->req.arg[1] |= vf->vp->handle << 16; | ||
723 | err = qlcnic_issue_cmd(adapter, cmd); | ||
724 | |||
725 | if (!err) | ||
726 | vf->rx_ctx_id = 0; | ||
727 | |||
728 | return err; | ||
729 | } | ||
730 | |||
731 | static int qlcnic_sriov_validate_del_tx_ctx(struct qlcnic_vf_info *vf, | ||
732 | struct qlcnic_cmd_args *cmd) | ||
733 | { | ||
734 | if ((cmd->req.arg[0] >> 29) != 0x3) | ||
735 | return -EINVAL; | ||
736 | |||
737 | if ((cmd->req.arg[1] & 0xffff) != vf->tx_ctx_id) | ||
738 | return -EINVAL; | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | static int qlcnic_sriov_pf_del_tx_ctx_cmd(struct qlcnic_bc_trans *trans, | ||
744 | struct qlcnic_cmd_args *cmd) | ||
745 | { | ||
746 | struct qlcnic_vf_info *vf = trans->vf; | ||
747 | struct qlcnic_adapter *adapter = vf->adapter; | ||
748 | int err; | ||
749 | |||
750 | err = qlcnic_sriov_validate_del_tx_ctx(vf, cmd); | ||
751 | if (err) { | ||
752 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
753 | return err; | ||
754 | } | ||
755 | |||
756 | cmd->req.arg[1] |= vf->vp->handle << 16; | ||
757 | err = qlcnic_issue_cmd(adapter, cmd); | ||
758 | |||
759 | if (!err) | ||
760 | vf->tx_ctx_id = 0; | ||
761 | |||
762 | return err; | ||
763 | } | ||
764 | |||
765 | static int qlcnic_sriov_validate_cfg_lro(struct qlcnic_vf_info *vf, | ||
766 | struct qlcnic_cmd_args *cmd) | ||
767 | { | ||
768 | if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id) | ||
769 | return -EINVAL; | ||
770 | |||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static int qlcnic_sriov_pf_cfg_lro_cmd(struct qlcnic_bc_trans *trans, | ||
775 | struct qlcnic_cmd_args *cmd) | ||
776 | { | ||
777 | struct qlcnic_vf_info *vf = trans->vf; | ||
778 | struct qlcnic_adapter *adapter = vf->adapter; | ||
779 | int err; | ||
780 | |||
781 | err = qlcnic_sriov_validate_cfg_lro(vf, cmd); | ||
782 | if (err) { | ||
783 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
784 | return err; | ||
785 | } | ||
786 | |||
787 | err = qlcnic_issue_cmd(adapter, cmd); | ||
788 | return err; | ||
789 | } | ||
790 | |||
791 | static int qlcnic_sriov_pf_cfg_ip_cmd(struct qlcnic_bc_trans *trans, | ||
792 | struct qlcnic_cmd_args *cmd) | ||
793 | { | ||
794 | struct qlcnic_vf_info *vf = trans->vf; | ||
795 | struct qlcnic_adapter *adapter = vf->adapter; | ||
796 | int err = -EIO; | ||
797 | u8 op; | ||
798 | |||
799 | op = cmd->req.arg[1] & 0xff; | ||
800 | |||
801 | cmd->req.arg[1] |= vf->vp->handle << 16; | ||
802 | cmd->req.arg[1] |= BIT_31; | ||
803 | |||
804 | err = qlcnic_issue_cmd(adapter, cmd); | ||
805 | return err; | ||
806 | } | ||
807 | |||
808 | static int qlcnic_sriov_validate_cfg_intrpt(struct qlcnic_vf_info *vf, | ||
809 | struct qlcnic_cmd_args *cmd) | ||
810 | { | ||
811 | if (((cmd->req.arg[1] >> 8) & 0xff) != vf->pci_func) | ||
812 | return -EINVAL; | ||
813 | |||
814 | if (!(cmd->req.arg[1] & BIT_16)) | ||
815 | return -EINVAL; | ||
816 | |||
817 | if ((cmd->req.arg[1] & 0xff) != 0x1) | ||
818 | return -EINVAL; | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static int qlcnic_sriov_pf_cfg_intrpt_cmd(struct qlcnic_bc_trans *trans, | ||
824 | struct qlcnic_cmd_args *cmd) | ||
825 | { | ||
826 | struct qlcnic_vf_info *vf = trans->vf; | ||
827 | struct qlcnic_adapter *adapter = vf->adapter; | ||
828 | int err; | ||
829 | |||
830 | err = qlcnic_sriov_validate_cfg_intrpt(vf, cmd); | ||
831 | if (err) | ||
832 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
833 | else | ||
834 | err = qlcnic_issue_cmd(adapter, cmd); | ||
835 | |||
836 | return err; | ||
837 | } | ||
838 | |||
839 | static int qlcnic_sriov_validate_mtu(struct qlcnic_adapter *adapter, | ||
840 | struct qlcnic_vf_info *vf, | ||
841 | struct qlcnic_cmd_args *cmd) | ||
842 | { | ||
843 | if (cmd->req.arg[1] != vf->rx_ctx_id) | ||
844 | return -EINVAL; | ||
845 | |||
846 | if (cmd->req.arg[2] > adapter->ahw->max_mtu) | ||
847 | return -EINVAL; | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static int qlcnic_sriov_pf_set_mtu_cmd(struct qlcnic_bc_trans *trans, | ||
853 | struct qlcnic_cmd_args *cmd) | ||
854 | { | ||
855 | struct qlcnic_vf_info *vf = trans->vf; | ||
856 | struct qlcnic_adapter *adapter = vf->adapter; | ||
857 | int err; | ||
858 | |||
859 | err = qlcnic_sriov_validate_mtu(adapter, vf, cmd); | ||
860 | if (err) | ||
861 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
862 | else | ||
863 | err = qlcnic_issue_cmd(adapter, cmd); | ||
864 | |||
865 | return err; | ||
866 | } | ||
867 | |||
868 | static int qlcnic_sriov_validate_get_nic_info(struct qlcnic_vf_info *vf, | ||
869 | struct qlcnic_cmd_args *cmd) | ||
870 | { | ||
871 | if (cmd->req.arg[1] & BIT_31) { | ||
872 | if (((cmd->req.arg[1] >> 16) & 0x7fff) != vf->pci_func) | ||
873 | return -EINVAL; | ||
874 | } else { | ||
875 | cmd->req.arg[1] |= vf->vp->handle << 16; | ||
876 | } | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | static int qlcnic_sriov_pf_get_nic_info_cmd(struct qlcnic_bc_trans *trans, | ||
882 | struct qlcnic_cmd_args *cmd) | ||
883 | { | ||
884 | struct qlcnic_vf_info *vf = trans->vf; | ||
885 | struct qlcnic_adapter *adapter = vf->adapter; | ||
886 | int err; | ||
887 | |||
888 | err = qlcnic_sriov_validate_get_nic_info(vf, cmd); | ||
889 | if (err) { | ||
890 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
891 | return err; | ||
892 | } | ||
893 | |||
894 | err = qlcnic_issue_cmd(adapter, cmd); | ||
895 | return err; | ||
896 | } | ||
897 | |||
898 | static int qlcnic_sriov_validate_cfg_rss(struct qlcnic_vf_info *vf, | ||
899 | struct qlcnic_cmd_args *cmd) | ||
900 | { | ||
901 | if (cmd->req.arg[1] != vf->rx_ctx_id) | ||
902 | return -EINVAL; | ||
903 | |||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | static int qlcnic_sriov_pf_cfg_rss_cmd(struct qlcnic_bc_trans *trans, | ||
908 | struct qlcnic_cmd_args *cmd) | ||
909 | { | ||
910 | struct qlcnic_vf_info *vf = trans->vf; | ||
911 | struct qlcnic_adapter *adapter = vf->adapter; | ||
912 | int err; | ||
913 | |||
914 | err = qlcnic_sriov_validate_cfg_rss(vf, cmd); | ||
915 | if (err) | ||
916 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
917 | else | ||
918 | err = qlcnic_issue_cmd(adapter, cmd); | ||
919 | |||
920 | return err; | ||
921 | } | ||
922 | |||
923 | static int qlcnic_sriov_validate_cfg_intrcoal(struct qlcnic_adapter *adapter, | ||
924 | struct qlcnic_vf_info *vf, | ||
925 | struct qlcnic_cmd_args *cmd) | ||
926 | { | ||
927 | struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal; | ||
928 | u16 ctx_id, pkts, time; | ||
929 | |||
930 | ctx_id = cmd->req.arg[1] >> 16; | ||
931 | pkts = cmd->req.arg[2] & 0xffff; | ||
932 | time = cmd->req.arg[2] >> 16; | ||
933 | |||
934 | if (ctx_id != vf->rx_ctx_id) | ||
935 | return -EINVAL; | ||
936 | if (pkts > coal->rx_packets) | ||
937 | return -EINVAL; | ||
938 | if (time < coal->rx_time_us) | ||
939 | return -EINVAL; | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static int qlcnic_sriov_pf_cfg_intrcoal_cmd(struct qlcnic_bc_trans *tran, | ||
945 | struct qlcnic_cmd_args *cmd) | ||
946 | { | ||
947 | struct qlcnic_vf_info *vf = tran->vf; | ||
948 | struct qlcnic_adapter *adapter = vf->adapter; | ||
949 | int err; | ||
950 | |||
951 | err = qlcnic_sriov_validate_cfg_intrcoal(adapter, vf, cmd); | ||
952 | if (err) { | ||
953 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
954 | return err; | ||
955 | } | ||
956 | |||
957 | err = qlcnic_issue_cmd(adapter, cmd); | ||
958 | return err; | ||
959 | } | ||
960 | |||
961 | static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, | ||
962 | struct qlcnic_vf_info *vf, | ||
963 | struct qlcnic_cmd_args *cmd) | ||
964 | { | ||
965 | struct qlcnic_macvlan_mbx *macvlan; | ||
966 | |||
967 | if (!(cmd->req.arg[1] & BIT_8)) | ||
968 | return -EINVAL; | ||
969 | |||
970 | cmd->req.arg[1] |= (vf->vp->handle << 16); | ||
971 | cmd->req.arg[1] |= BIT_31; | ||
972 | |||
973 | macvlan = (struct qlcnic_macvlan_mbx *)&cmd->req.arg[2]; | ||
974 | if (!(macvlan->mac_addr0 & BIT_0)) { | ||
975 | dev_err(&adapter->pdev->dev, | ||
976 | "MAC address change is not allowed from VF %d", | ||
977 | vf->pci_func); | ||
978 | return -EINVAL; | ||
979 | } | ||
980 | |||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static int qlcnic_sriov_pf_cfg_macvlan_cmd(struct qlcnic_bc_trans *trans, | ||
985 | struct qlcnic_cmd_args *cmd) | ||
986 | { | ||
987 | struct qlcnic_vf_info *vf = trans->vf; | ||
988 | struct qlcnic_adapter *adapter = vf->adapter; | ||
989 | int err; | ||
990 | |||
991 | err = qlcnic_sriov_validate_cfg_macvlan(adapter, vf, cmd); | ||
992 | if (err) { | ||
993 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
994 | return err; | ||
995 | } | ||
996 | |||
997 | err = qlcnic_issue_cmd(adapter, cmd); | ||
998 | return err; | ||
999 | } | ||
1000 | |||
1001 | static int qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info *vf, | ||
1002 | struct qlcnic_cmd_args *cmd) | ||
1003 | { | ||
1004 | if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id) | ||
1005 | return -EINVAL; | ||
1006 | |||
1007 | if (!(cmd->req.arg[1] & BIT_8)) | ||
1008 | return -EINVAL; | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int qlcnic_sriov_pf_linkevent_cmd(struct qlcnic_bc_trans *trans, | ||
1014 | struct qlcnic_cmd_args *cmd) | ||
1015 | { | ||
1016 | struct qlcnic_vf_info *vf = trans->vf; | ||
1017 | struct qlcnic_adapter *adapter = vf->adapter; | ||
1018 | int err; | ||
1019 | |||
1020 | err = qlcnic_sriov_validate_linkevent(vf, cmd); | ||
1021 | if (err) { | ||
1022 | cmd->rsp.arg[0] |= (0x6 << 25); | ||
1023 | return err; | ||
1024 | } | ||
1025 | |||
1026 | err = qlcnic_issue_cmd(adapter, cmd); | ||
1027 | return err; | ||
1028 | } | ||
1029 | |||
1030 | static int qlcnic_sriov_pf_cfg_promisc_cmd(struct qlcnic_bc_trans *trans, | ||
1031 | struct qlcnic_cmd_args *cmd) | ||
1032 | { | ||
1033 | struct qlcnic_vf_info *vf = trans->vf; | ||
1034 | struct qlcnic_adapter *adapter = vf->adapter; | ||
1035 | int err; | ||
1036 | |||
1037 | cmd->req.arg[1] |= vf->vp->handle << 16; | ||
1038 | cmd->req.arg[1] |= BIT_31; | ||
1039 | err = qlcnic_issue_cmd(adapter, cmd); | ||
1040 | return err; | ||
1041 | } | ||
1042 | |||
1043 | static const int qlcnic_pf_passthru_supp_cmds[] = { | ||
1044 | QLCNIC_CMD_GET_STATISTICS, | ||
1045 | QLCNIC_CMD_GET_PORT_CONFIG, | ||
1046 | QLCNIC_CMD_GET_LINK_STATUS, | ||
1047 | }; | ||
1048 | |||
545 | static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = { | 1049 | static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = { |
546 | [QLCNIC_BC_CMD_CHANNEL_INIT] = {&qlcnic_sriov_pf_channel_cfg_cmd}, | 1050 | [QLCNIC_BC_CMD_CHANNEL_INIT] = {&qlcnic_sriov_pf_channel_cfg_cmd}, |
547 | [QLCNIC_BC_CMD_CHANNEL_TERM] = {&qlcnic_sriov_pf_channel_cfg_cmd}, | 1051 | [QLCNIC_BC_CMD_CHANNEL_TERM] = {&qlcnic_sriov_pf_channel_cfg_cmd}, |
548 | }; | 1052 | }; |
549 | 1053 | ||
1054 | static const struct qlcnic_sriov_fw_cmd_handler qlcnic_pf_fw_cmd_hdlr[] = { | ||
1055 | {QLCNIC_CMD_CREATE_RX_CTX, qlcnic_sriov_pf_create_rx_ctx_cmd}, | ||
1056 | {QLCNIC_CMD_CREATE_TX_CTX, qlcnic_sriov_pf_create_tx_ctx_cmd}, | ||
1057 | {QLCNIC_CMD_MAC_ADDRESS, qlcnic_sriov_pf_mac_address_cmd}, | ||
1058 | {QLCNIC_CMD_DESTROY_RX_CTX, qlcnic_sriov_pf_del_rx_ctx_cmd}, | ||
1059 | {QLCNIC_CMD_DESTROY_TX_CTX, qlcnic_sriov_pf_del_tx_ctx_cmd}, | ||
1060 | {QLCNIC_CMD_CONFIGURE_HW_LRO, qlcnic_sriov_pf_cfg_lro_cmd}, | ||
1061 | {QLCNIC_CMD_CONFIGURE_IP_ADDR, qlcnic_sriov_pf_cfg_ip_cmd}, | ||
1062 | {QLCNIC_CMD_CONFIG_INTRPT, qlcnic_sriov_pf_cfg_intrpt_cmd}, | ||
1063 | {QLCNIC_CMD_SET_MTU, qlcnic_sriov_pf_set_mtu_cmd}, | ||
1064 | {QLCNIC_CMD_GET_NIC_INFO, qlcnic_sriov_pf_get_nic_info_cmd}, | ||
1065 | {QLCNIC_CMD_CONFIGURE_RSS, qlcnic_sriov_pf_cfg_rss_cmd}, | ||
1066 | {QLCNIC_CMD_CONFIG_INTR_COAL, qlcnic_sriov_pf_cfg_intrcoal_cmd}, | ||
1067 | {QLCNIC_CMD_CONFIG_MAC_VLAN, qlcnic_sriov_pf_cfg_macvlan_cmd}, | ||
1068 | {QLCNIC_CMD_GET_LINK_EVENT, qlcnic_sriov_pf_linkevent_cmd}, | ||
1069 | {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, qlcnic_sriov_pf_cfg_promisc_cmd}, | ||
1070 | }; | ||
1071 | |||
550 | void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *adapter, | 1072 | void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *adapter, |
551 | struct qlcnic_bc_trans *trans, | 1073 | struct qlcnic_bc_trans *trans, |
552 | struct qlcnic_cmd_args *cmd) | 1074 | struct qlcnic_cmd_args *cmd) |
@@ -561,7 +1083,94 @@ void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *adapter, | |||
561 | qlcnic_pf_bc_cmd_hdlr[cmd_op].fn(trans, cmd); | 1083 | qlcnic_pf_bc_cmd_hdlr[cmd_op].fn(trans, cmd); |
562 | return; | 1084 | return; |
563 | } | 1085 | } |
1086 | } else { | ||
1087 | int i; | ||
1088 | size = ARRAY_SIZE(qlcnic_pf_fw_cmd_hdlr); | ||
1089 | for (i = 0; i < size; i++) { | ||
1090 | if (cmd_op == qlcnic_pf_fw_cmd_hdlr[i].cmd) { | ||
1091 | qlcnic_pf_fw_cmd_hdlr[i].fn(trans, cmd); | ||
1092 | return; | ||
1093 | } | ||
1094 | } | ||
1095 | |||
1096 | size = ARRAY_SIZE(qlcnic_pf_passthru_supp_cmds); | ||
1097 | for (i = 0; i < size; i++) { | ||
1098 | if (cmd_op == qlcnic_pf_passthru_supp_cmds[i]) { | ||
1099 | qlcnic_issue_cmd(adapter, cmd); | ||
1100 | return; | ||
1101 | } | ||
1102 | } | ||
564 | } | 1103 | } |
565 | 1104 | ||
566 | cmd->rsp.arg[0] |= (0x9 << 25); | 1105 | cmd->rsp.arg[0] |= (0x9 << 25); |
567 | } | 1106 | } |
1107 | |||
1108 | void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter, | ||
1109 | u32 *int_id) | ||
1110 | { | ||
1111 | u16 vpid; | ||
1112 | |||
1113 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1114 | adapter->ahw->pci_func); | ||
1115 | *int_id |= vpid; | ||
1116 | } | ||
1117 | |||
1118 | void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter, | ||
1119 | u32 *int_id) | ||
1120 | { | ||
1121 | u16 vpid; | ||
1122 | |||
1123 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1124 | adapter->ahw->pci_func); | ||
1125 | *int_id |= vpid << 16; | ||
1126 | } | ||
1127 | |||
1128 | void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter, | ||
1129 | u32 *int_id) | ||
1130 | { | ||
1131 | int vpid; | ||
1132 | |||
1133 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1134 | adapter->ahw->pci_func); | ||
1135 | *int_id |= vpid << 16; | ||
1136 | } | ||
1137 | |||
1138 | void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter, | ||
1139 | u32 *int_id) | ||
1140 | { | ||
1141 | u16 vpid; | ||
1142 | |||
1143 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1144 | adapter->ahw->pci_func); | ||
1145 | *int_id |= vpid << 16; | ||
1146 | } | ||
1147 | |||
1148 | void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, | ||
1149 | u32 *int_id) | ||
1150 | { | ||
1151 | u16 vpid; | ||
1152 | |||
1153 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1154 | adapter->ahw->pci_func); | ||
1155 | *int_id |= (vpid << 16) | BIT_31; | ||
1156 | } | ||
1157 | |||
1158 | void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, | ||
1159 | u32 *int_id) | ||
1160 | { | ||
1161 | u16 vpid; | ||
1162 | |||
1163 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1164 | adapter->ahw->pci_func); | ||
1165 | *int_id |= (vpid << 16) | BIT_31; | ||
1166 | } | ||
1167 | |||
1168 | void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, | ||
1169 | u32 *int_id) | ||
1170 | { | ||
1171 | u16 vpid; | ||
1172 | |||
1173 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, | ||
1174 | adapter->ahw->pci_func); | ||
1175 | *int_id |= (vpid << 16) | BIT_31; | ||
1176 | } | ||