Skip to content

Commit 3d895e4

Browse files
committed
Merge branch 'master' into backport_ubuntu_16.04.2_4.4.0-62-generic
2 parents c95b9a8 + 9ee89b0 commit 3d895e4

File tree

5 files changed

+183
-27
lines changed

5 files changed

+183
-27
lines changed

linux/switchtec.h

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#define SWITCHTEC_EVENT_EN_CLI BIT(2)
3333
#define SWITCHTEC_EVENT_EN_IRQ BIT(3)
3434
#define SWITCHTEC_EVENT_FATAL BIT(4)
35+
#define SWITCHTEC_EVENT_NOT_SUPP BIT(31)
3536

3637
#define SWITCHTEC_DMA_MRPC_EN BIT(0)
3738

@@ -137,17 +138,21 @@ enum {
137138
};
138139

139140
enum {
140-
SWITCHTEC_GEN4_BL2_0_RUNNING = 0x01,
141-
SWITCHTEC_GEN4_BL2_1_RUNNING = 0x02,
142-
SWITCHTEC_GEN4_MAP0_RUNNING = 0x03,
143-
SWITCHTEC_GEN4_MAP1_RUNNING = 0x04,
144-
SWITCHTEC_GEN4_CFG0_RUNNING = 0x05,
145-
SWITCHTEC_GEN4_CFG1_RUNNING = 0x06,
146-
SWITCHTEC_GEN4_IMG0_RUNNING = 0x07,
147-
SWITCHTEC_GEN4_IMG1_RUNNING = 0x08,
141+
SWITCHTEC_GEN4_MAP0_RUNNING = 0x00,
142+
SWITCHTEC_GEN4_MAP1_RUNNING = 0x01,
143+
SWITCHTEC_GEN4_KEY0_RUNNING = 0x02,
144+
SWITCHTEC_GEN4_KEY1_RUNNING = 0x03,
145+
SWITCHTEC_GEN4_BL2_0_RUNNING = 0x04,
146+
SWITCHTEC_GEN4_BL2_1_RUNNING = 0x05,
147+
SWITCHTEC_GEN4_CFG0_RUNNING = 0x06,
148+
SWITCHTEC_GEN4_CFG1_RUNNING = 0x07,
149+
SWITCHTEC_GEN4_IMG0_RUNNING = 0x08,
150+
SWITCHTEC_GEN4_IMG1_RUNNING = 0x09,
148151
};
149152

