aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-04-16 22:34:40 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-16 22:34:40 -0400
commitefde611b0afa47e64f2a329f4430830b91d77ea2 (patch)
tree6065a2d9bfe45518f6f8ce4e4425fc2460a70b22
parent7a7c1705dc6c629e3b1dce1c0c1ecc0af87486ac (diff)
parent3d780b926a12dd798417446d733d457f1be1cc73 (diff)
Merge branch 'nfp-next'
Jakub Kicinski says ==================== nfp: cleanups and improvements Main purpose of this set is to get rid of doing potentially long mdelay()s but it also contains some trivial changes I've accumulated. First two patches fix harmless copy-paste errors, next two clean up the documentation and remove unused defines. Patch 5 clarifies the interpretation of RX descriptor fields. Patch 6, by far the biggest, adds ability to perform FW reconfig asynchronously thanks to which we can stop using mdelay(). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h12
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c198
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h10
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c4
4 files changed, 176 insertions, 48 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 3d53fcf323eb..e744acc18ef4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -59,8 +59,8 @@
59 netdev_warn((nn)->netdev, fmt, ## args); \ 59 netdev_warn((nn)->netdev, fmt, ## args); \
60 } while (0) 60 } while (0)
61 61
62/* Max time to wait for NFP to respond on updates (in ms) */ 62/* Max time to wait for NFP to respond on updates (in seconds) */
63#define NFP_NET_POLL_TIMEOUT 5000 63#define NFP_NET_POLL_TIMEOUT 5
64 64
65/* Bar allocation */ 65/* Bar allocation */
66#define NFP_NET_CRTL_BAR 0 66#define NFP_NET_CRTL_BAR 0
@@ -447,6 +447,10 @@ static inline bool nfp_net_fw_ver_eq(struct nfp_net_fw_version *fw_ver,
447 * @shared_name: Name for shared interrupt 447 * @shared_name: Name for shared interrupt
448 * @me_freq_mhz: ME clock_freq (MHz) 448 * @me_freq_mhz: ME clock_freq (MHz)
449 * @reconfig_lock: Protects HW reconfiguration request regs/machinery 449 * @reconfig_lock: Protects HW reconfiguration request regs/machinery
450 * @reconfig_posted: Pending reconfig bits coming from async sources
451 * @reconfig_timer_active: Timer for reading reconfiguration results is pending
452 * @reconfig_sync_present: Some thread is performing synchronous reconfig
453 * @reconfig_timer: Timer for async reading of reconfig results
450 * @link_up: Is the link up? 454 * @link_up: Is the link up?
451 * @link_status_lock: Protects @link_up and ensures atomicity with BAR reading 455 * @link_status_lock: Protects @link_up and ensures atomicity with BAR reading
452 * @rx_coalesce_usecs: RX interrupt moderation usecs delay parameter 456 * @rx_coalesce_usecs: RX interrupt moderation usecs delay parameter
@@ -531,6 +535,10 @@ struct nfp_net {
531 spinlock_t link_status_lock; 535 spinlock_t link_status_lock;
532 536
533 spinlock_t reconfig_lock; 537 spinlock_t reconfig_lock;
538 u32 reconfig_posted;
539 bool reconfig_timer_active;
540 bool reconfig_sync_present;
541 struct timer_list reconfig_timer;
534 542
535 u32 rx_coalesce_usecs; 543 u32 rx_coalesce_usecs;
536 u32 rx_coalesce_max_frames; 544 u32 rx_coalesce_max_frames;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 0bdff390c958..fa47c14c743a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -80,6 +80,116 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
80 put_unaligned_le32(reg, fw_ver); 80 put_unaligned_le32(reg, fw_ver);
81} 81}
82 82
83/* Firmware reconfig
84 *
85 * Firmware reconfig may take a while so we have two versions of it -
86 * synchronous and asynchronous (posted). All synchronous callers are holding
87 * RTNL so we don't have to worry about serializing them.
88 */
89static void nfp_net_reconfig_start(struct nfp_net *nn, u32 update)
90{
91 nn_writel(nn, NFP_NET_CFG_UPDATE, update);
92 /* ensure update is written before pinging HW */
93 nn_pci_flush(nn);
94 nfp_qcp_wr_ptr_add(nn->qcp_cfg, 1);
95}
96
97/* Pass 0 as update to run posted reconfigs. */
98static void nfp_net_reconfig_start_async(struct nfp_net *nn, u32 update)
99{
100 update |= nn->reconfig_posted;
101 nn->reconfig_posted = 0;
102
103 nfp_net_reconfig_start(nn, update);
104
105 nn->reconfig_timer_active = true;
106 mod_timer(&nn->reconfig_timer, jiffies + NFP_NET_POLL_TIMEOUT * HZ);
107}
108
109static bool nfp_net_reconfig_check_done(struct nfp_net *nn, bool last_check)
110{
111 u32 reg;
112
113 reg = nn_readl(nn, NFP_NET_CFG_UPDATE);
114 if (reg == 0)
115 return true;
116 if (reg & NFP_NET_CFG_UPDATE_ERR) {
117 nn_err(nn, "Reconfig error: 0x%08x\n", reg);
118 return true;
119 } else if (last_check) {
120 nn_err(nn, "Reconfig timeout: 0x%08x\n", reg);
121 return true;
122 }
123
124 return false;
125}
126
127static int nfp_net_reconfig_wait(struct nfp_net *nn, unsigned long deadline)
128{
129 bool timed_out = false;
130
131 /* Poll update field, waiting for NFP to ack the config */
132 while (!nfp_net_reconfig_check_done(nn, timed_out)) {
133 msleep(1);
134 timed_out = time_is_before_eq_jiffies(deadline);
135 }
136
137 if (nn_readl(nn, NFP_NET_CFG_UPDATE) & NFP_NET_CFG_UPDATE_ERR)
138 return -EIO;
139
140 return timed_out ? -EIO : 0;
141}
142
143static void nfp_net_reconfig_timer(unsigned long data)
144{
145 struct nfp_net *nn = (void *)data;
146
147 spin_lock_bh(&nn->reconfig_lock);
148
149 nn->reconfig_timer_active = false;
150
151 /* If sync caller is present it will take over from us */
152 if (nn->reconfig_sync_present)
153 goto done;
154
155 /* Read reconfig status and report errors */
156 nfp_net_reconfig_check_done(nn, true);
157
158 if (nn->reconfig_posted)
159 nfp_net_reconfig_start_async(nn, 0);
160done:
161 spin_unlock_bh(&nn->reconfig_lock);
162}
163
164/**
165 * nfp_net_reconfig_post() - Post async reconfig request
166 * @nn: NFP Net device to reconfigure
167 * @update: The value for the update field in the BAR config
168 *
169 * Record FW reconfiguration request. Reconfiguration will be kicked off
170 * whenever reconfiguration machinery is idle. Multiple requests can be
171 * merged together!
172 */
173static void nfp_net_reconfig_post(struct nfp_net *nn, u32 update)
174{
175 spin_lock_bh(&nn->reconfig_lock);
176
177 /* Sync caller will kick off async reconf when it's done, just post */
178 if (nn->reconfig_sync_present) {
179 nn->reconfig_posted |= update;
180 goto done;
181 }
182
183 /* Opportunistically check if the previous command is done */
184 if (!nn->reconfig_timer_active ||
185 nfp_net_reconfig_check_done(nn, false))
186 nfp_net_reconfig_start_async(nn, update);
187 else
188 nn->reconfig_posted |= update;
189done:
190 spin_unlock_bh(&nn->reconfig_lock);
191}
192
83/** 193/**
84 * nfp_net_reconfig() - Reconfigure the firmware 194 * nfp_net_reconfig() - Reconfigure the firmware
85 * @nn: NFP Net device to reconfigure 195 * @nn: NFP Net device to reconfigure
@@ -93,35 +203,45 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
93 */ 203 */
94int nfp_net_reconfig(struct nfp_net *nn, u32 update) 204int nfp_net_reconfig(struct nfp_net *nn, u32 update)
95{ 205{
96 int cnt, ret = 0; 206 bool cancelled_timer = false;
97 u32 new; 207 u32 pre_posted_requests;
208 int ret;
98 209
99 spin_lock_bh(&nn->reconfig_lock); 210 spin_lock_bh(&nn->reconfig_lock);
100 211
101 nn_writel(nn, NFP_NET_CFG_UPDATE, update); 212 nn->reconfig_sync_present = true;
102 /* ensure update is written before pinging HW */
103 nn_pci_flush(nn);
104 nfp_qcp_wr_ptr_add(nn->qcp_cfg, 1);
105 213
106 /* Poll update field, waiting for NFP to ack the config */ 214 if (nn->reconfig_timer_active) {
107 for (cnt = 0; ; cnt++) { 215 del_timer(&nn->reconfig_timer);
108 new = nn_readl(nn, NFP_NET_CFG_UPDATE); 216 nn->reconfig_timer_active = false;
109 if (new == 0) 217 cancelled_timer = true;
110 break; 218 }
111 if (new & NFP_NET_CFG_UPDATE_ERR) { 219 pre_posted_requests = nn->reconfig_posted;
112 nn_err(nn, "Reconfig error: 0x%08x\n", new); 220 nn->reconfig_posted = 0;
113 ret = -EIO; 221
114 break; 222 spin_unlock_bh(&nn->reconfig_lock);
115 } else if (cnt >= NFP_NET_POLL_TIMEOUT) { 223
116 nn_err(nn, "Reconfig timeout for 0x%08x after %dms\n", 224 if (cancelled_timer)
117 update, cnt); 225 nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires);
118 ret = -EIO; 226
119 break; 227 /* Run the posted reconfigs which were issued before we started */
120 } 228 if (pre_posted_requests) {
121 mdelay(1); 229 nfp_net_reconfig_start(nn, pre_posted_requests);
230 nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
122 } 231 }
123 232
233 nfp_net_reconfig_start(nn, update);
234 ret = nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
235
236 spin_lock_bh(&nn->reconfig_lock);
237
238 if (nn->reconfig_posted)
239 nfp_net_reconfig_start_async(nn, 0);
240
241 nn->reconfig_sync_present = false;
242
124 spin_unlock_bh(&nn->reconfig_lock); 243 spin_unlock_bh(&nn->reconfig_lock);
244
125 return ret; 245 return ret;
126} 246}
127 247
@@ -1298,23 +1418,25 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
1298 1418
1299 nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr); 1419 nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr);
1300 1420
1421 /* < meta_len >
1422 * <-- [rx_offset] -->
1423 * ---------------------------------------------------------
1424 * | [XX] | metadata | packet | XXXX |
1425 * ---------------------------------------------------------
1426 * <---------------- data_len --------------->
1427 *
1428 * The rx_offset is fixed for all packets, the meta_len can vary
1429 * on a packet by packet basis. If rx_offset is set to zero
1430 * (_RX_OFFSET_DYNAMIC) metadata starts at the beginning of the
1431 * buffer and is immediately followed by the packet (no [XX]).
1432 */
1301 meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK; 1433 meta_len = rxd->rxd.meta_len_dd & PCIE_DESC_RX_META_LEN_MASK;
1302 data_len = le16_to_cpu(rxd->rxd.data_len); 1434 data_len = le16_to_cpu(rxd->rxd.data_len);
1303 1435
1304 if (WARN_ON_ONCE(data_len > nn->fl_bufsz)) { 1436 if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
1305 dev_kfree_skb_any(skb);
1306 continue;
1307 }
1308
1309 if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) {
1310 /* The packet data starts after the metadata */
1311 skb_reserve(skb, meta_len); 1437 skb_reserve(skb, meta_len);
1312 } else { 1438 else
1313 /* The packet data starts at a fixed offset */
1314 skb_reserve(skb, nn->rx_offset); 1439 skb_reserve(skb, nn->rx_offset);
1315 }
1316
1317 /* Adjust the SKB for the dynamic meta data pre-pended */
1318 skb_put(skb, data_len - meta_len); 1440 skb_put(skb, data_len - meta_len);
1319 1441
1320 nfp_net_set_hash(nn->netdev, skb, rxd); 1442 nfp_net_set_hash(nn->netdev, skb, rxd);
@@ -2094,8 +2216,7 @@ static void nfp_net_set_rx_mode(struct net_device *netdev)
2094 return; 2216 return;
2095 2217
2096 nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl); 2218 nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl);
2097 if (nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN)) 2219 nfp_net_reconfig_post(nn, NFP_NET_CFG_UPDATE_GEN);
2098 return;
2099 2220
2100 nn->ctrl = new_ctrl; 2221 nn->ctrl = new_ctrl;
2101} 2222}
@@ -2403,7 +2524,7 @@ static void nfp_net_set_vxlan_port(struct nfp_net *nn, int idx, __be16 port)
2403 be16_to_cpu(nn->vxlan_ports[i + 1]) << 16 | 2524 be16_to_cpu(nn->vxlan_ports[i + 1]) << 16 |
2404 be16_to_cpu(nn->vxlan_ports[i])); 2525 be16_to_cpu(nn->vxlan_ports[i]));
2405 2526
2406 nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VXLAN); 2527 nfp_net_reconfig_post(nn, NFP_NET_CFG_UPDATE_VXLAN);
2407} 2528}
2408 2529
2409/** 2530/**
@@ -2549,6 +2670,9 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
2549 spin_lock_init(&nn->reconfig_lock); 2670 spin_lock_init(&nn->reconfig_lock);
2550 spin_lock_init(&nn->link_status_lock); 2671 spin_lock_init(&nn->link_status_lock);
2551 2672
2673 setup_timer(&nn->reconfig_timer,
2674 nfp_net_reconfig_timer, (unsigned long)nn);
2675
2552 return nn; 2676 return nn;
2553} 2677}
2554 2678
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index 8692003aeed8..ad6c4e31cedd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -81,14 +81,10 @@
81 81
82/** 82/**
83 * @NFP_NET_TXR_MAX: Maximum number of TX rings 83 * @NFP_NET_TXR_MAX: Maximum number of TX rings
84 * @NFP_NET_TXR_MASK: Mask for TX rings
85 * @NFP_NET_RXR_MAX: Maximum number of RX rings 84 * @NFP_NET_RXR_MAX: Maximum number of RX rings
86 * @NFP_NET_RXR_MASK: Mask for RX rings
87 */ 85 */
88#define NFP_NET_TXR_MAX 64 86#define NFP_NET_TXR_MAX 64
89#define NFP_NET_TXR_MASK (NFP_NET_TXR_MAX - 1)
90#define NFP_NET_RXR_MAX 64 87#define NFP_NET_RXR_MAX 64
91#define NFP_NET_RXR_MASK (NFP_NET_RXR_MAX - 1)
92 88
93/** 89/**
94 * Read/Write config words (0x0000 - 0x002c) 90 * Read/Write config words (0x0000 - 0x002c)
@@ -152,9 +148,9 @@
152 * @NFP_NET_CFG_VERSION: Firmware version number 148 * @NFP_NET_CFG_VERSION: Firmware version number
153 * @NFP_NET_CFG_STS: Status 149 * @NFP_NET_CFG_STS: Status
154 * @NFP_NET_CFG_CAP: Capabilities (same bits as @NFP_NET_CFG_CTRL) 150 * @NFP_NET_CFG_CAP: Capabilities (same bits as @NFP_NET_CFG_CTRL)
155 * @NFP_NET_MAX_TXRINGS: Maximum number of TX rings 151 * @NFP_NET_CFG_MAX_TXRINGS: Maximum number of TX rings
156 * @NFP_NET_MAX_RXRINGS: Maximum number of RX rings 152 * @NFP_NET_CFG_MAX_RXRINGS: Maximum number of RX rings
157 * @NFP_NET_MAX_MTU: Maximum support MTU 153 * @NFP_NET_CFG_MAX_MTU: Maximum support MTU
158 * @NFP_NET_CFG_START_TXQ: Start Queue Control Queue to use for TX (PF only) 154 * @NFP_NET_CFG_START_TXQ: Start Queue Control Queue to use for TX (PF only)
159 * @NFP_NET_CFG_START_RXQ: Start Queue Control Queue to use for RX (PF only) 155 * @NFP_NET_CFG_START_RXQ: Start Queue Control Queue to use for RX (PF only)
160 * 156 *
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
index f86a1f13d27b..f7c9a5bc4aa3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
@@ -187,7 +187,7 @@ static const struct file_operations nfp_tx_q_fops = {
187 187
188void nfp_net_debugfs_adapter_add(struct nfp_net *nn) 188void nfp_net_debugfs_adapter_add(struct nfp_net *nn)
189{ 189{
190 static struct dentry *queues, *tx, *rx; 190 struct dentry *queues, *tx, *rx;
191 char int_name[16]; 191 char int_name[16];
192 int i; 192 int i;
193 193
@@ -200,7 +200,7 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn)
200 200
201 /* Create queue debugging sub-tree */ 201 /* Create queue debugging sub-tree */
202 queues = debugfs_create_dir("queue", nn->debugfs_dir); 202 queues = debugfs_create_dir("queue", nn->debugfs_dir);
203 if (IS_ERR_OR_NULL(nn->debugfs_dir)) 203 if (IS_ERR_OR_NULL(queues))
204 return; 204 return;
205 205
206 rx = debugfs_create_dir("rx", queues); 206 rx = debugfs_create_dir("rx", queues);