aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWesley Sheng <wesley.sheng@microchip.com>2018-12-10 04:12:24 -0500
committerBjorn Helgaas <bhelgaas@google.com>2018-12-13 10:03:32 -0500
commitf7eb7b8a4f72b0d9dea69b09f58185ffab97fd35 (patch)
tree44c8f6a837faf78d53bd2ad0308db0b3a5a2ea7f
parent52d8db8e0cd7c28316514568fe5df0cfd4fa2075 (diff)
switchtec: Add MRPC DMA mode support
MRPC normal mode requires the host to read the MRPC command status and output data from BAR. This results in high latency responses from the Memory Read TLP and potential Completion Timeout (CTO). Add support for MRPC DMA mode, including related macro definitions and data structures and code to: * Retrieve MRPC DMA mode version from adapter firmware * Allocate DMA buffer, register ISR, and enable DMA during init * Check MRPC execution status and get execution results from DMA buffer * Release DMA buffer and disable DMA function when unloading module MRPC DMA mode is a new feature of firmware, and the driver will fall back to MRPC normal mode if there is no support in the legacy firmware. Add a module parameter, "use_dma_mrpc", to select between MRPC DMA mode and MRPC normal mode. Since the driver automatically detects DMA support in the firmware, this parameter is just for debugging and testing. Include <linux/io-64-nonatomic-lo-hi.h> so that readq/writeq is replaced by two readl/writel on systems that do not support it. Signed-off-by: Wesley Sheng <wesley.sheng@microchip.com> [bhelgaas: changelog, simplify dma_ver check] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
-rw-r--r--drivers/pci/switch/switchtec.c108
-rw-r--r--include/linux/switchtec.h16
2 files changed, 114 insertions, 10 deletions
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 0b8862b50ad2..6c5536d3d42a 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -13,7 +13,7 @@
13#include <linux/uaccess.h> 13#include <linux/uaccess.h>
14#include <linux/poll.h> 14#include <linux/poll.h>
15#include <linux/wait.h> 15#include <linux/wait.h>
16 16#include <linux/io-64-nonatomic-lo-hi.h>
17#include <linux/nospec.h> 17#include <linux/nospec.h>
18 18
19MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver"); 19MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
@@ -25,6 +25,11 @@ static int max_devices = 16;
25module_param(max_devices, int, 0644); 25module_param(max_devices, int, 0644);
26MODULE_PARM_DESC(max_devices, "max number of switchtec device instances"); 26MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");
27 27
28static bool use_dma_mrpc = 1;
29module_param(use_dma_mrpc, bool, 0644);
30MODULE_PARM_DESC(use_dma_mrpc,
31 "Enable the use of the DMA MRPC feature");
32
28static dev_t switchtec_devt; 33static dev_t switchtec_devt;
29static DEFINE_IDA(switchtec_minor_ida); 34static DEFINE_IDA(switchtec_minor_ida);
30 35
@@ -141,6 +146,11 @@ static void mrpc_cmd_submit(struct switchtec_dev *stdev)
141 stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, 146 stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
142 list); 147 list);
143 148
149 if (stdev->dma_mrpc) {
150 stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS;
151 memset(stdev->dma_mrpc->data, 0xFF, SWITCHTEC_MRPC_PAYLOAD_SIZE);
152 }
153
144 stuser_set_state(stuser, MRPC_RUNNING); 154 stuser_set_state(stuser, MRPC_RUNNING);
145 stdev->mrpc_busy = 1; 155 stdev->mrpc_busy = 1;
146 memcpy_toio(&stdev->mmio_mrpc->input_data, 156 memcpy_toio(&stdev->mmio_mrpc->input_data,
@@ -180,7 +190,11 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
180 stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, 190 stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
181 list); 191 list);
182 192
183 stuser->status = ioread32(&stdev->mmio_mrpc->status); 193 if (stdev->dma_mrpc)
194 stuser->status = stdev->dma_mrpc->status;
195 else
196 stuser->status = ioread32(&stdev->mmio_mrpc->status);
197
184 if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS) 198 if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
185 return; 199 return;
186 200
@@ -190,13 +204,19 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
190 if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE) 204 if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
191 goto out; 205 goto out;
192 206
193 stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value); 207 if (stdev->dma_mrpc)
208 stuser->return_code = stdev->dma_mrpc->rtn_code;
209 else
210 stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value);
194 if (stuser->return_code != 0) 211 if (stuser->return_code != 0)
195 goto out; 212 goto out;
196 213
197 memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data, 214 if (stdev->dma_mrpc)
198 stuser->read_len); 215 memcpy(stuser->data, &stdev->dma_mrpc->data,
199 216 stuser->read_len);
217 else
218 memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
219 stuser->read_len);
200out: 220out:
201 complete_all(&stuser->comp); 221 complete_all(&stuser->comp);
202 list_del_init(&stuser->list); 222 list_del_init(&stuser->list);
@@ -231,7 +251,10 @@ static void mrpc_timeout_work(struct work_struct *work)
231 251
232 mutex_lock(&stdev->mrpc_mutex); 252 mutex_lock(&stdev->mrpc_mutex);
233 253
234 status = ioread32(&stdev->mmio_mrpc->status); 254 if (stdev->dma_mrpc)
255 status = stdev->dma_mrpc->status;
256 else
257 status = ioread32(&stdev->mmio_mrpc->status);
235 if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) { 258 if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
236 schedule_delayed_work(&stdev->mrpc_timeout, 259 schedule_delayed_work(&stdev->mrpc_timeout,
237 msecs_to_jiffies(500)); 260 msecs_to_jiffies(500));
@@ -239,7 +262,6 @@ static void mrpc_timeout_work(struct work_struct *work)
239 } 262 }
240 263
241 mrpc_complete_cmd(stdev); 264 mrpc_complete_cmd(stdev);
242
243out: 265out:
244 mutex_unlock(&stdev->mrpc_mutex); 266 mutex_unlock(&stdev->mrpc_mutex);
245} 267}
@@ -1030,10 +1052,24 @@ static void enable_link_state_events(struct switchtec_dev *stdev)
1030 } 1052 }
1031} 1053}
1032 1054
1055static void enable_dma_mrpc(struct switchtec_dev *stdev)
1056{
1057 writeq(stdev->dma_mrpc_dma_addr, &stdev->mmio_mrpc->dma_addr);
1058 flush_wc_buf(stdev);
1059 iowrite32(SWITCHTEC_DMA_MRPC_EN, &stdev->mmio_mrpc->dma_en);
1060}
1061
1033static void stdev_release(struct device *dev) 1062static void stdev_release(struct device *dev)
1034{ 1063{
1035 struct switchtec_dev *stdev = to_stdev(dev); 1064 struct switchtec_dev *stdev = to_stdev(dev);
1036 1065
1066 if (stdev->dma_mrpc) {
1067 iowrite32(0, &stdev->mmio_mrpc->dma_en);
1068 flush_wc_buf(stdev);
1069 writeq(0, &stdev->mmio_mrpc->dma_addr);
1070 dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
1071 stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
1072 }
1037 kfree(stdev); 1073 kfree(stdev);
1038} 1074}
1039 1075
@@ -1189,10 +1225,27 @@ static irqreturn_t switchtec_event_isr(int irq, void *dev)
1189 return ret; 1225 return ret;
1190} 1226}
1191 1227
1228
1229static irqreturn_t switchtec_dma_mrpc_isr(int irq, void *dev)
1230{
1231 struct switchtec_dev *stdev = dev;
1232 irqreturn_t ret = IRQ_NONE;
1233
1234 iowrite32(SWITCHTEC_EVENT_CLEAR |
1235 SWITCHTEC_EVENT_EN_IRQ,
1236 &stdev->mmio_part_cfg->mrpc_comp_hdr);
1237 schedule_work(&stdev->mrpc_work);
1238
1239 ret = IRQ_HANDLED;
1240 return ret;
1241}
1242
1192static int switchtec_init_isr(struct switchtec_dev *stdev) 1243static int switchtec_init_isr(struct switchtec_dev *stdev)
1193{ 1244{
1194 int nvecs; 1245 int nvecs;
1195 int event_irq; 1246 int event_irq;
1247 int dma_mrpc_irq;
1248 int rc;
1196 1249
1197 nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, 4, 1250 nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, 4,
1198 PCI_IRQ_MSIX | PCI_IRQ_MSI); 1251 PCI_IRQ_MSIX | PCI_IRQ_MSI);
@@ -1207,9 +1260,29 @@ static int switchtec_init_isr(struct switchtec_dev *stdev)
1207 if (event_irq < 0) 1260 if (event_irq < 0)
1208 return event_irq; 1261 return event_irq;
1209 1262
1210 return devm_request_irq(&stdev->pdev->dev, event_irq, 1263 rc = devm_request_irq(&stdev->pdev->dev, event_irq,
1211 switchtec_event_isr, 0, 1264 switchtec_event_isr, 0,
1212 KBUILD_MODNAME, stdev); 1265 KBUILD_MODNAME, stdev);
1266
1267 if (rc)
1268 return rc;
1269
1270 if (!stdev->dma_mrpc)
1271 return rc;
1272
1273 dma_mrpc_irq = ioread32(&stdev->mmio_mrpc->dma_vector);
1274 if (dma_mrpc_irq < 0 || dma_mrpc_irq >= nvecs)
1275 return -EFAULT;
1276
1277 dma_mrpc_irq = pci_irq_vector(stdev->pdev, dma_mrpc_irq);
1278 if (dma_mrpc_irq < 0)
1279 return dma_mrpc_irq;
1280
1281 rc = devm_request_irq(&stdev->pdev->dev, dma_mrpc_irq,
1282 switchtec_dma_mrpc_isr, 0,
1283 KBUILD_MODNAME, stdev);
1284
1285 return rc;
1213} 1286}
1214 1287
1215static void init_pff(struct switchtec_dev *stdev) 1288static void init_pff(struct switchtec_dev *stdev)
@@ -1294,6 +1367,19 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
1294 1367
1295 pci_set_drvdata(pdev, stdev); 1368 pci_set_drvdata(pdev, stdev);
1296 1369
1370 if (!use_dma_mrpc)
1371 return 0;
1372
1373 if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0)
1374 return 0;
1375
1376 stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev,
1377 sizeof(*stdev->dma_mrpc),
1378 &stdev->dma_mrpc_dma_addr,
1379 GFP_KERNEL);
1380 if (stdev->dma_mrpc == NULL)
1381 return -ENOMEM;
1382
1297 return 0; 1383 return 0;
1298} 1384}
1299 1385
@@ -1325,6 +1411,9 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
1325 &stdev->mmio_part_cfg->mrpc_comp_hdr); 1411 &stdev->mmio_part_cfg->mrpc_comp_hdr);
1326 enable_link_state_events(stdev); 1412 enable_link_state_events(stdev);
1327 1413
1414 if (stdev->dma_mrpc)
1415 enable_dma_mrpc(stdev);
1416
1328 rc = cdev_device_add(&stdev->cdev, &stdev->dev); 1417 rc = cdev_device_add(&stdev->cdev, &stdev->dev);
1329 if (rc) 1418 if (rc)
1330 goto err_devadd; 1419 goto err_devadd;
@@ -1350,7 +1439,6 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
1350 cdev_device_del(&stdev->cdev, &stdev->dev); 1439 cdev_device_del(&stdev->cdev, &stdev->dev);
1351 ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt)); 1440 ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
1352 dev_info(&stdev->dev, "unregistered.\n"); 1441 dev_info(&stdev->dev, "unregistered.\n");
1353
1354 stdev_kill(stdev); 1442 stdev_kill(stdev);
1355 put_device(&stdev->dev); 1443 put_device(&stdev->dev);
1356} 1444}
diff --git a/include/linux/switchtec.h b/include/linux/switchtec.h
index ab400af6f0ce..eee0412bdf4b 100644
--- a/include/linux/switchtec.h
+++ b/include/linux/switchtec.h
@@ -29,6 +29,7 @@
29#define SWITCHTEC_EVENT_EN_IRQ BIT(3) 29#define SWITCHTEC_EVENT_EN_IRQ BIT(3)
30#define SWITCHTEC_EVENT_FATAL BIT(4) 30#define SWITCHTEC_EVENT_FATAL BIT(4)
31 31
32#define SWITCHTEC_DMA_MRPC_EN BIT(0)
32enum { 33enum {
33 SWITCHTEC_GAS_MRPC_OFFSET = 0x0000, 34 SWITCHTEC_GAS_MRPC_OFFSET = 0x0000,
34 SWITCHTEC_GAS_TOP_CFG_OFFSET = 0x1000, 35 SWITCHTEC_GAS_TOP_CFG_OFFSET = 0x1000,
@@ -46,6 +47,10 @@ struct mrpc_regs {
46 u32 cmd; 47 u32 cmd;
47 u32 status; 48 u32 status;
48 u32 ret_value; 49 u32 ret_value;
50 u32 dma_en;
51 u64 dma_addr;
52 u32 dma_vector;
53 u32 dma_ver;
49} __packed; 54} __packed;
50 55
51enum mrpc_status { 56enum mrpc_status {
@@ -342,6 +347,14 @@ struct pff_csr_regs {
342 347
343struct switchtec_ntb; 348struct switchtec_ntb;
344 349
350struct dma_mrpc_output {
351 u32 status;
352 u32 cmd_id;
353 u32 rtn_code;
354 u32 output_size;
355 u8 data[SWITCHTEC_MRPC_PAYLOAD_SIZE];
356};
357
345struct switchtec_dev { 358struct switchtec_dev {
346 struct pci_dev *pdev; 359 struct pci_dev *pdev;
347 struct device dev; 360 struct device dev;
@@ -381,6 +394,9 @@ struct switchtec_dev {
381 u8 link_event_count[SWITCHTEC_MAX_PFF_CSR]; 394 u8 link_event_count[SWITCHTEC_MAX_PFF_CSR];
382 395
383 struct switchtec_ntb *sndev; 396 struct switchtec_ntb *sndev;
397
398 struct dma_mrpc_output *dma_mrpc;
399 dma_addr_t dma_mrpc_dma_addr;
384}; 400};
385 401
386static inline struct switchtec_dev *to_stdev(struct device *dev) 402static inline struct switchtec_dev *to_stdev(struct device *dev)