150153
enum {
154+
SWITCHTEC_GEN4_KEY0_ACTIVE = 0,
155+
SWITCHTEC_GEN4_KEY1_ACTIVE = 1,
151156
SWITCHTEC_GEN4_BL2_0_ACTIVE = 0,
152157
SWITCHTEC_GEN4_BL2_1_ACTIVE = 1,
153158
SWITCHTEC_GEN4_CFG0_ACTIVE = 0,
@@ -186,32 +191,32 @@ struct sys_info_regs_gen4 {
186191
u8 mrpc_inband_ver;
187192
u32 reserved3[7];
188193
u32 fw_update_tmo;
189-
u32 table_version_cfg;
190-
u32 table_version_img;
194+
u32 xml_version_cfg;
195+
u32 xml_version_img;
191196
u32 partition_id;
192197
u16 bl2_running;
193198
u16 cfg_running;
194199
u16 img_running;
195-
u16 reserved4;
196-
u32 reserved5[43];
200+
u16 key_running;
201+
u32 reserved4[43];
197202
u32 vendor_seeprom_twi;
198203
u32 vendor_table_revision;
199204
u32 vendor_specific_info[2];
200205
u16 p2p_vendor_id;
201206
u16 p2p_device_id;
202207
u8 p2p_revision_id;
203-
u8 reserved6[3];
208+
u8 reserved5[3];
204209
u32 p2p_class_id;
205210
u16 subsystem_vendor_id;
206211
u16 subsystem_id;
207212
u32 p2p_serial_number[2];
208213
u8 mac_addr[6];
209-
u8 reserved7[2];
210-
u32 reserved8[3];
214+
u8 reserved6[2];
215+
u32 reserved7[3];
211216
char vendor_id[8];
212217
char product_id[24];
213218
char product_revision[2];
214-
u16 reserved9;
219+
u16 reserved8;
215220
} __packed;
216221

217222
struct sys_info_regs {
@@ -260,16 +265,17 @@ struct flash_info_regs_gen4 {
260265
unsigned char bl2;
261266
unsigned char cfg;
262267
unsigned char img;
263-
unsigned char reserved;
268+
unsigned char key;
264269
} active_flag;
265270

266271
u32 reserved[3];
267272

268-
struct partition_info bl1;
269-
struct partition_info bl2_0;
270-
struct partition_info bl2_1;
271273
struct partition_info map0;
272274
struct partition_info map1;
275+
struct partition_info key0;
276+
struct partition_info key1;
277+
struct partition_info bl2_0;
278+
struct partition_info bl2_1;
273279
struct partition_info cfg0;
274280
struct partition_info cfg1;
275281
struct partition_info img0;

linux/switchtec_ioctl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@
3434
#define SWITCHTEC_IOCTL_PART_VENDOR7 12
3535
#define SWITCHTEC_IOCTL_PART_BL2_0 13
3636
#define SWITCHTEC_IOCTL_PART_BL2_1 14
37+
#define SWITCHTEC_IOCTL_PART_MAP_0 15
38+
#define SWITCHTEC_IOCTL_PART_MAP_1 16
39+
#define SWITCHTEC_IOCTL_PART_KEY_0 17
40+
#define SWITCHTEC_IOCTL_PART_KEY_1 18
3741

3842
#define SWITCHTEC_NUM_PARTITIONS_GEN3 13
39-
#define SWITCHTEC_NUM_PARTITIONS_GEN4 15
43+
#define SWITCHTEC_NUM_PARTITIONS_GEN4 19
4044

4145
struct switchtec_ioctl_flash_info {
4246
__u64 flash_length;

ntb_hw_switchtec.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static int switchtec_ntb_mw_set_trans(struct ntb_dev *ntb, int idx,
396396
if (rc)
397397
return rc;
398398

399-
if (addr == 0 || size == 0) {
399+
if (size == 0) {
400400
if (idx < nr_direct_mw)
401401
switchtec_ntb_mw_clr_direct(sndev, idx);
402402
else
@@ -434,9 +434,19 @@ static void switchtec_ntb_part_link_speed(struct switchtec_ntb *sndev,
434434
enum ntb_width *width)
435435
{
436436
struct switchtec_dev *stdev = sndev->stdev;
437+
u32 pff;
438+
u32 linksta;
439+
440+
pff = ioread32(&stdev->mmio_part_cfg_all[partition].vep_pff_inst_id);
441+
if (pff == 0xFFFFFFFF) {
442+
dev_warn(&sndev->stdev->dev,
443+
"Invalid pff, setting speed/width to 0");
444+
*speed = 0;
445+
*width = 0;
446+
return;
447+
}
437448

438-
u32 pff = ioread32(&stdev->mmio_part_cfg[partition].vep_pff_inst_id);
439-
u32 linksta = ioread32(&stdev->mmio_pff_csr[pff].pci_cap_region[13]);
449+
linksta = ioread32(&stdev->mmio_pff_csr[pff].pci_cap_region[13]);
440450

441451
if (speed)
442452
*speed = (linksta >> 16) & 0xF;
@@ -853,6 +863,7 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
853863
tpart_vec |= ioread32(&sndev->mmio_ntb->ntp_info[self].target_part_low);
854864

855865
part_map = ioread64(&sndev->mmio_ntb->ep_map);
866+
tpart_vec &= part_map;
856867
part_map &= ~(1 << sndev->self_partition);
857868

858869
if (!tpart_vec) {
@@ -877,7 +888,7 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
877888
}
878889

879890
sndev->peer_partition = __ffs64(tpart_vec);
880-
if (!(part_map & (1 << sndev->peer_partition))) {
891+
if (!(part_map & (1ULL << sndev->peer_partition))) {
881892
dev_err(&sndev->stdev->dev,
882893
"ntb target partition is not NT partition\n");
883894
return -ENODEV;

switchtec.c

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/poll.h>
2626
#include <linux/wait.h>
2727
#include <linux/io-64-nonatomic-lo-hi.h>
28+
#include <linux/aer.h>
2829

2930
#include "version.h"
3031
MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
@@ -705,6 +706,26 @@ static int flash_part_info_gen4(struct switchtec_dev *stdev,
705706
struct active_partition_info_gen4 __iomem *af = &fi->active_flag;
706707

707708
switch (info->flash_partition) {
709+
case SWITCHTEC_IOCTL_PART_MAP_0:
710+
set_fw_info_part(info, &fi->map0);
711+
break;
712+
case SWITCHTEC_IOCTL_PART_MAP_1:
713+
set_fw_info_part(info, &fi->map1);
714+
break;
715+
case SWITCHTEC_IOCTL_PART_KEY_0:
716+
set_fw_info_part(info, &fi->key0);
717+
if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY0_ACTIVE)
718+
info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
719+
if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY0_RUNNING)
720+
info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
721+
break;
722+
case SWITCHTEC_IOCTL_PART_KEY_1:
723+
set_fw_info_part(info, &fi->key1);
724+
if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY1_ACTIVE)
725+
info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
726+
if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY1_RUNNING)
727+
info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
728+
break;
708729
case SWITCHTEC_IOCTL_PART_BL2_0:
709730
set_fw_info_part(info, &fi->bl2_0);
710731
if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_0_ACTIVE)
@@ -947,6 +968,9 @@ static int event_ctl(struct switchtec_dev *stdev,
947968
return PTR_ERR(reg);
948969

949970
hdr = ioread32(reg);
971+
if (hdr & SWITCHTEC_EVENT_NOT_SUPP)
972+
return -ENOTSUPP;
973+
950974
for (i = 0; i < ARRAY_SIZE(ctl->data); i++)
951975
ctl->data[i] = ioread32(&reg[i + 1]);
952976

@@ -1019,7 +1043,7 @@ static int ioctl_event_ctl(struct switchtec_dev *stdev,
10191043
for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
10201044
ctl.flags = event_flags;
10211045
ret = event_ctl(stdev, &ctl);
1022-
if (ret < 0)
1046+
if (ret < 0 && ret != -ENOTSUPP)
10231047
return ret;
10241048
}
10251049
} else {
@@ -1324,6 +1348,9 @@ static int mask_event(struct switchtec_dev *stdev, int eid, int idx)
13241348
hdr_reg = event_regs[eid].map_reg(stdev, off, idx);
13251349
hdr = ioread32(hdr_reg);
13261350

1351+
if (hdr & SWITCHTEC_EVENT_NOT_SUPP)
1352+
return 0;
1353+
13271354
if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))
13281355
return 0;
13291356

@@ -1662,6 +1689,8 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
16621689
goto err_devadd;
16631690

16641691
dev_info(&stdev->dev, "Management device registered.\n");
1692+
pci_enable_pcie_error_reporting(pdev);
1693+
pci_save_state(pdev);
16651694

16661695
return 0;
16671696

@@ -1688,6 +1717,111 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
16881717
put_device(&stdev->dev);
16891718
}
16901719

1720+
static void switchtec_pci_disable(struct pci_dev *pdev)
1721+
{
1722+
struct switchtec_dev *stdev = pci_get_drvdata(pdev);
1723+
1724+
if (pci_is_enabled(pdev)) {
1725+
pci_disable_pcie_error_reporting(pdev);
1726+
pci_disable_device(pdev);
1727+
}
1728+
1729+
stdev_kill(stdev);
1730+
}
1731+
1732+
static pci_ers_result_t switchtec_pci_error_detected(struct pci_dev *pdev,
1733+
pci_channel_state_t state)
1734+
{
1735+
struct switchtec_dev *stdev = pci_get_drvdata(pdev);
1736+
1737+
/*
1738+
* A frozen channel requires a reset. When detected, this method
1739+
* will disable the device. The device will be restarted
1740+
* after the slot reset through driver's slot_reset callback.
1741+
*/
1742+
switch (state) {
1743+
case pci_channel_io_normal:
1744+
return PCI_ERS_RESULT_CAN_RECOVER;
1745+
case pci_channel_io_frozen:
1746+
switchtec_pci_disable(pdev);
1747+
dev_info(&stdev->dev, "frozen state error detected - reset needed\n");
1748+
return PCI_ERS_RESULT_NEED_RESET;
1749+
case pci_channel_io_perm_failure:
1750+
switchtec_pci_disable(pdev);
1751+
dev_info(&stdev->dev, "failure state error detected - request disconnect\n");
1752+
return PCI_ERS_RESULT_DISCONNECT;
1753+
}
1754+
return PCI_ERS_RESULT_NEED_RESET;
1755+
}
1756+
1757+
static pci_ers_result_t switchtec_pci_slot_reset(struct pci_dev *pdev)
1758+
{
1759+
struct switchtec_dev *stdev = pci_get_drvdata(pdev);
1760+
int rc;
1761+
unsigned long res_start, res_len;
1762+
1763+
dev_info(&stdev->dev, "slot_reset.\n");
1764+
1765+
pci_restore_state(pdev);
1766+
1767+
/*
1768+
* First, release PCI resources and memory regions
1769+
*/
1770+
if (stdev->dma_mrpc){
1771+
iowrite32(0, &stdev->mmio_mrpc->dma_en);
1772+
flush_wc_buf(stdev);
1773+
writeq(0, &stdev->mmio_mrpc->dma_addr);
1774+
dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
1775+
stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
1776+
}
1777+
1778+
res_start = pci_resource_start(pdev, 0);
1779+
res_len = pci_resource_len(pdev, 0);
1780+
1781+
devm_release_mem_region(&pdev->dev, res_start, res_len);
1782+
1783+
/*
1784+
* Second, reinitialize PCI resources, remap memory regions and reenable events.
1785+
*/
1786+
rc = switchtec_init_pci(stdev, pdev);
1787+
if (rc) {
1788+
dev_err(&stdev->dev, "failed to reinitialize pci.\n");
1789+
goto err_ret;
1790+
}
1791+
1792+
iowrite32(SWITCHTEC_EVENT_CLEAR |
1793+
SWITCHTEC_EVENT_EN_IRQ,
1794+
&stdev->mmio_part_cfg->mrpc_comp_hdr);
1795+
enable_link_state_events(stdev);
1796+
1797+
if (stdev->dma_mrpc)
1798+
enable_dma_mrpc(stdev);
1799+
1800+
stdev->alive = true;
1801+
stdev->mrpc_busy = 0;
1802+
1803+
pci_enable_pcie_error_reporting(pdev);
1804+
pci_save_state(pdev);
1805+
1806+
return PCI_ERS_RESULT_RECOVERED;
1807+
err_ret:
1808+
return PCI_ERS_RESULT_DISCONNECT;
1809+
}
1810+
1811+
static void switchtec_pci_error_resume(struct pci_dev *pdev)
1812+
{
1813+
struct switchtec_dev *stdev = pci_get_drvdata(pdev);
1814+
1815+
dev_info(&stdev->dev, "resume.\n");
1816+
pci_cleanup_aer_uncorrect_error_status(pdev);
1817+
}
1818+
1819+
static const struct pci_error_handlers switchtec_pci_err_handler = {
1820+
.error_detected = switchtec_pci_error_detected,
1821+
.slot_reset = switchtec_pci_slot_reset,
1822+
.resume = switchtec_pci_error_resume,
1823+
};
1824+
16911825
#define SWITCHTEC_PCI_DEVICE(device_id, gen) \
16921826
{ \
16931827
.vendor = MICROSEMI_VENDOR_ID, \
@@ -1766,6 +1900,7 @@ static struct pci_driver switchtec_pci_driver = {
17661900
.id_table = switchtec_pci_tbl,
17671901
.probe = switchtec_pci_probe,
17681902
.remove = switchtec_pci_remove,
1903+
.err_handler = &switchtec_pci_err_handler,
17691904
};
17701905

17711906
static int __init switchtec_init(void)

version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.3
1+
1.4

0 commit comments

Comments
 (0)