diff options
Diffstat (limited to 'drivers/misc')
42 files changed, 1168 insertions, 347 deletions
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index 99a04686e45f..7b55f8a152d4 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c | |||
@@ -1185,7 +1185,7 @@ static int bh1770_probe(struct i2c_client *client, | |||
1185 | struct bh1770_chip *chip; | 1185 | struct bh1770_chip *chip; |
1186 | int err; | 1186 | int err; |
1187 | 1187 | ||
1188 | chip = kzalloc(sizeof *chip, GFP_KERNEL); | 1188 | chip = devm_kzalloc(&client->dev, sizeof *chip, GFP_KERNEL); |
1189 | if (!chip) | 1189 | if (!chip) |
1190 | return -ENOMEM; | 1190 | return -ENOMEM; |
1191 | 1191 | ||
@@ -1198,8 +1198,7 @@ static int bh1770_probe(struct i2c_client *client, | |||
1198 | 1198 | ||
1199 | if (client->dev.platform_data == NULL) { | 1199 | if (client->dev.platform_data == NULL) { |
1200 | dev_err(&client->dev, "platform data is mandatory\n"); | 1200 | dev_err(&client->dev, "platform data is mandatory\n"); |
1201 | err = -EINVAL; | 1201 | return -EINVAL; |
1202 | goto fail1; | ||
1203 | } | 1202 | } |
1204 | 1203 | ||
1205 | chip->pdata = client->dev.platform_data; | 1204 | chip->pdata = client->dev.platform_data; |
@@ -1224,24 +1223,24 @@ static int bh1770_probe(struct i2c_client *client, | |||
1224 | chip->regs[0].supply = reg_vcc; | 1223 | chip->regs[0].supply = reg_vcc; |
1225 | chip->regs[1].supply = reg_vleds; | 1224 | chip->regs[1].supply = reg_vleds; |
1226 | 1225 | ||
1227 | err = regulator_bulk_get(&client->dev, | 1226 | err = devm_regulator_bulk_get(&client->dev, |
1228 | ARRAY_SIZE(chip->regs), chip->regs); | 1227 | ARRAY_SIZE(chip->regs), chip->regs); |
1229 | if (err < 0) { | 1228 | if (err < 0) { |
1230 | dev_err(&client->dev, "Cannot get regulators\n"); | 1229 | dev_err(&client->dev, "Cannot get regulators\n"); |
1231 | goto fail1; | 1230 | return err; |
1232 | } | 1231 | } |
1233 | 1232 | ||
1234 | err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), | 1233 | err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), |
1235 | chip->regs); | 1234 | chip->regs); |
1236 | if (err < 0) { | 1235 | if (err < 0) { |
1237 | dev_err(&client->dev, "Cannot enable regulators\n"); | 1236 | dev_err(&client->dev, "Cannot enable regulators\n"); |
1238 | goto fail2; | 1237 | return err; |
1239 | } | 1238 | } |
1240 | 1239 | ||
1241 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); | 1240 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); |
1242 | err = bh1770_detect(chip); | 1241 | err = bh1770_detect(chip); |
1243 | if (err < 0) | 1242 | if (err < 0) |
1244 | goto fail3; | 1243 | goto fail0; |
1245 | 1244 | ||
1246 | /* Start chip */ | 1245 | /* Start chip */ |
1247 | bh1770_chip_on(chip); | 1246 | bh1770_chip_on(chip); |
@@ -1252,14 +1251,14 @@ static int bh1770_probe(struct i2c_client *client, | |||
1252 | if (chip->lux_corr == 0) { | 1251 | if (chip->lux_corr == 0) { |
1253 | dev_err(&client->dev, "Improper correction values\n"); | 1252 | dev_err(&client->dev, "Improper correction values\n"); |
1254 | err = -EINVAL; | 1253 | err = -EINVAL; |
1255 | goto fail3; | 1254 | goto fail0; |
1256 | } | 1255 | } |
1257 | 1256 | ||
1258 | if (chip->pdata->setup_resources) { | 1257 | if (chip->pdata->setup_resources) { |
1259 | err = chip->pdata->setup_resources(); | 1258 | err = chip->pdata->setup_resources(); |
1260 | if (err) { | 1259 | if (err) { |
1261 | err = -EINVAL; | 1260 | err = -EINVAL; |
1262 | goto fail3; | 1261 | goto fail0; |
1263 | } | 1262 | } |
1264 | } | 1263 | } |
1265 | 1264 | ||
@@ -1267,7 +1266,7 @@ static int bh1770_probe(struct i2c_client *client, | |||
1267 | &bh1770_attribute_group); | 1266 | &bh1770_attribute_group); |
1268 | if (err < 0) { | 1267 | if (err < 0) { |
1269 | dev_err(&chip->client->dev, "Sysfs registration failed\n"); | 1268 | dev_err(&chip->client->dev, "Sysfs registration failed\n"); |
1270 | goto fail4; | 1269 | goto fail1; |
1271 | } | 1270 | } |
1272 | 1271 | ||
1273 | /* | 1272 | /* |
@@ -1283,22 +1282,18 @@ static int bh1770_probe(struct i2c_client *client, | |||
1283 | if (err) { | 1282 | if (err) { |
1284 | dev_err(&client->dev, "could not get IRQ %d\n", | 1283 | dev_err(&client->dev, "could not get IRQ %d\n", |
1285 | client->irq); | 1284 | client->irq); |
1286 | goto fail5; | 1285 | goto fail2; |
1287 | } | 1286 | } |
1288 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | 1287 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); |
1289 | return err; | 1288 | return err; |
1290 | fail5: | 1289 | fail2: |
1291 | sysfs_remove_group(&chip->client->dev.kobj, | 1290 | sysfs_remove_group(&chip->client->dev.kobj, |
1292 | &bh1770_attribute_group); | 1291 | &bh1770_attribute_group); |
1293 | fail4: | 1292 | fail1: |
1294 | if (chip->pdata->release_resources) | 1293 | if (chip->pdata->release_resources) |
1295 | chip->pdata->release_resources(); | 1294 | chip->pdata->release_resources(); |
1296 | fail3: | 1295 | fail0: |
1297 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | 1296 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); |
1298 | fail2: | ||
1299 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1300 | fail1: | ||
1301 | kfree(chip); | ||
1302 | return err; | 1297 | return err; |
1303 | } | 1298 | } |
1304 | 1299 | ||
@@ -1322,8 +1317,6 @@ static int bh1770_remove(struct i2c_client *client) | |||
1322 | pm_runtime_disable(&client->dev); | 1317 | pm_runtime_disable(&client->dev); |
1323 | pm_runtime_set_suspended(&client->dev); | 1318 | pm_runtime_set_suspended(&client->dev); |
1324 | 1319 | ||
1325 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1326 | kfree(chip); | ||
1327 | return 0; | 1320 | return 0; |
1328 | } | 1321 | } |
1329 | 1322 | ||
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 48ea33d15a79..4c4a59b25537 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c | |||
@@ -149,50 +149,35 @@ static int bh1780_probe(struct i2c_client *client, | |||
149 | const struct i2c_device_id *id) | 149 | const struct i2c_device_id *id) |
150 | { | 150 | { |
151 | int ret; | 151 | int ret; |
152 | struct bh1780_data *ddata = NULL; | 152 | struct bh1780_data *ddata; |
153 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 153 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
154 | 154 | ||
155 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { | 155 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) |
156 | ret = -EIO; | 156 | return -EIO; |
157 | goto err_op_failed; | ||
158 | } | ||
159 | 157 | ||
160 | ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL); | 158 | ddata = devm_kzalloc(&client->dev, sizeof(struct bh1780_data), |
161 | if (ddata == NULL) { | 159 | GFP_KERNEL); |
162 | ret = -ENOMEM; | 160 | if (ddata == NULL) |
163 | goto err_op_failed; | 161 | return -ENOMEM; |
164 | } | ||
165 | 162 | ||
166 | ddata->client = client; | 163 | ddata->client = client; |
167 | i2c_set_clientdata(client, ddata); | 164 | i2c_set_clientdata(client, ddata); |
168 | 165 | ||
169 | ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); | 166 | ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID"); |
170 | if (ret < 0) | 167 | if (ret < 0) |
171 | goto err_op_failed; | 168 | return ret; |
172 | 169 | ||
173 | dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n", | 170 | dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n", |
174 | (ret & BH1780_REVMASK)); | 171 | (ret & BH1780_REVMASK)); |
175 | 172 | ||
176 | mutex_init(&ddata->lock); | 173 | mutex_init(&ddata->lock); |
177 | 174 | ||
178 | ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); | 175 | return sysfs_create_group(&client->dev.kobj, &bh1780_attr_group); |
179 | if (ret) | ||
180 | goto err_op_failed; | ||
181 | |||
182 | return 0; | ||
183 | |||
184 | err_op_failed: | ||
185 | kfree(ddata); | ||
186 | return ret; | ||
187 | } | 176 | } |
188 | 177 | ||
189 | static int bh1780_remove(struct i2c_client *client) | 178 | static int bh1780_remove(struct i2c_client *client) |
190 | { | 179 | { |
191 | struct bh1780_data *ddata; | ||
192 | |||
193 | ddata = i2c_get_clientdata(client); | ||
194 | sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group); | 180 | sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group); |
195 | kfree(ddata); | ||
196 | 181 | ||
197 | return 0; | 182 | return 0; |
198 | } | 183 | } |
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 14d90eae605b..55e913b7eb11 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c | |||
@@ -954,10 +954,7 @@ static int data_debugfs_init(struct fpga_device *priv) | |||
954 | { | 954 | { |
955 | priv->dbg_entry = debugfs_create_file(drv_name, S_IRUGO, NULL, priv, | 955 | priv->dbg_entry = debugfs_create_file(drv_name, S_IRUGO, NULL, priv, |
956 | &data_debug_fops); | 956 | &data_debug_fops); |
957 | if (IS_ERR(priv->dbg_entry)) | 957 | return PTR_ERR_OR_ZERO(priv->dbg_entry); |
958 | return PTR_ERR(priv->dbg_entry); | ||
959 | |||
960 | return 0; | ||
961 | } | 958 | } |
962 | 959 | ||
963 | static void data_debugfs_exit(struct fpga_device *priv) | 960 | static void data_debugfs_exit(struct fpga_device *priv) |
diff --git a/drivers/misc/dummy-irq.c b/drivers/misc/dummy-irq.c index 4d0db15df115..acbbe0390be4 100644 --- a/drivers/misc/dummy-irq.c +++ b/drivers/misc/dummy-irq.c | |||
@@ -61,3 +61,4 @@ MODULE_LICENSE("GPL"); | |||
61 | MODULE_AUTHOR("Jiri Kosina"); | 61 | MODULE_AUTHOR("Jiri Kosina"); |
62 | module_param(irq, uint, 0444); | 62 | module_param(irq, uint, 0444); |
63 | MODULE_PARM_DESC(irq, "The IRQ to register for"); | 63 | MODULE_PARM_DESC(irq, "The IRQ to register for"); |
64 | MODULE_DESCRIPTION("Dummy IRQ handler driver"); | ||
diff --git a/drivers/misc/genwqe/Kconfig b/drivers/misc/genwqe/Kconfig index 6069d8cd79d7..4c0a033cbfdb 100644 --- a/drivers/misc/genwqe/Kconfig +++ b/drivers/misc/genwqe/Kconfig | |||
@@ -11,3 +11,9 @@ menuconfig GENWQE | |||
11 | Enables PCIe card driver for IBM GenWQE accelerators. | 11 | Enables PCIe card driver for IBM GenWQE accelerators. |
12 | The user-space interface is described in | 12 | The user-space interface is described in |
13 | include/linux/genwqe/genwqe_card.h. | 13 | include/linux/genwqe/genwqe_card.h. |
14 | |||
15 | config GENWQE_PLATFORM_ERROR_RECOVERY | ||
16 | int "Use platform recovery procedures (0=off, 1=on)" | ||
17 | depends on GENWQE | ||
18 | default 1 if PPC64 | ||
19 | default 0 | ||
diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c index 74d51c9bb858..43bbabc96b6c 100644 --- a/drivers/misc/genwqe/card_base.c +++ b/drivers/misc/genwqe/card_base.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/notifier.h> | 38 | #include <linux/notifier.h> |
39 | #include <linux/device.h> | 39 | #include <linux/device.h> |
40 | #include <linux/log2.h> | 40 | #include <linux/log2.h> |
41 | #include <linux/genwqe/genwqe_card.h> | ||
42 | 41 | ||
43 | #include "card_base.h" | 42 | #include "card_base.h" |
44 | #include "card_ddcb.h" | 43 | #include "card_ddcb.h" |
@@ -58,7 +57,7 @@ static struct dentry *debugfs_genwqe; | |||
58 | static struct genwqe_dev *genwqe_devices[GENWQE_CARD_NO_MAX]; | 57 | static struct genwqe_dev *genwqe_devices[GENWQE_CARD_NO_MAX]; |
59 | 58 | ||
60 | /* PCI structure for identifying device by PCI vendor and device ID */ | 59 | /* PCI structure for identifying device by PCI vendor and device ID */ |
61 | static DEFINE_PCI_DEVICE_TABLE(genwqe_device_table) = { | 60 | static const struct pci_device_id genwqe_device_table[] = { |
62 | { .vendor = PCI_VENDOR_ID_IBM, | 61 | { .vendor = PCI_VENDOR_ID_IBM, |
63 | .device = PCI_DEVICE_GENWQE, | 62 | .device = PCI_DEVICE_GENWQE, |
64 | .subvendor = PCI_SUBVENDOR_ID_IBM, | 63 | .subvendor = PCI_SUBVENDOR_ID_IBM, |
@@ -140,6 +139,12 @@ static struct genwqe_dev *genwqe_dev_alloc(void) | |||
140 | cd->class_genwqe = class_genwqe; | 139 | cd->class_genwqe = class_genwqe; |
141 | cd->debugfs_genwqe = debugfs_genwqe; | 140 | cd->debugfs_genwqe = debugfs_genwqe; |
142 | 141 | ||
142 | /* | ||
143 | * This comes from kernel config option and can be overritten via | ||
144 | * debugfs. | ||
145 | */ | ||
146 | cd->use_platform_recovery = CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY; | ||
147 | |||
143 | init_waitqueue_head(&cd->queue_waitq); | 148 | init_waitqueue_head(&cd->queue_waitq); |
144 | 149 | ||
145 | spin_lock_init(&cd->file_lock); | 150 | spin_lock_init(&cd->file_lock); |
@@ -761,6 +766,124 @@ static u64 genwqe_fir_checking(struct genwqe_dev *cd) | |||
761 | } | 766 | } |
762 | 767 | ||
763 | /** | 768 | /** |
769 | * genwqe_pci_fundamental_reset() - trigger a PCIe fundamental reset on the slot | ||
770 | * | ||
771 | * Note: pci_set_pcie_reset_state() is not implemented on all archs, so this | ||
772 | * reset method will not work in all cases. | ||
773 | * | ||
774 | * Return: 0 on success or error code from pci_set_pcie_reset_state() | ||
775 | */ | ||
776 | static int genwqe_pci_fundamental_reset(struct pci_dev *pci_dev) | ||
777 | { | ||
778 | int rc; | ||
779 | |||
780 | /* | ||
781 | * lock pci config space access from userspace, | ||
782 | * save state and issue PCIe fundamental reset | ||
783 | */ | ||
784 | pci_cfg_access_lock(pci_dev); | ||
785 | pci_save_state(pci_dev); | ||
786 | rc = pci_set_pcie_reset_state(pci_dev, pcie_warm_reset); | ||
787 | if (!rc) { | ||
788 | /* keep PCIe reset asserted for 250ms */ | ||
789 | msleep(250); | ||
790 | pci_set_pcie_reset_state(pci_dev, pcie_deassert_reset); | ||
791 | /* Wait for 2s to reload flash and train the link */ | ||
792 | msleep(2000); | ||
793 | } | ||
794 | pci_restore_state(pci_dev); | ||
795 | pci_cfg_access_unlock(pci_dev); | ||
796 | return rc; | ||
797 | } | ||
798 | |||
799 | |||
800 | static int genwqe_platform_recovery(struct genwqe_dev *cd) | ||
801 | { | ||
802 | struct pci_dev *pci_dev = cd->pci_dev; | ||
803 | int rc; | ||
804 | |||
805 | dev_info(&pci_dev->dev, | ||
806 | "[%s] resetting card for error recovery\n", __func__); | ||
807 | |||
808 | /* Clear out error injection flags */ | ||
809 | cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE | | ||
810 | GENWQE_INJECT_GFIR_FATAL | | ||
811 | GENWQE_INJECT_GFIR_INFO); | ||
812 | |||
813 | genwqe_stop(cd); | ||
814 | |||
815 | /* Try recoverying the card with fundamental reset */ | ||
816 | rc = genwqe_pci_fundamental_reset(pci_dev); | ||
817 | if (!rc) { | ||
818 | rc = genwqe_start(cd); | ||
819 | if (!rc) | ||
820 | dev_info(&pci_dev->dev, | ||
821 | "[%s] card recovered\n", __func__); | ||
822 | else | ||
823 | dev_err(&pci_dev->dev, | ||
824 | "[%s] err: cannot start card services! (err=%d)\n", | ||
825 | __func__, rc); | ||
826 | } else { | ||
827 | dev_err(&pci_dev->dev, | ||
828 | "[%s] card reset failed\n", __func__); | ||
829 | } | ||
830 | |||
831 | return rc; | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * genwqe_reload_bistream() - reload card bitstream | ||
836 | * | ||
837 | * Set the appropriate register and call fundamental reset to reaload the card | ||
838 | * bitstream. | ||
839 | * | ||
840 | * Return: 0 on success, error code otherwise | ||
841 | */ | ||
842 | static int genwqe_reload_bistream(struct genwqe_dev *cd) | ||
843 | { | ||
844 | struct pci_dev *pci_dev = cd->pci_dev; | ||
845 | int rc; | ||
846 | |||
847 | dev_info(&pci_dev->dev, | ||
848 | "[%s] resetting card for bitstream reload\n", | ||
849 | __func__); | ||
850 | |||
851 | genwqe_stop(cd); | ||
852 | |||
853 | /* | ||
854 | * Cause a CPLD reprogram with the 'next_bitstream' | ||
855 | * partition on PCIe hot or fundamental reset | ||
856 | */ | ||
857 | __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, | ||
858 | (cd->softreset & 0xcull) | 0x70ull); | ||
859 | |||
860 | rc = genwqe_pci_fundamental_reset(pci_dev); | ||
861 | if (rc) { | ||
862 | /* | ||
863 | * A fundamental reset failure can be caused | ||
864 | * by lack of support on the arch, so we just | ||
865 | * log the error and try to start the card | ||
866 | * again. | ||
867 | */ | ||
868 | dev_err(&pci_dev->dev, | ||
869 | "[%s] err: failed to reset card for bitstream reload\n", | ||
870 | __func__); | ||
871 | } | ||
872 | |||
873 | rc = genwqe_start(cd); | ||
874 | if (rc) { | ||
875 | dev_err(&pci_dev->dev, | ||
876 | "[%s] err: cannot start card services! (err=%d)\n", | ||
877 | __func__, rc); | ||
878 | return rc; | ||
879 | } | ||
880 | dev_info(&pci_dev->dev, | ||
881 | "[%s] card reloaded\n", __func__); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | |||
886 | /** | ||
764 | * genwqe_health_thread() - Health checking thread | 887 | * genwqe_health_thread() - Health checking thread |
765 | * | 888 | * |
766 | * This thread is only started for the PF of the card. | 889 | * This thread is only started for the PF of the card. |
@@ -786,6 +909,7 @@ static int genwqe_health_thread(void *data) | |||
786 | struct pci_dev *pci_dev = cd->pci_dev; | 909 | struct pci_dev *pci_dev = cd->pci_dev; |
787 | u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg; | 910 | u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg; |
788 | 911 | ||
912 | health_thread_begin: | ||
789 | while (!kthread_should_stop()) { | 913 | while (!kthread_should_stop()) { |
790 | rc = wait_event_interruptible_timeout(cd->health_waitq, | 914 | rc = wait_event_interruptible_timeout(cd->health_waitq, |
791 | (genwqe_health_check_cond(cd, &gfir) || | 915 | (genwqe_health_check_cond(cd, &gfir) || |
@@ -846,6 +970,13 @@ static int genwqe_health_thread(void *data) | |||
846 | } | 970 | } |
847 | } | 971 | } |
848 | 972 | ||
973 | if (cd->card_state == GENWQE_CARD_RELOAD_BITSTREAM) { | ||
974 | /* Userspace requested card bitstream reload */ | ||
975 | rc = genwqe_reload_bistream(cd); | ||
976 | if (rc) | ||
977 | goto fatal_error; | ||
978 | } | ||
979 | |||
849 | cd->last_gfir = gfir; | 980 | cd->last_gfir = gfir; |
850 | cond_resched(); | 981 | cond_resched(); |
851 | } | 982 | } |
@@ -853,6 +984,28 @@ static int genwqe_health_thread(void *data) | |||
853 | return 0; | 984 | return 0; |
854 | 985 | ||
855 | fatal_error: | 986 | fatal_error: |
987 | if (cd->use_platform_recovery) { | ||
988 | /* | ||
989 | * Since we use raw accessors, EEH errors won't be detected | ||
990 | * by the platform until we do a non-raw MMIO or config space | ||
991 | * read | ||
992 | */ | ||
993 | readq(cd->mmio + IO_SLC_CFGREG_GFIR); | ||
994 | |||
995 | /* We do nothing if the card is going over PCI recovery */ | ||
996 | if (pci_channel_offline(pci_dev)) | ||
997 | return -EIO; | ||
998 | |||
999 | /* | ||
1000 | * If it's supported by the platform, we try a fundamental reset | ||
1001 | * to recover from a fatal error. Otherwise, we continue to wait | ||
1002 | * for an external recovery procedure to take care of it. | ||
1003 | */ | ||
1004 | rc = genwqe_platform_recovery(cd); | ||
1005 | if (!rc) | ||
1006 | goto health_thread_begin; | ||
1007 | } | ||
1008 | |||
856 | dev_err(&pci_dev->dev, | 1009 | dev_err(&pci_dev->dev, |
857 | "[%s] card unusable. Please trigger unbind!\n", __func__); | 1010 | "[%s] card unusable. Please trigger unbind!\n", __func__); |
858 | 1011 | ||
@@ -958,6 +1111,9 @@ static int genwqe_pci_setup(struct genwqe_dev *cd) | |||
958 | pci_set_master(pci_dev); | 1111 | pci_set_master(pci_dev); |
959 | pci_enable_pcie_error_reporting(pci_dev); | 1112 | pci_enable_pcie_error_reporting(pci_dev); |
960 | 1113 | ||
1114 | /* EEH recovery requires PCIe fundamental reset */ | ||
1115 | pci_dev->needs_freset = 1; | ||
1116 | |||
961 | /* request complete BAR-0 space (length = 0) */ | 1117 | /* request complete BAR-0 space (length = 0) */ |
962 | cd->mmio_len = pci_resource_len(pci_dev, 0); | 1118 | cd->mmio_len = pci_resource_len(pci_dev, 0); |
963 | cd->mmio = pci_iomap(pci_dev, 0, 0); | 1119 | cd->mmio = pci_iomap(pci_dev, 0, 0); |
@@ -1096,23 +1252,40 @@ static pci_ers_result_t genwqe_err_error_detected(struct pci_dev *pci_dev, | |||
1096 | 1252 | ||
1097 | dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state); | 1253 | dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state); |
1098 | 1254 | ||
1099 | if (pci_dev == NULL) | ||
1100 | return PCI_ERS_RESULT_NEED_RESET; | ||
1101 | |||
1102 | cd = dev_get_drvdata(&pci_dev->dev); | 1255 | cd = dev_get_drvdata(&pci_dev->dev); |
1103 | if (cd == NULL) | 1256 | if (cd == NULL) |
1104 | return PCI_ERS_RESULT_NEED_RESET; | 1257 | return PCI_ERS_RESULT_DISCONNECT; |
1105 | 1258 | ||
1106 | switch (state) { | 1259 | /* Stop the card */ |
1107 | case pci_channel_io_normal: | 1260 | genwqe_health_check_stop(cd); |
1108 | return PCI_ERS_RESULT_CAN_RECOVER; | 1261 | genwqe_stop(cd); |
1109 | case pci_channel_io_frozen: | 1262 | |
1110 | return PCI_ERS_RESULT_NEED_RESET; | 1263 | /* |
1111 | case pci_channel_io_perm_failure: | 1264 | * On permanent failure, the PCI code will call device remove |
1265 | * after the return of this function. | ||
1266 | * genwqe_stop() can be called twice. | ||
1267 | */ | ||
1268 | if (state == pci_channel_io_perm_failure) { | ||
1112 | return PCI_ERS_RESULT_DISCONNECT; | 1269 | return PCI_ERS_RESULT_DISCONNECT; |
1270 | } else { | ||
1271 | genwqe_pci_remove(cd); | ||
1272 | return PCI_ERS_RESULT_NEED_RESET; | ||
1113 | } | 1273 | } |
1274 | } | ||
1275 | |||
1276 | static pci_ers_result_t genwqe_err_slot_reset(struct pci_dev *pci_dev) | ||
1277 | { | ||
1278 | int rc; | ||
1279 | struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); | ||
1114 | 1280 | ||
1115 | return PCI_ERS_RESULT_NEED_RESET; | 1281 | rc = genwqe_pci_setup(cd); |
1282 | if (!rc) { | ||
1283 | return PCI_ERS_RESULT_RECOVERED; | ||
1284 | } else { | ||
1285 | dev_err(&pci_dev->dev, | ||
1286 | "err: problems with PCI setup (err=%d)\n", rc); | ||
1287 | return PCI_ERS_RESULT_DISCONNECT; | ||
1288 | } | ||
1116 | } | 1289 | } |
1117 | 1290 | ||
1118 | static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev) | 1291 | static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev) |
@@ -1120,8 +1293,22 @@ static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev) | |||
1120 | return PCI_ERS_RESULT_NONE; | 1293 | return PCI_ERS_RESULT_NONE; |
1121 | } | 1294 | } |
1122 | 1295 | ||
1123 | static void genwqe_err_resume(struct pci_dev *dev) | 1296 | static void genwqe_err_resume(struct pci_dev *pci_dev) |
1124 | { | 1297 | { |
1298 | int rc; | ||
1299 | struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev); | ||
1300 | |||
1301 | rc = genwqe_start(cd); | ||
1302 | if (!rc) { | ||
1303 | rc = genwqe_health_check_start(cd); | ||
1304 | if (rc) | ||
1305 | dev_err(&pci_dev->dev, | ||
1306 | "err: cannot start health checking! (err=%d)\n", | ||
1307 | rc); | ||
1308 | } else { | ||
1309 | dev_err(&pci_dev->dev, | ||
1310 | "err: cannot start card services! (err=%d)\n", rc); | ||
1311 | } | ||
1125 | } | 1312 | } |
1126 | 1313 | ||
1127 | static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs) | 1314 | static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs) |
@@ -1144,7 +1331,7 @@ static struct pci_error_handlers genwqe_err_handler = { | |||
1144 | .error_detected = genwqe_err_error_detected, | 1331 | .error_detected = genwqe_err_error_detected, |
1145 | .mmio_enabled = genwqe_err_result_none, | 1332 | .mmio_enabled = genwqe_err_result_none, |
1146 | .link_reset = genwqe_err_result_none, | 1333 | .link_reset = genwqe_err_result_none, |
1147 | .slot_reset = genwqe_err_result_none, | 1334 | .slot_reset = genwqe_err_slot_reset, |
1148 | .resume = genwqe_err_resume, | 1335 | .resume = genwqe_err_resume, |
1149 | }; | 1336 | }; |
1150 | 1337 | ||
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index 0e608a288603..67abd8cb2247 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h | |||
@@ -291,6 +291,8 @@ struct genwqe_dev { | |||
291 | struct task_struct *health_thread; | 291 | struct task_struct *health_thread; |
292 | wait_queue_head_t health_waitq; | 292 | wait_queue_head_t health_waitq; |
293 | 293 | ||
294 | int use_platform_recovery; /* use platform recovery mechanisms */ | ||
295 | |||
294 | /* char device */ | 296 | /* char device */ |
295 | dev_t devnum_genwqe; /* major/minor num card */ | 297 | dev_t devnum_genwqe; /* major/minor num card */ |
296 | struct class *class_genwqe; /* reference to class object */ | 298 | struct class *class_genwqe; /* reference to class object */ |
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index c8046db2d5a2..dc9851a5540e 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c | |||
@@ -1118,7 +1118,21 @@ static irqreturn_t genwqe_pf_isr(int irq, void *dev_id) | |||
1118 | * safer, but slower for the good-case ... See above. | 1118 | * safer, but slower for the good-case ... See above. |
1119 | */ | 1119 | */ |
1120 | gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); | 1120 | gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR); |
1121 | if ((gfir & GFIR_ERR_TRIGGER) != 0x0) { | 1121 | if (((gfir & GFIR_ERR_TRIGGER) != 0x0) && |
1122 | !pci_channel_offline(pci_dev)) { | ||
1123 | |||
1124 | if (cd->use_platform_recovery) { | ||
1125 | /* | ||
1126 | * Since we use raw accessors, EEH errors won't be | ||
1127 | * detected by the platform until we do a non-raw | ||
1128 | * MMIO or config space read | ||
1129 | */ | ||
1130 | readq(cd->mmio + IO_SLC_CFGREG_GFIR); | ||
1131 | |||
1132 | /* Don't do anything if the PCI channel is frozen */ | ||
1133 | if (pci_channel_offline(pci_dev)) | ||
1134 | goto exit; | ||
1135 | } | ||
1122 | 1136 | ||
1123 | wake_up_interruptible(&cd->health_waitq); | 1137 | wake_up_interruptible(&cd->health_waitq); |
1124 | 1138 | ||
@@ -1126,12 +1140,12 @@ static irqreturn_t genwqe_pf_isr(int irq, void *dev_id) | |||
1126 | * By default GFIRs causes recovery actions. This | 1140 | * By default GFIRs causes recovery actions. This |
1127 | * count is just for debug when recovery is masked. | 1141 | * count is just for debug when recovery is masked. |
1128 | */ | 1142 | */ |
1129 | printk_ratelimited(KERN_ERR | 1143 | dev_err_ratelimited(&pci_dev->dev, |
1130 | "%s %s: [%s] GFIR=%016llx\n", | 1144 | "[%s] GFIR=%016llx\n", |
1131 | GENWQE_DEVNAME, dev_name(&pci_dev->dev), | 1145 | __func__, gfir); |
1132 | __func__, gfir); | ||
1133 | } | 1146 | } |
1134 | 1147 | ||
1148 | exit: | ||
1135 | return IRQ_HANDLED; | 1149 | return IRQ_HANDLED; |
1136 | } | 1150 | } |
1137 | 1151 | ||
@@ -1237,9 +1251,7 @@ int genwqe_setup_service_layer(struct genwqe_dev *cd) | |||
1237 | } | 1251 | } |
1238 | 1252 | ||
1239 | rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS); | 1253 | rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS); |
1240 | if (rc > 0) | 1254 | if (rc) { |
1241 | rc = genwqe_set_interrupt_capability(cd, rc); | ||
1242 | if (rc != 0) { | ||
1243 | rc = -ENODEV; | 1255 | rc = -ENODEV; |
1244 | goto stop_kthread; | 1256 | goto stop_kthread; |
1245 | } | 1257 | } |
diff --git a/drivers/misc/genwqe/card_debugfs.c b/drivers/misc/genwqe/card_debugfs.c index 0a33ade64109..c9b4d6d0eb99 100644 --- a/drivers/misc/genwqe/card_debugfs.c +++ b/drivers/misc/genwqe/card_debugfs.c | |||
@@ -485,6 +485,13 @@ int genwqe_init_debugfs(struct genwqe_dev *cd) | |||
485 | goto err1; | 485 | goto err1; |
486 | } | 486 | } |
487 | 487 | ||
488 | file = debugfs_create_u32("use_platform_recovery", 0666, root, | ||
489 | &cd->use_platform_recovery); | ||
490 | if (!file) { | ||
491 | ret = -ENOMEM; | ||
492 | goto err1; | ||
493 | } | ||
494 | |||
488 | cd->debugfs_root = root; | 495 | cd->debugfs_root = root; |
489 | return 0; | 496 | return 0; |
490 | err1: | 497 | err1: |
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 1d2f163a1906..aae42555e2ca 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c | |||
@@ -1048,10 +1048,15 @@ static long genwqe_ioctl(struct file *filp, unsigned int cmd, | |||
1048 | int rc = 0; | 1048 | int rc = 0; |
1049 | struct genwqe_file *cfile = (struct genwqe_file *)filp->private_data; | 1049 | struct genwqe_file *cfile = (struct genwqe_file *)filp->private_data; |
1050 | struct genwqe_dev *cd = cfile->cd; | 1050 | struct genwqe_dev *cd = cfile->cd; |
1051 | struct pci_dev *pci_dev = cd->pci_dev; | ||
1051 | struct genwqe_reg_io __user *io; | 1052 | struct genwqe_reg_io __user *io; |
1052 | u64 val; | 1053 | u64 val; |
1053 | u32 reg_offs; | 1054 | u32 reg_offs; |
1054 | 1055 | ||
1056 | /* Return -EIO if card hit EEH */ | ||
1057 | if (pci_channel_offline(pci_dev)) | ||
1058 | return -EIO; | ||
1059 | |||
1055 | if (_IOC_TYPE(cmd) != GENWQE_IOC_CODE) | 1060 | if (_IOC_TYPE(cmd) != GENWQE_IOC_CODE) |
1056 | return -EINVAL; | 1061 | return -EINVAL; |
1057 | 1062 | ||
diff --git a/drivers/misc/genwqe/card_sysfs.c b/drivers/misc/genwqe/card_sysfs.c index a72a99266c3c..7232e40a3ad9 100644 --- a/drivers/misc/genwqe/card_sysfs.c +++ b/drivers/misc/genwqe/card_sysfs.c | |||
@@ -223,6 +223,30 @@ static ssize_t next_bitstream_store(struct device *dev, | |||
223 | } | 223 | } |
224 | static DEVICE_ATTR_RW(next_bitstream); | 224 | static DEVICE_ATTR_RW(next_bitstream); |
225 | 225 | ||
226 | static ssize_t reload_bitstream_store(struct device *dev, | ||
227 | struct device_attribute *attr, | ||
228 | const char *buf, size_t count) | ||
229 | { | ||
230 | int reload; | ||
231 | struct genwqe_dev *cd = dev_get_drvdata(dev); | ||
232 | |||
233 | if (kstrtoint(buf, 0, &reload) < 0) | ||
234 | return -EINVAL; | ||
235 | |||
236 | if (reload == 0x1) { | ||
237 | if (cd->card_state == GENWQE_CARD_UNUSED || | ||
238 | cd->card_state == GENWQE_CARD_USED) | ||
239 | cd->card_state = GENWQE_CARD_RELOAD_BITSTREAM; | ||
240 | else | ||
241 | return -EIO; | ||
242 | } else { | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | return count; | ||
247 | } | ||
248 | static DEVICE_ATTR_WO(reload_bitstream); | ||
249 | |||
226 | /* | 250 | /* |
227 | * Create device_attribute structures / params: name, mode, show, store | 251 | * Create device_attribute structures / params: name, mode, show, store |
228 | * additional flag if valid in VF | 252 | * additional flag if valid in VF |
@@ -239,6 +263,7 @@ static struct attribute *genwqe_attributes[] = { | |||
239 | &dev_attr_status.attr, | 263 | &dev_attr_status.attr, |
240 | &dev_attr_freerunning_timer.attr, | 264 | &dev_attr_freerunning_timer.attr, |
241 | &dev_attr_queue_working_time.attr, | 265 | &dev_attr_queue_working_time.attr, |
266 | &dev_attr_reload_bitstream.attr, | ||
242 | NULL, | 267 | NULL, |
243 | }; | 268 | }; |
244 | 269 | ||
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 62cc6bb3f62e..a6400f09229c 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c | |||
@@ -53,12 +53,17 @@ | |||
53 | */ | 53 | */ |
54 | int __genwqe_writeq(struct genwqe_dev *cd, u64 byte_offs, u64 val) | 54 | int __genwqe_writeq(struct genwqe_dev *cd, u64 byte_offs, u64 val) |
55 | { | 55 | { |
56 | struct pci_dev *pci_dev = cd->pci_dev; | ||
57 | |||
56 | if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE) | 58 | if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE) |
57 | return -EIO; | 59 | return -EIO; |
58 | 60 | ||
59 | if (cd->mmio == NULL) | 61 | if (cd->mmio == NULL) |
60 | return -EIO; | 62 | return -EIO; |
61 | 63 | ||
64 | if (pci_channel_offline(pci_dev)) | ||
65 | return -EIO; | ||
66 | |||
62 | __raw_writeq((__force u64)cpu_to_be64(val), cd->mmio + byte_offs); | 67 | __raw_writeq((__force u64)cpu_to_be64(val), cd->mmio + byte_offs); |
63 | return 0; | 68 | return 0; |
64 | } | 69 | } |
@@ -99,12 +104,17 @@ u64 __genwqe_readq(struct genwqe_dev *cd, u64 byte_offs) | |||
99 | */ | 104 | */ |
100 | int __genwqe_writel(struct genwqe_dev *cd, u64 byte_offs, u32 val) | 105 | int __genwqe_writel(struct genwqe_dev *cd, u64 byte_offs, u32 val) |
101 | { | 106 | { |
107 | struct pci_dev *pci_dev = cd->pci_dev; | ||
108 | |||
102 | if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE) | 109 | if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE) |
103 | return -EIO; | 110 | return -EIO; |
104 | 111 | ||
105 | if (cd->mmio == NULL) | 112 | if (cd->mmio == NULL) |
106 | return -EIO; | 113 | return -EIO; |
107 | 114 | ||
115 | if (pci_channel_offline(pci_dev)) | ||
116 | return -EIO; | ||
117 | |||
108 | __raw_writel((__force u32)cpu_to_be32(val), cd->mmio + byte_offs); | 118 | __raw_writel((__force u32)cpu_to_be32(val), cd->mmio + byte_offs); |
109 | return 0; | 119 | return 0; |
110 | } | 120 | } |
@@ -718,10 +728,12 @@ int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count) | |||
718 | int rc; | 728 | int rc; |
719 | struct pci_dev *pci_dev = cd->pci_dev; | 729 | struct pci_dev *pci_dev = cd->pci_dev; |
720 | 730 | ||
721 | rc = pci_enable_msi_exact(pci_dev, count); | 731 | rc = pci_enable_msi_range(pci_dev, 1, count); |
722 | if (rc == 0) | 732 | if (rc < 0) |
723 | cd->flags |= GENWQE_FLAG_MSI_ENABLED; | 733 | return rc; |
724 | return rc; | 734 | |
735 | cd->flags |= GENWQE_FLAG_MSI_ENABLED; | ||
736 | return 0; | ||
725 | } | 737 | } |
726 | 738 | ||
727 | /** | 739 | /** |
diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h index cd5263163a6e..a506e9aa2d57 100644 --- a/drivers/misc/genwqe/genwqe_driver.h +++ b/drivers/misc/genwqe/genwqe_driver.h | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <asm/byteorder.h> | 36 | #include <asm/byteorder.h> |
37 | #include <linux/genwqe/genwqe_card.h> | 37 | #include <linux/genwqe/genwqe_card.h> |
38 | 38 | ||
39 | #define DRV_VERS_STRING "2.0.15" | 39 | #define DRV_VERS_STRING "2.0.21" |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Static minor number assignement, until we decide/implement | 42 | * Static minor number assignement, until we decide/implement |
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c index 0a1565e63c71..7ffdb589841e 100644 --- a/drivers/misc/lattice-ecp3-config.c +++ b/drivers/misc/lattice-ecp3-config.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <asm/unaligned.h> | ||
18 | 19 | ||
19 | #define FIRMWARE_NAME "lattice-ecp3.bit" | 20 | #define FIRMWARE_NAME "lattice-ecp3.bit" |
20 | 21 | ||
@@ -91,8 +92,8 @@ static void firmware_load(const struct firmware *fw, void *context) | |||
91 | /* Trying to speak with the FPGA via SPI... */ | 92 | /* Trying to speak with the FPGA via SPI... */ |
92 | txbuf[0] = FPGA_CMD_READ_ID; | 93 | txbuf[0] = FPGA_CMD_READ_ID; |
93 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | 94 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); |
94 | dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", *(u32 *)&rxbuf[4]); | 95 | jedec_id = get_unaligned_be32(&rxbuf[4]); |
95 | jedec_id = *(u32 *)&rxbuf[4]; | 96 | dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", jedec_id); |
96 | 97 | ||
97 | for (i = 0; i < ARRAY_SIZE(ecp3_dev); i++) { | 98 | for (i = 0; i < ARRAY_SIZE(ecp3_dev); i++) { |
98 | if (jedec_id == ecp3_dev[i].jedec_id) | 99 | if (jedec_id == ecp3_dev[i].jedec_id) |
@@ -109,7 +110,8 @@ static void firmware_load(const struct firmware *fw, void *context) | |||
109 | 110 | ||
110 | txbuf[0] = FPGA_CMD_READ_STATUS; | 111 | txbuf[0] = FPGA_CMD_READ_STATUS; |
111 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | 112 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); |
112 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]); | 113 | status = get_unaligned_be32(&rxbuf[4]); |
114 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", status); | ||
113 | 115 | ||
114 | buffer = kzalloc(fw->size + 8, GFP_KERNEL); | 116 | buffer = kzalloc(fw->size + 8, GFP_KERNEL); |
115 | if (!buffer) { | 117 | if (!buffer) { |
@@ -141,7 +143,7 @@ static void firmware_load(const struct firmware *fw, void *context) | |||
141 | for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) { | 143 | for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) { |
142 | txbuf[0] = FPGA_CMD_READ_STATUS; | 144 | txbuf[0] = FPGA_CMD_READ_STATUS; |
143 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | 145 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); |
144 | status = *(u32 *)&rxbuf[4]; | 146 | status = get_unaligned_be32(&rxbuf[4]); |
145 | if (status == FPGA_STATUS_CLEARED) | 147 | if (status == FPGA_STATUS_CLEARED) |
146 | break; | 148 | break; |
147 | 149 | ||
@@ -164,8 +166,8 @@ static void firmware_load(const struct firmware *fw, void *context) | |||
164 | 166 | ||
165 | txbuf[0] = FPGA_CMD_READ_STATUS; | 167 | txbuf[0] = FPGA_CMD_READ_STATUS; |
166 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); | 168 | ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len); |
167 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]); | 169 | status = get_unaligned_be32(&rxbuf[4]); |
168 | status = *(u32 *)&rxbuf[4]; | 170 | dev_dbg(&spi->dev, "FPGA Status=%08x\n", status); |
169 | 171 | ||
170 | /* Check result */ | 172 | /* Check result */ |
171 | if (status & FPGA_STATUS_DONE) | 173 | if (status & FPGA_STATUS_DONE) |
@@ -196,7 +198,7 @@ static int lattice_ecp3_probe(struct spi_device *spi) | |||
196 | spi_set_drvdata(spi, data); | 198 | spi_set_drvdata(spi, data); |
197 | 199 | ||
198 | init_completion(&data->fw_loaded); | 200 | init_completion(&data->fw_loaded); |
199 | err = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 201 | err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, |
200 | FIRMWARE_NAME, &spi->dev, | 202 | FIRMWARE_NAME, &spi->dev, |
201 | GFP_KERNEL, spi, firmware_load); | 203 | GFP_KERNEL, spi, firmware_load); |
202 | if (err) { | 204 | if (err) { |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index d66a2f24f6b3..b5abe34120b8 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -870,3 +870,4 @@ module_init(lkdtm_module_init); | |||
870 | module_exit(lkdtm_module_exit); | 870 | module_exit(lkdtm_module_exit); |
871 | 871 | ||
872 | MODULE_LICENSE("GPL"); | 872 | MODULE_LICENSE("GPL"); |
873 | MODULE_DESCRIPTION("Kprobe module for testing crash dumps"); | ||
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 59d20c599b16..324e1de93687 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c | |||
@@ -459,7 +459,7 @@ int mei_cl_disconnect(struct mei_cl *cl) | |||
459 | { | 459 | { |
460 | struct mei_device *dev; | 460 | struct mei_device *dev; |
461 | struct mei_cl_cb *cb; | 461 | struct mei_cl_cb *cb; |
462 | int rets, err; | 462 | int rets; |
463 | 463 | ||
464 | if (WARN_ON(!cl || !cl->dev)) | 464 | if (WARN_ON(!cl || !cl->dev)) |
465 | return -ENODEV; | 465 | return -ENODEV; |
@@ -491,6 +491,7 @@ int mei_cl_disconnect(struct mei_cl *cl) | |||
491 | cl_err(dev, cl, "failed to disconnect.\n"); | 491 | cl_err(dev, cl, "failed to disconnect.\n"); |
492 | goto free; | 492 | goto free; |
493 | } | 493 | } |
494 | cl->timer_count = MEI_CONNECT_TIMEOUT; | ||
494 | mdelay(10); /* Wait for hardware disconnection ready */ | 495 | mdelay(10); /* Wait for hardware disconnection ready */ |
495 | list_add_tail(&cb->list, &dev->ctrl_rd_list.list); | 496 | list_add_tail(&cb->list, &dev->ctrl_rd_list.list); |
496 | } else { | 497 | } else { |
@@ -500,23 +501,18 @@ int mei_cl_disconnect(struct mei_cl *cl) | |||
500 | } | 501 | } |
501 | mutex_unlock(&dev->device_lock); | 502 | mutex_unlock(&dev->device_lock); |
502 | 503 | ||
503 | err = wait_event_timeout(dev->wait_recvd_msg, | 504 | wait_event_timeout(dev->wait_recvd_msg, |
504 | MEI_FILE_DISCONNECTED == cl->state, | 505 | MEI_FILE_DISCONNECTED == cl->state, |
505 | mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); | 506 | mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); |
506 | 507 | ||
507 | mutex_lock(&dev->device_lock); | 508 | mutex_lock(&dev->device_lock); |
509 | |||
508 | if (MEI_FILE_DISCONNECTED == cl->state) { | 510 | if (MEI_FILE_DISCONNECTED == cl->state) { |
509 | rets = 0; | 511 | rets = 0; |
510 | cl_dbg(dev, cl, "successfully disconnected from FW client.\n"); | 512 | cl_dbg(dev, cl, "successfully disconnected from FW client.\n"); |
511 | } else { | 513 | } else { |
512 | rets = -ENODEV; | 514 | cl_dbg(dev, cl, "timeout on disconnect from FW client.\n"); |
513 | if (MEI_FILE_DISCONNECTED != cl->state) | 515 | rets = -ETIME; |
514 | cl_err(dev, cl, "wrong status client disconnect.\n"); | ||
515 | |||
516 | if (err) | ||
517 | cl_dbg(dev, cl, "wait failed disconnect err=%d\n", err); | ||
518 | |||
519 | cl_err(dev, cl, "failed to disconnect from FW client.\n"); | ||
520 | } | 516 | } |
521 | 517 | ||
522 | mei_io_list_flush(&dev->ctrl_rd_list, cl); | 518 | mei_io_list_flush(&dev->ctrl_rd_list, cl); |
@@ -616,6 +612,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) | |||
616 | mutex_lock(&dev->device_lock); | 612 | mutex_lock(&dev->device_lock); |
617 | 613 | ||
618 | if (cl->state != MEI_FILE_CONNECTED) { | 614 | if (cl->state != MEI_FILE_CONNECTED) { |
615 | cl->state = MEI_FILE_DISCONNECTED; | ||
619 | /* something went really wrong */ | 616 | /* something went really wrong */ |
620 | if (!cl->status) | 617 | if (!cl->status) |
621 | cl->status = -EFAULT; | 618 | cl->status = -EFAULT; |
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index a7856c0ac576..c5feafdd58a8 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h | |||
@@ -115,6 +115,7 @@ | |||
115 | #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ | 115 | #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ |
116 | 116 | ||
117 | #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ | 117 | #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ |
118 | #define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */ | ||
118 | 119 | ||
119 | /* Host Firmware Status Registers in PCI Config Space */ | 120 | /* Host Firmware Status Registers in PCI Config Space */ |
120 | #define PCI_CFG_HFS_1 0x40 | 121 | #define PCI_CFG_HFS_1 0x40 |
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 6a2d272cea43..a9a0d08f758e 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -710,64 +710,10 @@ end: | |||
710 | return IRQ_HANDLED; | 710 | return IRQ_HANDLED; |
711 | } | 711 | } |
712 | 712 | ||
713 | /** | ||
714 | * mei_me_fw_status - retrieve fw status from the pci config space | ||
715 | * | ||
716 | * @dev: the device structure | ||
717 | * @fw_status: fw status registers storage | ||
718 | * | ||
719 | * returns 0 on success an error code otherwise | ||
720 | */ | ||
721 | static int mei_me_fw_status(struct mei_device *dev, | ||
722 | struct mei_fw_status *fw_status) | ||
723 | { | ||
724 | const u32 pci_cfg_reg[] = {PCI_CFG_HFS_1, PCI_CFG_HFS_2}; | ||
725 | int i; | ||
726 | |||
727 | if (!fw_status) | ||
728 | return -EINVAL; | ||
729 | |||
730 | switch (dev->pdev->device) { | ||
731 | case MEI_DEV_ID_IBXPK_1: | ||
732 | case MEI_DEV_ID_IBXPK_2: | ||
733 | case MEI_DEV_ID_CPT_1: | ||
734 | case MEI_DEV_ID_PBG_1: | ||
735 | case MEI_DEV_ID_PPT_1: | ||
736 | case MEI_DEV_ID_PPT_2: | ||
737 | case MEI_DEV_ID_PPT_3: | ||
738 | case MEI_DEV_ID_LPT_H: | ||
739 | case MEI_DEV_ID_LPT_W: | ||
740 | case MEI_DEV_ID_LPT_LP: | ||
741 | case MEI_DEV_ID_LPT_HR: | ||
742 | case MEI_DEV_ID_WPT_LP: | ||
743 | fw_status->count = 2; | ||
744 | break; | ||
745 | case MEI_DEV_ID_ICH10_1: | ||
746 | case MEI_DEV_ID_ICH10_2: | ||
747 | case MEI_DEV_ID_ICH10_3: | ||
748 | case MEI_DEV_ID_ICH10_4: | ||
749 | fw_status->count = 1; | ||
750 | break; | ||
751 | default: | ||
752 | fw_status->count = 0; | ||
753 | break; | ||
754 | } | ||
755 | |||
756 | for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) { | ||
757 | int ret; | ||
758 | ret = pci_read_config_dword(dev->pdev, | ||
759 | pci_cfg_reg[i], &fw_status->status[i]); | ||
760 | if (ret) | ||
761 | return ret; | ||
762 | } | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static const struct mei_hw_ops mei_me_hw_ops = { | 713 | static const struct mei_hw_ops mei_me_hw_ops = { |
767 | 714 | ||
768 | .pg_state = mei_me_pg_state, | 715 | .pg_state = mei_me_pg_state, |
769 | 716 | ||
770 | .fw_status = mei_me_fw_status, | ||
771 | .host_is_ready = mei_me_host_is_ready, | 717 | .host_is_ready = mei_me_host_is_ready, |
772 | 718 | ||
773 | .hw_is_ready = mei_me_hw_is_ready, | 719 | .hw_is_ready = mei_me_hw_is_ready, |
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 93273783dec5..f1cd166094f2 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c | |||
@@ -1042,40 +1042,8 @@ end: | |||
1042 | return IRQ_HANDLED; | 1042 | return IRQ_HANDLED; |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | |||
1046 | /** | ||
1047 | * mei_txe_fw_status - retrieve fw status from the pci config space | ||
1048 | * | ||
1049 | * @dev: the device structure | ||
1050 | * @fw_status: fw status registers storage | ||
1051 | * | ||
1052 | * returns: 0 on success an error code otherwise | ||
1053 | */ | ||
1054 | static int mei_txe_fw_status(struct mei_device *dev, | ||
1055 | struct mei_fw_status *fw_status) | ||
1056 | { | ||
1057 | const u32 pci_cfg_reg[] = {PCI_CFG_TXE_FW_STS0, PCI_CFG_TXE_FW_STS1}; | ||
1058 | int i; | ||
1059 | |||
1060 | if (!fw_status) | ||
1061 | return -EINVAL; | ||
1062 | |||
1063 | fw_status->count = 2; | ||
1064 | |||
1065 | for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) { | ||
1066 | int ret; | ||
1067 | ret = pci_read_config_dword(dev->pdev, | ||
1068 | pci_cfg_reg[i], &fw_status->status[i]); | ||
1069 | if (ret) | ||
1070 | return ret; | ||
1071 | } | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static const struct mei_hw_ops mei_txe_hw_ops = { | 1045 | static const struct mei_hw_ops mei_txe_hw_ops = { |
1077 | 1046 | ||
1078 | .fw_status = mei_txe_fw_status, | ||
1079 | .host_is_ready = mei_txe_host_is_ready, | 1047 | .host_is_ready = mei_txe_host_is_ready, |
1080 | 1048 | ||
1081 | .pg_state = mei_txe_pg_state, | 1049 | .pg_state = mei_txe_pg_state, |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 66f0a1a06451..401a3d526cd0 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/compat.h> | 32 | #include <linux/compat.h> |
33 | #include <linux/jiffies.h> | 33 | #include <linux/jiffies.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/miscdevice.h> | ||
36 | 35 | ||
37 | #include <linux/mei.h> | 36 | #include <linux/mei.h> |
38 | 37 | ||
@@ -49,19 +48,12 @@ | |||
49 | */ | 48 | */ |
50 | static int mei_open(struct inode *inode, struct file *file) | 49 | static int mei_open(struct inode *inode, struct file *file) |
51 | { | 50 | { |
52 | struct miscdevice *misc = file->private_data; | ||
53 | struct pci_dev *pdev; | ||
54 | struct mei_cl *cl; | ||
55 | struct mei_device *dev; | 51 | struct mei_device *dev; |
52 | struct mei_cl *cl; | ||
56 | 53 | ||
57 | int err; | 54 | int err; |
58 | 55 | ||
59 | if (!misc->parent) | 56 | dev = container_of(inode->i_cdev, struct mei_device, cdev); |
60 | return -ENODEV; | ||
61 | |||
62 | pdev = container_of(misc->parent, struct pci_dev, dev); | ||
63 | |||
64 | dev = pci_get_drvdata(pdev); | ||
65 | if (!dev) | 57 | if (!dev) |
66 | return -ENODEV; | 58 | return -ENODEV; |
67 | 59 | ||
@@ -667,46 +659,148 @@ static const struct file_operations mei_fops = { | |||
667 | .llseek = no_llseek | 659 | .llseek = no_llseek |
668 | }; | 660 | }; |
669 | 661 | ||
670 | /* | 662 | static struct class *mei_class; |
671 | * Misc Device Struct | 663 | static dev_t mei_devt; |
664 | #define MEI_MAX_DEVS MINORMASK | ||
665 | static DEFINE_MUTEX(mei_minor_lock); | ||
666 | static DEFINE_IDR(mei_idr); | ||
667 | |||
668 | /** | ||
669 | * mei_minor_get - obtain next free device minor number | ||
670 | * | ||
671 | * @dev: device pointer | ||
672 | * | ||
673 | * returns allocated minor, or -ENOSPC if no free minor left | ||
672 | */ | 674 | */ |
673 | static struct miscdevice mei_misc_device = { | 675 | static int mei_minor_get(struct mei_device *dev) |
674 | .name = "mei", | 676 | { |
675 | .fops = &mei_fops, | 677 | int ret; |
676 | .minor = MISC_DYNAMIC_MINOR, | 678 | |
677 | }; | 679 | mutex_lock(&mei_minor_lock); |
680 | ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL); | ||
681 | if (ret >= 0) | ||
682 | dev->minor = ret; | ||
683 | else if (ret == -ENOSPC) | ||
684 | dev_err(&dev->pdev->dev, "too many mei devices\n"); | ||
678 | 685 | ||
686 | mutex_unlock(&mei_minor_lock); | ||
687 | return ret; | ||
688 | } | ||
679 | 689 | ||
680 | int mei_register(struct mei_device *dev) | 690 | /** |
691 | * mei_minor_free - mark device minor number as free | ||
692 | * | ||
693 | * @dev: device pointer | ||
694 | */ | ||
695 | static void mei_minor_free(struct mei_device *dev) | ||
681 | { | 696 | { |
682 | int ret; | 697 | mutex_lock(&mei_minor_lock); |
683 | mei_misc_device.parent = &dev->pdev->dev; | 698 | idr_remove(&mei_idr, dev->minor); |
684 | ret = misc_register(&mei_misc_device); | 699 | mutex_unlock(&mei_minor_lock); |
685 | if (ret) | 700 | } |
701 | |||
702 | int mei_register(struct mei_device *dev, struct device *parent) | ||
703 | { | ||
704 | struct device *clsdev; /* class device */ | ||
705 | int ret, devno; | ||
706 | |||
707 | ret = mei_minor_get(dev); | ||
708 | if (ret < 0) | ||
686 | return ret; | 709 | return ret; |
687 | 710 | ||
688 | if (mei_dbgfs_register(dev, mei_misc_device.name)) | 711 | /* Fill in the data structures */ |
689 | dev_err(&dev->pdev->dev, "cannot register debugfs\n"); | 712 | devno = MKDEV(MAJOR(mei_devt), dev->minor); |
713 | cdev_init(&dev->cdev, &mei_fops); | ||
714 | dev->cdev.owner = mei_fops.owner; | ||
715 | |||
716 | /* Add the device */ | ||
717 | ret = cdev_add(&dev->cdev, devno, 1); | ||
718 | if (ret) { | ||
719 | dev_err(parent, "unable to add device %d:%d\n", | ||
720 | MAJOR(mei_devt), dev->minor); | ||
721 | goto err_dev_add; | ||
722 | } | ||
723 | |||
724 | clsdev = device_create(mei_class, parent, devno, | ||
725 | NULL, "mei%d", dev->minor); | ||
726 | |||
727 | if (IS_ERR(clsdev)) { | ||
728 | dev_err(parent, "unable to create device %d:%d\n", | ||
729 | MAJOR(mei_devt), dev->minor); | ||
730 | ret = PTR_ERR(clsdev); | ||
731 | goto err_dev_create; | ||
732 | } | ||
733 | |||
734 | ret = mei_dbgfs_register(dev, dev_name(clsdev)); | ||
735 | if (ret) { | ||
736 | dev_err(clsdev, "cannot register debugfs ret = %d\n", ret); | ||
737 | goto err_dev_dbgfs; | ||
738 | } | ||
690 | 739 | ||
691 | return 0; | 740 | return 0; |
741 | |||
742 | err_dev_dbgfs: | ||
743 | device_destroy(mei_class, devno); | ||
744 | err_dev_create: | ||
745 | cdev_del(&dev->cdev); | ||
746 | err_dev_add: | ||
747 | mei_minor_free(dev); | ||
748 | return ret; | ||
692 | } | 749 | } |
693 | EXPORT_SYMBOL_GPL(mei_register); | 750 | EXPORT_SYMBOL_GPL(mei_register); |
694 | 751 | ||
695 | void mei_deregister(struct mei_device *dev) | 752 | void mei_deregister(struct mei_device *dev) |
696 | { | 753 | { |
754 | int devno; | ||
755 | |||
756 | devno = dev->cdev.dev; | ||
757 | cdev_del(&dev->cdev); | ||
758 | |||
697 | mei_dbgfs_deregister(dev); | 759 | mei_dbgfs_deregister(dev); |
698 | misc_deregister(&mei_misc_device); | 760 | |
699 | mei_misc_device.parent = NULL; | 761 | device_destroy(mei_class, devno); |
762 | |||
763 | mei_minor_free(dev); | ||
700 | } | 764 | } |
701 | EXPORT_SYMBOL_GPL(mei_deregister); | 765 | EXPORT_SYMBOL_GPL(mei_deregister); |
702 | 766 | ||
703 | static int __init mei_init(void) | 767 | static int __init mei_init(void) |
704 | { | 768 | { |
705 | return mei_cl_bus_init(); | 769 | int ret; |
770 | |||
771 | mei_class = class_create(THIS_MODULE, "mei"); | ||
772 | if (IS_ERR(mei_class)) { | ||
773 | pr_err("couldn't create class\n"); | ||
774 | ret = PTR_ERR(mei_class); | ||
775 | goto err; | ||
776 | } | ||
777 | |||
778 | ret = alloc_chrdev_region(&mei_devt, 0, MEI_MAX_DEVS, "mei"); | ||
779 | if (ret < 0) { | ||
780 | pr_err("unable to allocate char dev region\n"); | ||
781 | goto err_class; | ||
782 | } | ||
783 | |||
784 | ret = mei_cl_bus_init(); | ||
785 | if (ret < 0) { | ||
786 | pr_err("unable to initialize bus\n"); | ||
787 | goto err_chrdev; | ||
788 | } | ||
789 | |||
790 | return 0; | ||
791 | |||
792 | err_chrdev: | ||
793 | unregister_chrdev_region(mei_devt, MEI_MAX_DEVS); | ||
794 | err_class: | ||
795 | class_destroy(mei_class); | ||
796 | err: | ||
797 | return ret; | ||
706 | } | 798 | } |
707 | 799 | ||
708 | static void __exit mei_exit(void) | 800 | static void __exit mei_exit(void) |
709 | { | 801 | { |
802 | unregister_chrdev_region(mei_devt, MEI_MAX_DEVS); | ||
803 | class_destroy(mei_class); | ||
710 | mei_cl_bus_exit(); | 804 | mei_cl_bus_exit(); |
711 | } | 805 | } |
712 | 806 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 5c7e990e2f22..0b0d6135543b 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -227,7 +227,6 @@ struct mei_cl { | |||
227 | 227 | ||
228 | /** struct mei_hw_ops | 228 | /** struct mei_hw_ops |
229 | * | 229 | * |
230 | * @fw_status - read FW status from PCI config space | ||
231 | * @host_is_ready - query for host readiness | 230 | * @host_is_ready - query for host readiness |
232 | 231 | ||
233 | * @hw_is_ready - query if hw is ready | 232 | * @hw_is_ready - query if hw is ready |
@@ -255,8 +254,6 @@ struct mei_cl { | |||
255 | */ | 254 | */ |
256 | struct mei_hw_ops { | 255 | struct mei_hw_ops { |
257 | 256 | ||
258 | int (*fw_status)(struct mei_device *dev, | ||
259 | struct mei_fw_status *fw_status); | ||
260 | bool (*host_is_ready)(struct mei_device *dev); | 257 | bool (*host_is_ready)(struct mei_device *dev); |
261 | 258 | ||
262 | bool (*hw_is_ready)(struct mei_device *dev); | 259 | bool (*hw_is_ready)(struct mei_device *dev); |
@@ -400,6 +397,10 @@ struct mei_cfg { | |||
400 | /** | 397 | /** |
401 | * struct mei_device - MEI private device struct | 398 | * struct mei_device - MEI private device struct |
402 | 399 | ||
400 | * @pdev - pointer to pci device struct | ||
401 | * @cdev - character device | ||
402 | * @minor - minor number allocated for device | ||
403 | * | ||
403 | * @reset_count - limits the number of consecutive resets | 404 | * @reset_count - limits the number of consecutive resets |
404 | * @hbm_state - state of host bus message protocol | 405 | * @hbm_state - state of host bus message protocol |
405 | * @pg_event - power gating event | 406 | * @pg_event - power gating event |
@@ -412,6 +413,9 @@ struct mei_cfg { | |||
412 | */ | 413 | */ |
413 | struct mei_device { | 414 | struct mei_device { |
414 | struct pci_dev *pdev; /* pointer to pci device struct */ | 415 | struct pci_dev *pdev; /* pointer to pci device struct */ |
416 | struct cdev cdev; | ||
417 | int minor; | ||
418 | |||
415 | /* | 419 | /* |
416 | * lists of queues | 420 | * lists of queues |
417 | */ | 421 | */ |
@@ -741,7 +745,7 @@ static inline int mei_dbgfs_register(struct mei_device *dev, const char *name) | |||
741 | static inline void mei_dbgfs_deregister(struct mei_device *dev) {} | 745 | static inline void mei_dbgfs_deregister(struct mei_device *dev) {} |
742 | #endif /* CONFIG_DEBUG_FS */ | 746 | #endif /* CONFIG_DEBUG_FS */ |
743 | 747 | ||
744 | int mei_register(struct mei_device *dev); | 748 | int mei_register(struct mei_device *dev, struct device *parent); |
745 | void mei_deregister(struct mei_device *dev); | 749 | void mei_deregister(struct mei_device *dev); |
746 | 750 | ||
747 | #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" | 751 | #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" |
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 1b46c64a649f..a0e9422b55a2 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
34 | #include <linux/miscdevice.h> | ||
35 | 34 | ||
36 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
37 | 36 | ||
@@ -82,6 +81,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { | |||
82 | {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)}, | 81 | {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)}, |
83 | {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)}, | 82 | {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)}, |
84 | {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)}, | 83 | {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)}, |
84 | {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch_cfg)}, | ||
85 | 85 | ||
86 | /* required last entry */ | 86 | /* required last entry */ |
87 | {0, } | 87 | {0, } |
@@ -207,7 +207,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
207 | pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT); | 207 | pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT); |
208 | pm_runtime_use_autosuspend(&pdev->dev); | 208 | pm_runtime_use_autosuspend(&pdev->dev); |
209 | 209 | ||
210 | err = mei_register(dev); | 210 | err = mei_register(dev, &pdev->dev); |
211 | if (err) | 211 | if (err) |
212 | goto release_irq; | 212 | goto release_irq; |
213 | 213 | ||
@@ -369,7 +369,7 @@ static int mei_me_pm_runtime_idle(struct device *device) | |||
369 | if (!dev) | 369 | if (!dev) |
370 | return -ENODEV; | 370 | return -ENODEV; |
371 | if (mei_write_is_idle(dev)) | 371 | if (mei_write_is_idle(dev)) |
372 | pm_schedule_suspend(device, MEI_ME_RPM_TIMEOUT * 2); | 372 | pm_runtime_autosuspend(device); |
373 | 373 | ||
374 | return -EBUSY; | 374 | return -EBUSY; |
375 | } | 375 | } |
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 2343c6236df9..19de57368b7a 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c | |||
@@ -149,7 +149,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
149 | pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); | 149 | pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); |
150 | pm_runtime_use_autosuspend(&pdev->dev); | 150 | pm_runtime_use_autosuspend(&pdev->dev); |
151 | 151 | ||
152 | err = mei_register(dev); | 152 | err = mei_register(dev, &pdev->dev); |
153 | if (err) | 153 | if (err) |
154 | goto release_irq; | 154 | goto release_irq; |
155 | 155 | ||
@@ -306,7 +306,7 @@ static int mei_txe_pm_runtime_idle(struct device *device) | |||
306 | if (!dev) | 306 | if (!dev) |
307 | return -ENODEV; | 307 | return -ENODEV; |
308 | if (mei_write_is_idle(dev)) | 308 | if (mei_write_is_idle(dev)) |
309 | pm_schedule_suspend(device, MEI_TXI_RPM_TIMEOUT * 2); | 309 | pm_runtime_autosuspend(device); |
310 | 310 | ||
311 | return -EBUSY; | 311 | return -EBUSY; |
312 | } | 312 | } |
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index 462a5b1d8651..cc4eef040c14 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig | |||
@@ -1,8 +1,25 @@ | |||
1 | comment "Intel MIC Bus Driver" | ||
2 | |||
3 | config INTEL_MIC_BUS | ||
4 | tristate "Intel MIC Bus Driver" | ||
5 | depends on 64BIT && PCI && X86 && X86_DEV_DMA_OPS | ||
6 | help | ||
7 | This option is selected by any driver which registers a | ||
8 | device or driver on the MIC Bus, such as CONFIG_INTEL_MIC_HOST, | ||
9 | CONFIG_INTEL_MIC_CARD, CONFIG_INTEL_MIC_X100_DMA etc. | ||
10 | |||
11 | If you are building a host/card kernel with an Intel MIC device | ||
12 | then say M (recommended) or Y, else say N. If unsure say N. | ||
13 | |||
14 | More information about the Intel MIC family as well as the Linux | ||
15 | OS and tools for MIC to use with this driver are available from | ||
16 | <http://software.intel.com/en-us/mic-developer>. | ||
17 | |||
1 | comment "Intel MIC Host Driver" | 18 | comment "Intel MIC Host Driver" |
2 | 19 | ||
3 | config INTEL_MIC_HOST | 20 | config INTEL_MIC_HOST |
4 | tristate "Intel MIC Host Driver" | 21 | tristate "Intel MIC Host Driver" |
5 | depends on 64BIT && PCI && X86 | 22 | depends on 64BIT && PCI && X86 && INTEL_MIC_BUS |
6 | select VHOST_RING | 23 | select VHOST_RING |
7 | help | 24 | help |
8 | This enables Host Driver support for the Intel Many Integrated | 25 | This enables Host Driver support for the Intel Many Integrated |
@@ -22,7 +39,7 @@ comment "Intel MIC Card Driver" | |||
22 | 39 | ||
23 | config INTEL_MIC_CARD | 40 | config INTEL_MIC_CARD |
24 | tristate "Intel MIC Card Driver" | 41 | tristate "Intel MIC Card Driver" |
25 | depends on 64BIT && X86 | 42 | depends on 64BIT && X86 && INTEL_MIC_BUS |
26 | select VIRTIO | 43 | select VIRTIO |
27 | help | 44 | help |
28 | This enables card driver support for the Intel Many Integrated | 45 | This enables card driver support for the Intel Many Integrated |
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile index 05b34d683a58..e9bf148755e2 100644 --- a/drivers/misc/mic/Makefile +++ b/drivers/misc/mic/Makefile | |||
@@ -4,3 +4,4 @@ | |||
4 | # | 4 | # |
5 | obj-$(CONFIG_INTEL_MIC_HOST) += host/ | 5 | obj-$(CONFIG_INTEL_MIC_HOST) += host/ |
6 | obj-$(CONFIG_INTEL_MIC_CARD) += card/ | 6 | obj-$(CONFIG_INTEL_MIC_CARD) += card/ |
7 | obj-$(CONFIG_INTEL_MIC_BUS) += bus/ | ||
diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile new file mode 100644 index 000000000000..d85c7f2a0af4 --- /dev/null +++ b/drivers/misc/mic/bus/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile - Intel MIC Linux driver. | ||
3 | # Copyright(c) 2014, Intel Corporation. | ||
4 | # | ||
5 | obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o | ||
diff --git a/drivers/misc/mic/bus/mic_bus.c b/drivers/misc/mic/bus/mic_bus.c new file mode 100644 index 000000000000..961ae90aae47 --- /dev/null +++ b/drivers/misc/mic/bus/mic_bus.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Intel MIC Platform Software Stack (MPSS) | ||
3 | * | ||
4 | * Copyright(c) 2014 Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License, version 2, as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * The full GNU General Public License is included in this distribution in | ||
16 | * the file called "COPYING". | ||
17 | * | ||
18 | * Intel MIC Bus driver. | ||
19 | * | ||
20 | * This implementation is very similar to the the virtio bus driver | ||
21 | * implementation @ drivers/virtio/virtio.c | ||
22 | */ | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/idr.h> | ||
26 | #include <linux/mic_bus.h> | ||
27 | |||
28 | /* Unique numbering for mbus devices. */ | ||
29 | static DEFINE_IDA(mbus_index_ida); | ||
30 | |||
31 | static ssize_t device_show(struct device *d, | ||
32 | struct device_attribute *attr, char *buf) | ||
33 | { | ||
34 | struct mbus_device *dev = dev_to_mbus(d); | ||
35 | return sprintf(buf, "0x%04x\n", dev->id.device); | ||
36 | } | ||
37 | static DEVICE_ATTR_RO(device); | ||
38 | |||
39 | static ssize_t vendor_show(struct device *d, | ||
40 | struct device_attribute *attr, char *buf) | ||
41 | { | ||
42 | struct mbus_device *dev = dev_to_mbus(d); | ||
43 | return sprintf(buf, "0x%04x\n", dev->id.vendor); | ||
44 | } | ||
45 | static DEVICE_ATTR_RO(vendor); | ||
46 | |||
47 | static ssize_t modalias_show(struct device *d, | ||
48 | struct device_attribute *attr, char *buf) | ||
49 | { | ||
50 | struct mbus_device *dev = dev_to_mbus(d); | ||
51 | return sprintf(buf, "mbus:d%08Xv%08X\n", | ||
52 | dev->id.device, dev->id.vendor); | ||
53 | } | ||
54 | static DEVICE_ATTR_RO(modalias); | ||
55 | |||
56 | static struct attribute *mbus_dev_attrs[] = { | ||
57 | &dev_attr_device.attr, | ||
58 | &dev_attr_vendor.attr, | ||
59 | &dev_attr_modalias.attr, | ||
60 | NULL, | ||
61 | }; | ||
62 | ATTRIBUTE_GROUPS(mbus_dev); | ||
63 | |||
64 | static inline int mbus_id_match(const struct mbus_device *dev, | ||
65 | const struct mbus_device_id *id) | ||
66 | { | ||
67 | if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID) | ||
68 | return 0; | ||
69 | |||
70 | return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev->id.vendor; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * This looks through all the IDs a driver claims to support. If any of them | ||
75 | * match, we return 1 and the kernel will call mbus_dev_probe(). | ||
76 | */ | ||
77 | static int mbus_dev_match(struct device *dv, struct device_driver *dr) | ||
78 | { | ||
79 | unsigned int i; | ||
80 | struct mbus_device *dev = dev_to_mbus(dv); | ||
81 | const struct mbus_device_id *ids; | ||
82 | |||
83 | ids = drv_to_mbus(dr)->id_table; | ||
84 | for (i = 0; ids[i].device; i++) | ||
85 | if (mbus_id_match(dev, &ids[i])) | ||
86 | return 1; | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env) | ||
91 | { | ||
92 | struct mbus_device *dev = dev_to_mbus(dv); | ||
93 | |||
94 | return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X", | ||
95 | dev->id.device, dev->id.vendor); | ||
96 | } | ||
97 | |||
98 | static int mbus_dev_probe(struct device *d) | ||
99 | { | ||
100 | int err; | ||
101 | struct mbus_device *dev = dev_to_mbus(d); | ||
102 | struct mbus_driver *drv = drv_to_mbus(dev->dev.driver); | ||
103 | |||
104 | err = drv->probe(dev); | ||
105 | if (!err) | ||
106 | if (drv->scan) | ||
107 | drv->scan(dev); | ||
108 | return err; | ||
109 | } | ||
110 | |||
111 | static int mbus_dev_remove(struct device *d) | ||
112 | { | ||
113 | struct mbus_device *dev = dev_to_mbus(d); | ||
114 | struct mbus_driver *drv = drv_to_mbus(dev->dev.driver); | ||
115 | |||
116 | drv->remove(dev); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static struct bus_type mic_bus = { | ||
121 | .name = "mic_bus", | ||
122 | .match = mbus_dev_match, | ||
123 | .dev_groups = mbus_dev_groups, | ||
124 | .uevent = mbus_uevent, | ||
125 | .probe = mbus_dev_probe, | ||
126 | .remove = mbus_dev_remove, | ||
127 | }; | ||
128 | |||
129 | int mbus_register_driver(struct mbus_driver *driver) | ||
130 | { | ||
131 | driver->driver.bus = &mic_bus; | ||
132 | return driver_register(&driver->driver); | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(mbus_register_driver); | ||
135 | |||
136 | void mbus_unregister_driver(struct mbus_driver *driver) | ||
137 | { | ||
138 | driver_unregister(&driver->driver); | ||
139 | } | ||
140 | EXPORT_SYMBOL_GPL(mbus_unregister_driver); | ||
141 | |||
142 | static void mbus_release_dev(struct device *d) | ||
143 | { | ||
144 | struct mbus_device *mbdev = dev_to_mbus(d); | ||
145 | kfree(mbdev); | ||
146 | } | ||
147 | |||
148 | struct mbus_device * | ||
149 | mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops, | ||
150 | struct mbus_hw_ops *hw_ops, void __iomem *mmio_va) | ||
151 | { | ||
152 | int ret; | ||
153 | struct mbus_device *mbdev; | ||
154 | |||
155 | mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL); | ||
156 | if (!mbdev) | ||
157 | return ERR_PTR(-ENOMEM); | ||
158 | |||
159 | mbdev->mmio_va = mmio_va; | ||
160 | mbdev->dev.parent = pdev; | ||
161 | mbdev->id.device = id; | ||
162 | mbdev->id.vendor = MBUS_DEV_ANY_ID; | ||
163 | mbdev->dev.archdata.dma_ops = dma_ops; | ||
164 | mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask; | ||
165 | dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64)); | ||
166 | mbdev->dev.release = mbus_release_dev; | ||
167 | mbdev->hw_ops = hw_ops; | ||
168 | mbdev->dev.bus = &mic_bus; | ||
169 | |||
170 | /* Assign a unique device index and hence name. */ | ||
171 | ret = ida_simple_get(&mbus_index_ida, 0, 0, GFP_KERNEL); | ||
172 | if (ret < 0) | ||
173 | goto free_mbdev; | ||
174 | |||
175 | mbdev->index = ret; | ||
176 | dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index); | ||
177 | /* | ||
178 | * device_register() causes the bus infrastructure to look for a | ||
179 | * matching driver. | ||
180 | */ | ||
181 | ret = device_register(&mbdev->dev); | ||
182 | if (ret) | ||
183 | goto ida_remove; | ||
184 | return mbdev; | ||
185 | ida_remove: | ||
186 | ida_simple_remove(&mbus_index_ida, mbdev->index); | ||
187 | free_mbdev: | ||
188 | kfree(mbdev); | ||
189 | return ERR_PTR(ret); | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(mbus_register_device); | ||
192 | |||
193 | void mbus_unregister_device(struct mbus_device *mbdev) | ||
194 | { | ||
195 | int index = mbdev->index; /* save for after device release */ | ||
196 | |||
197 | device_unregister(&mbdev->dev); | ||
198 | ida_simple_remove(&mbus_index_ida, index); | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(mbus_unregister_device); | ||
201 | |||
202 | static int __init mbus_init(void) | ||
203 | { | ||
204 | return bus_register(&mic_bus); | ||
205 | } | ||
206 | |||
207 | static void __exit mbus_exit(void) | ||
208 | { | ||
209 | bus_unregister(&mic_bus); | ||
210 | ida_destroy(&mbus_index_ida); | ||
211 | } | ||
212 | |||
213 | core_initcall(mbus_init); | ||
214 | module_exit(mbus_exit); | ||
215 | |||
216 | MODULE_AUTHOR("Intel Corporation"); | ||
217 | MODULE_DESCRIPTION("Intel(R) MIC Bus driver"); | ||
218 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c index d0980ff96833..83819eee553b 100644 --- a/drivers/misc/mic/card/mic_device.c +++ b/drivers/misc/mic/card/mic_device.c | |||
@@ -83,8 +83,8 @@ static int mic_shutdown_init(void) | |||
83 | int shutdown_db; | 83 | int shutdown_db; |
84 | 84 | ||
85 | shutdown_db = mic_next_card_db(); | 85 | shutdown_db = mic_next_card_db(); |
86 | shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, | 86 | shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, NULL, |
87 | "Shutdown", mdrv, shutdown_db); | 87 | "Shutdown", mdrv, shutdown_db); |
88 | if (IS_ERR(shutdown_cookie)) | 88 | if (IS_ERR(shutdown_cookie)) |
89 | rc = PTR_ERR(shutdown_cookie); | 89 | rc = PTR_ERR(shutdown_cookie); |
90 | else | 90 | else |
@@ -136,7 +136,8 @@ static void mic_dp_uninit(void) | |||
136 | /** | 136 | /** |
137 | * mic_request_card_irq - request an irq. | 137 | * mic_request_card_irq - request an irq. |
138 | * | 138 | * |
139 | * @func: The callback function that handles the interrupt. | 139 | * @handler: interrupt handler passed to request_threaded_irq. |
140 | * @thread_fn: thread fn. passed to request_threaded_irq. | ||
140 | * @name: The ASCII name of the callee requesting the irq. | 141 | * @name: The ASCII name of the callee requesting the irq. |
141 | * @data: private data that is returned back when calling the | 142 | * @data: private data that is returned back when calling the |
142 | * function handler. | 143 | * function handler. |
@@ -149,17 +150,19 @@ static void mic_dp_uninit(void) | |||
149 | * error code. | 150 | * error code. |
150 | * | 151 | * |
151 | */ | 152 | */ |
152 | struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data), | 153 | struct mic_irq * |
153 | const char *name, void *data, int index) | 154 | mic_request_card_irq(irq_handler_t handler, |
155 | irq_handler_t thread_fn, const char *name, | ||
156 | void *data, int index) | ||
154 | { | 157 | { |
155 | int rc = 0; | 158 | int rc = 0; |
156 | unsigned long cookie; | 159 | unsigned long cookie; |
157 | struct mic_driver *mdrv = g_drv; | 160 | struct mic_driver *mdrv = g_drv; |
158 | 161 | ||
159 | rc = request_irq(mic_db_to_irq(mdrv, index), func, | 162 | rc = request_threaded_irq(mic_db_to_irq(mdrv, index), handler, |
160 | 0, name, data); | 163 | thread_fn, 0, name, data); |
161 | if (rc) { | 164 | if (rc) { |
162 | dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc); | 165 | dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n", rc); |
163 | goto err; | 166 | goto err; |
164 | } | 167 | } |
165 | mdrv->irq_info.irq_usage_count[index]++; | 168 | mdrv->irq_info.irq_usage_count[index]++; |
@@ -172,9 +175,9 @@ err: | |||
172 | /** | 175 | /** |
173 | * mic_free_card_irq - free irq. | 176 | * mic_free_card_irq - free irq. |
174 | * | 177 | * |
175 | * @cookie: cookie obtained during a successful call to mic_request_irq | 178 | * @cookie: cookie obtained during a successful call to mic_request_threaded_irq |
176 | * @data: private data specified by the calling function during the | 179 | * @data: private data specified by the calling function during the |
177 | * mic_request_irq | 180 | * mic_request_threaded_irq |
178 | * | 181 | * |
179 | * returns: none. | 182 | * returns: none. |
180 | */ | 183 | */ |
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h index 306f502be95e..844be8fc9b22 100644 --- a/drivers/misc/mic/card/mic_device.h +++ b/drivers/misc/mic/card/mic_device.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/irqreturn.h> | 32 | #include <linux/irqreturn.h> |
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/mic_bus.h> | ||
33 | 35 | ||
34 | /** | 36 | /** |
35 | * struct mic_intr_info - Contains h/w specific interrupt sources info | 37 | * struct mic_intr_info - Contains h/w specific interrupt sources info |
@@ -70,6 +72,7 @@ struct mic_device { | |||
70 | * @hotplug_work: Hot plug work for adding/removing virtio devices. | 72 | * @hotplug_work: Hot plug work for adding/removing virtio devices. |
71 | * @irq_info: The OS specific irq information | 73 | * @irq_info: The OS specific irq information |
72 | * @intr_info: H/W specific interrupt information. | 74 | * @intr_info: H/W specific interrupt information. |
75 | * @dma_mbdev: dma device on the MIC virtual bus. | ||
73 | */ | 76 | */ |
74 | struct mic_driver { | 77 | struct mic_driver { |
75 | char name[20]; | 78 | char name[20]; |
@@ -80,6 +83,7 @@ struct mic_driver { | |||
80 | struct work_struct hotplug_work; | 83 | struct work_struct hotplug_work; |
81 | struct mic_irq_info irq_info; | 84 | struct mic_irq_info irq_info; |
82 | struct mic_intr_info intr_info; | 85 | struct mic_intr_info intr_info; |
86 | struct mbus_device *dma_mbdev; | ||
83 | }; | 87 | }; |
84 | 88 | ||
85 | /** | 89 | /** |
@@ -116,8 +120,9 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset) | |||
116 | int mic_driver_init(struct mic_driver *mdrv); | 120 | int mic_driver_init(struct mic_driver *mdrv); |
117 | void mic_driver_uninit(struct mic_driver *mdrv); | 121 | void mic_driver_uninit(struct mic_driver *mdrv); |
118 | int mic_next_card_db(void); | 122 | int mic_next_card_db(void); |
119 | struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data), | 123 | struct mic_irq * |
120 | const char *name, void *data, int intr_src); | 124 | mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn, |
125 | const char *name, void *data, int intr_src); | ||
121 | void mic_free_card_irq(struct mic_irq *cookie, void *data); | 126 | void mic_free_card_irq(struct mic_irq *cookie, void *data); |
122 | u32 mic_read_spad(struct mic_device *mdev, unsigned int idx); | 127 | u32 mic_read_spad(struct mic_device *mdev, unsigned int idx); |
123 | void mic_send_intr(struct mic_device *mdev, int doorbell); | 128 | void mic_send_intr(struct mic_device *mdev, int doorbell); |
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c index 653799b96bfa..f14b60080c21 100644 --- a/drivers/misc/mic/card/mic_virtio.c +++ b/drivers/misc/mic/card/mic_virtio.c | |||
@@ -417,7 +417,7 @@ static int mic_add_device(struct mic_device_desc __iomem *d, | |||
417 | 417 | ||
418 | virtio_db = mic_next_card_db(); | 418 | virtio_db = mic_next_card_db(); |
419 | mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler, | 419 | mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler, |
420 | "virtio intr", mvdev, virtio_db); | 420 | NULL, "virtio intr", mvdev, virtio_db); |
421 | if (IS_ERR(mvdev->virtio_cookie)) { | 421 | if (IS_ERR(mvdev->virtio_cookie)) { |
422 | ret = PTR_ERR(mvdev->virtio_cookie); | 422 | ret = PTR_ERR(mvdev->virtio_cookie); |
423 | goto kfree; | 423 | goto kfree; |
@@ -606,8 +606,9 @@ int mic_devices_init(struct mic_driver *mdrv) | |||
606 | mic_scan_devices(mdrv, !REMOVE_DEVICES); | 606 | mic_scan_devices(mdrv, !REMOVE_DEVICES); |
607 | 607 | ||
608 | config_db = mic_next_card_db(); | 608 | config_db = mic_next_card_db(); |
609 | virtio_config_cookie = mic_request_card_irq(mic_extint_handler, | 609 | virtio_config_cookie = mic_request_card_irq(mic_extint_handler, NULL, |
610 | "virtio_config_intr", mdrv, config_db); | 610 | "virtio_config_intr", mdrv, |
611 | config_db); | ||
611 | if (IS_ERR(virtio_config_cookie)) { | 612 | if (IS_ERR(virtio_config_cookie)) { |
612 | rc = PTR_ERR(virtio_config_cookie); | 613 | rc = PTR_ERR(virtio_config_cookie); |
613 | goto exit; | 614 | goto exit; |
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c index 2868945c9a4d..9d57545d64f6 100644 --- a/drivers/misc/mic/card/mic_x100.c +++ b/drivers/misc/mic/card/mic_x100.c | |||
@@ -148,6 +148,47 @@ void mic_card_unmap(struct mic_device *mdev, void __iomem *addr) | |||
148 | iounmap(addr); | 148 | iounmap(addr); |
149 | } | 149 | } |
150 | 150 | ||
151 | static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev) | ||
152 | { | ||
153 | return dev_get_drvdata(mbdev->dev.parent); | ||
154 | } | ||
155 | |||
156 | static struct mic_irq * | ||
157 | _mic_request_threaded_irq(struct mbus_device *mbdev, | ||
158 | irq_handler_t handler, irq_handler_t thread_fn, | ||
159 | const char *name, void *data, int intr_src) | ||
160 | { | ||
161 | int rc = 0; | ||
162 | unsigned int irq = intr_src; | ||
163 | unsigned long cookie = irq; | ||
164 | |||
165 | rc = request_threaded_irq(irq, handler, thread_fn, 0, name, data); | ||
166 | if (rc) { | ||
167 | dev_err(mbdev_to_mdrv(mbdev)->dev, | ||
168 | "request_threaded_irq failed rc = %d\n", rc); | ||
169 | return ERR_PTR(rc); | ||
170 | } | ||
171 | return (struct mic_irq *)cookie; | ||
172 | } | ||
173 | |||
174 | static void _mic_free_irq(struct mbus_device *mbdev, | ||
175 | struct mic_irq *cookie, void *data) | ||
176 | { | ||
177 | unsigned long irq = (unsigned long)cookie; | ||
178 | free_irq(irq, data); | ||
179 | } | ||
180 | |||
181 | static void _mic_ack_interrupt(struct mbus_device *mbdev, int num) | ||
182 | { | ||
183 | mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev); | ||
184 | } | ||
185 | |||
186 | static struct mbus_hw_ops mbus_hw_ops = { | ||
187 | .request_threaded_irq = _mic_request_threaded_irq, | ||
188 | .free_irq = _mic_free_irq, | ||
189 | .ack_interrupt = _mic_ack_interrupt, | ||
190 | }; | ||
191 | |||
151 | static int __init mic_probe(struct platform_device *pdev) | 192 | static int __init mic_probe(struct platform_device *pdev) |
152 | { | 193 | { |
153 | struct mic_driver *mdrv = &g_drv; | 194 | struct mic_driver *mdrv = &g_drv; |
@@ -159,32 +200,41 @@ static int __init mic_probe(struct platform_device *pdev) | |||
159 | 200 | ||
160 | mdev->mmio.pa = MIC_X100_MMIO_BASE; | 201 | mdev->mmio.pa = MIC_X100_MMIO_BASE; |
161 | mdev->mmio.len = MIC_X100_MMIO_LEN; | 202 | mdev->mmio.len = MIC_X100_MMIO_LEN; |
162 | mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN); | 203 | mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE, |
204 | MIC_X100_MMIO_LEN); | ||
163 | if (!mdev->mmio.va) { | 205 | if (!mdev->mmio.va) { |
164 | dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); | 206 | dev_err(&pdev->dev, "Cannot remap MMIO BAR\n"); |
165 | rc = -EIO; | 207 | rc = -EIO; |
166 | goto done; | 208 | goto done; |
167 | } | 209 | } |
168 | mic_hw_intr_init(mdrv); | 210 | mic_hw_intr_init(mdrv); |
211 | platform_set_drvdata(pdev, mdrv); | ||
212 | mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC, | ||
213 | NULL, &mbus_hw_ops, | ||
214 | mdrv->mdev.mmio.va); | ||
215 | if (IS_ERR(mdrv->dma_mbdev)) { | ||
216 | rc = PTR_ERR(mdrv->dma_mbdev); | ||
217 | dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc); | ||
218 | goto done; | ||
219 | } | ||
169 | rc = mic_driver_init(mdrv); | 220 | rc = mic_driver_init(mdrv); |
170 | if (rc) { | 221 | if (rc) { |
171 | dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc); | 222 | dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc); |
172 | goto iounmap; | 223 | goto remove_dma; |
173 | } | 224 | } |
174 | done: | 225 | done: |
175 | return rc; | 226 | return rc; |
176 | iounmap: | 227 | remove_dma: |
177 | iounmap(mdev->mmio.va); | 228 | mbus_unregister_device(mdrv->dma_mbdev); |
178 | return rc; | 229 | return rc; |
179 | } | 230 | } |
180 | 231 | ||
181 | static int mic_remove(struct platform_device *pdev) | 232 | static int mic_remove(struct platform_device *pdev) |
182 | { | 233 | { |
183 | struct mic_driver *mdrv = &g_drv; | 234 | struct mic_driver *mdrv = &g_drv; |
184 | struct mic_device *mdev = &mdrv->mdev; | ||
185 | 235 | ||
186 | mic_driver_uninit(mdrv); | 236 | mic_driver_uninit(mdrv); |
187 | iounmap(mdev->mmio.va); | 237 | mbus_unregister_device(mdrv->dma_mbdev); |
188 | return 0; | 238 | return 0; |
189 | } | 239 | } |
190 | 240 | ||
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index b75c6b5cc20f..ff2b0fb1a6be 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c | |||
@@ -23,11 +23,70 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | 24 | ||
25 | #include <linux/mic_common.h> | 25 | #include <linux/mic_common.h> |
26 | #include <linux/mic_bus.h> | ||
26 | #include "../common/mic_dev.h" | 27 | #include "../common/mic_dev.h" |
27 | #include "mic_device.h" | 28 | #include "mic_device.h" |
28 | #include "mic_smpt.h" | 29 | #include "mic_smpt.h" |
29 | #include "mic_virtio.h" | 30 | #include "mic_virtio.h" |
30 | 31 | ||
32 | static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev) | ||
33 | { | ||
34 | return dev_get_drvdata(mbdev->dev.parent); | ||
35 | } | ||
36 | |||
37 | static dma_addr_t | ||
38 | mic_dma_map_page(struct device *dev, struct page *page, | ||
39 | unsigned long offset, size_t size, enum dma_data_direction dir, | ||
40 | struct dma_attrs *attrs) | ||
41 | { | ||
42 | void *va = phys_to_virt(page_to_phys(page)) + offset; | ||
43 | struct mic_device *mdev = dev_get_drvdata(dev->parent); | ||
44 | |||
45 | return mic_map_single(mdev, va, size); | ||
46 | } | ||
47 | |||
48 | static void | ||
49 | mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, | ||
50 | size_t size, enum dma_data_direction dir, | ||
51 | struct dma_attrs *attrs) | ||
52 | { | ||
53 | struct mic_device *mdev = dev_get_drvdata(dev->parent); | ||
54 | mic_unmap_single(mdev, dma_addr, size); | ||
55 | } | ||
56 | |||
57 | static struct dma_map_ops mic_dma_ops = { | ||
58 | .map_page = mic_dma_map_page, | ||
59 | .unmap_page = mic_dma_unmap_page, | ||
60 | }; | ||
61 | |||
62 | static struct mic_irq * | ||
63 | _mic_request_threaded_irq(struct mbus_device *mbdev, | ||
64 | irq_handler_t handler, irq_handler_t thread_fn, | ||
65 | const char *name, void *data, int intr_src) | ||
66 | { | ||
67 | return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler, | ||
68 | thread_fn, name, data, | ||
69 | intr_src, MIC_INTR_DMA); | ||
70 | } | ||
71 | |||
72 | static void _mic_free_irq(struct mbus_device *mbdev, | ||
73 | struct mic_irq *cookie, void *data) | ||
74 | { | ||
75 | return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data); | ||
76 | } | ||
77 | |||
78 | static void _mic_ack_interrupt(struct mbus_device *mbdev, int num) | ||
79 | { | ||
80 | struct mic_device *mdev = mbdev_to_mdev(mbdev); | ||
81 | mdev->ops->intr_workarounds(mdev); | ||
82 | } | ||
83 | |||
84 | static struct mbus_hw_ops mbus_hw_ops = { | ||
85 | .request_threaded_irq = _mic_request_threaded_irq, | ||
86 | .free_irq = _mic_free_irq, | ||
87 | .ack_interrupt = _mic_ack_interrupt, | ||
88 | }; | ||
89 | |||
31 | /** | 90 | /** |
32 | * mic_reset - Reset the MIC device. | 91 | * mic_reset - Reset the MIC device. |
33 | * @mdev: pointer to mic_device instance | 92 | * @mdev: pointer to mic_device instance |
@@ -95,9 +154,21 @@ retry: | |||
95 | */ | 154 | */ |
96 | goto retry; | 155 | goto retry; |
97 | } | 156 | } |
157 | mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent, | ||
158 | MBUS_DEV_DMA_HOST, &mic_dma_ops, | ||
159 | &mbus_hw_ops, mdev->mmio.va); | ||
160 | if (IS_ERR(mdev->dma_mbdev)) { | ||
161 | rc = PTR_ERR(mdev->dma_mbdev); | ||
162 | goto unlock_ret; | ||
163 | } | ||
164 | mdev->dma_ch = mic_request_dma_chan(mdev); | ||
165 | if (!mdev->dma_ch) { | ||
166 | rc = -ENXIO; | ||
167 | goto dma_remove; | ||
168 | } | ||
98 | rc = mdev->ops->load_mic_fw(mdev, buf); | 169 | rc = mdev->ops->load_mic_fw(mdev, buf); |
99 | if (rc) | 170 | if (rc) |
100 | goto unlock_ret; | 171 | goto dma_release; |
101 | mic_smpt_restore(mdev); | 172 | mic_smpt_restore(mdev); |
102 | mic_intr_restore(mdev); | 173 | mic_intr_restore(mdev); |
103 | mdev->intr_ops->enable_interrupts(mdev); | 174 | mdev->intr_ops->enable_interrupts(mdev); |
@@ -105,6 +176,11 @@ retry: | |||
105 | mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); | 176 | mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32); |
106 | mdev->ops->send_firmware_intr(mdev); | 177 | mdev->ops->send_firmware_intr(mdev); |
107 | mic_set_state(mdev, MIC_ONLINE); | 178 | mic_set_state(mdev, MIC_ONLINE); |
179 | goto unlock_ret; | ||
180 | dma_release: | ||
181 | dma_release_channel(mdev->dma_ch); | ||
182 | dma_remove: | ||
183 | mbus_unregister_device(mdev->dma_mbdev); | ||
108 | unlock_ret: | 184 | unlock_ret: |
109 | mutex_unlock(&mdev->mic_mutex); | 185 | mutex_unlock(&mdev->mic_mutex); |
110 | return rc; | 186 | return rc; |
@@ -122,6 +198,11 @@ void mic_stop(struct mic_device *mdev, bool force) | |||
122 | mutex_lock(&mdev->mic_mutex); | 198 | mutex_lock(&mdev->mic_mutex); |
123 | if (MIC_OFFLINE != mdev->state || force) { | 199 | if (MIC_OFFLINE != mdev->state || force) { |
124 | mic_virtio_reset_devices(mdev); | 200 | mic_virtio_reset_devices(mdev); |
201 | if (mdev->dma_ch) { | ||
202 | dma_release_channel(mdev->dma_ch); | ||
203 | mdev->dma_ch = NULL; | ||
204 | } | ||
205 | mbus_unregister_device(mdev->dma_mbdev); | ||
125 | mic_bootparam_init(mdev); | 206 | mic_bootparam_init(mdev); |
126 | mic_reset(mdev); | 207 | mic_reset(mdev); |
127 | if (MIC_RESET_FAILED == mdev->state) | 208 | if (MIC_RESET_FAILED == mdev->state) |
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h index 0398c696d257..016bd15a7bd1 100644 --- a/drivers/misc/mic/host/mic_device.h +++ b/drivers/misc/mic/host/mic_device.h | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/idr.h> | 25 | #include <linux/idr.h> |
26 | #include <linux/notifier.h> | 26 | #include <linux/notifier.h> |
27 | #include <linux/irqreturn.h> | 27 | #include <linux/irqreturn.h> |
28 | #include <linux/dmaengine.h> | ||
29 | #include <linux/mic_bus.h> | ||
28 | 30 | ||
29 | #include "mic_intr.h" | 31 | #include "mic_intr.h" |
30 | 32 | ||
@@ -87,6 +89,8 @@ enum mic_stepping { | |||
87 | * @cdev: Character device for MIC. | 89 | * @cdev: Character device for MIC. |
88 | * @vdev_list: list of virtio devices. | 90 | * @vdev_list: list of virtio devices. |
89 | * @pm_notifier: Handles PM notifications from the OS. | 91 | * @pm_notifier: Handles PM notifications from the OS. |
92 | * @dma_mbdev: MIC BUS DMA device. | ||
93 | * @dma_ch: DMA channel reserved by this driver for use by virtio devices. | ||
90 | */ | 94 | */ |
91 | struct mic_device { | 95 | struct mic_device { |
92 | struct mic_mw mmio; | 96 | struct mic_mw mmio; |
@@ -124,6 +128,8 @@ struct mic_device { | |||
124 | struct cdev cdev; | 128 | struct cdev cdev; |
125 | struct list_head vdev_list; | 129 | struct list_head vdev_list; |
126 | struct notifier_block pm_notifier; | 130 | struct notifier_block pm_notifier; |
131 | struct mbus_device *dma_mbdev; | ||
132 | struct dma_chan *dma_ch; | ||
127 | }; | 133 | }; |
128 | 134 | ||
129 | /** | 135 | /** |
@@ -144,6 +150,7 @@ struct mic_device { | |||
144 | * @load_mic_fw: Load firmware segments required to boot the card | 150 | * @load_mic_fw: Load firmware segments required to boot the card |
145 | * into card memory. This includes the kernel, command line, ramdisk etc. | 151 | * into card memory. This includes the kernel, command line, ramdisk etc. |
146 | * @get_postcode: Get post code status from firmware. | 152 | * @get_postcode: Get post code status from firmware. |
153 | * @dma_filter: DMA filter function to be used. | ||
147 | */ | 154 | */ |
148 | struct mic_hw_ops { | 155 | struct mic_hw_ops { |
149 | u8 aper_bar; | 156 | u8 aper_bar; |
@@ -159,6 +166,7 @@ struct mic_hw_ops { | |||
159 | void (*send_firmware_intr)(struct mic_device *mdev); | 166 | void (*send_firmware_intr)(struct mic_device *mdev); |
160 | int (*load_mic_fw)(struct mic_device *mdev, const char *buf); | 167 | int (*load_mic_fw)(struct mic_device *mdev, const char *buf); |
161 | u32 (*get_postcode)(struct mic_device *mdev); | 168 | u32 (*get_postcode)(struct mic_device *mdev); |
169 | bool (*dma_filter)(struct dma_chan *chan, void *param); | ||
162 | }; | 170 | }; |
163 | 171 | ||
164 | /** | 172 | /** |
@@ -187,6 +195,22 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset) | |||
187 | iowrite32(val, mw->va + offset); | 195 | iowrite32(val, mw->va + offset); |
188 | } | 196 | } |
189 | 197 | ||
198 | static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev) | ||
199 | { | ||
200 | dma_cap_mask_t mask; | ||
201 | struct dma_chan *chan; | ||
202 | |||
203 | dma_cap_zero(mask); | ||
204 | dma_cap_set(DMA_MEMCPY, mask); | ||
205 | chan = dma_request_channel(mask, mdev->ops->dma_filter, | ||
206 | mdev->sdev->parent); | ||
207 | if (chan) | ||
208 | return chan; | ||
209 | dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n", | ||
210 | __func__, __LINE__); | ||
211 | return NULL; | ||
212 | } | ||
213 | |||
190 | void mic_sysfs_init(struct mic_device *mdev); | 214 | void mic_sysfs_init(struct mic_device *mdev); |
191 | int mic_start(struct mic_device *mdev, const char *buf); | 215 | int mic_start(struct mic_device *mdev, const char *buf); |
192 | void mic_stop(struct mic_device *mdev, bool force); | 216 | void mic_stop(struct mic_device *mdev, bool force); |
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c index dbc5afde1392..d686f2846ac7 100644 --- a/drivers/misc/mic/host/mic_intr.c +++ b/drivers/misc/mic/host/mic_intr.c | |||
@@ -24,28 +24,29 @@ | |||
24 | #include "../common/mic_dev.h" | 24 | #include "../common/mic_dev.h" |
25 | #include "mic_device.h" | 25 | #include "mic_device.h" |
26 | 26 | ||
27 | /* | 27 | static irqreturn_t mic_thread_fn(int irq, void *dev) |
28 | * mic_invoke_callback - Invoke callback functions registered for | ||
29 | * the corresponding source id. | ||
30 | * | ||
31 | * @mdev: pointer to the mic_device instance | ||
32 | * @idx: The interrupt source id. | ||
33 | * | ||
34 | * Returns none. | ||
35 | */ | ||
36 | static inline void mic_invoke_callback(struct mic_device *mdev, int idx) | ||
37 | { | 28 | { |
29 | struct mic_device *mdev = dev; | ||
30 | struct mic_intr_info *intr_info = mdev->intr_info; | ||
31 | struct mic_irq_info *irq_info = &mdev->irq_info; | ||
38 | struct mic_intr_cb *intr_cb; | 32 | struct mic_intr_cb *intr_cb; |
39 | struct pci_dev *pdev = container_of(mdev->sdev->parent, | 33 | struct pci_dev *pdev = container_of(mdev->sdev->parent, |
40 | struct pci_dev, dev); | 34 | struct pci_dev, dev); |
35 | int i; | ||
41 | 36 | ||
42 | spin_lock(&mdev->irq_info.mic_intr_lock); | 37 | spin_lock(&irq_info->mic_thread_lock); |
43 | list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list) | 38 | for (i = intr_info->intr_start_idx[MIC_INTR_DB]; |
44 | if (intr_cb->func) | 39 | i < intr_info->intr_len[MIC_INTR_DB]; i++) |
45 | intr_cb->func(pdev->irq, intr_cb->data); | 40 | if (test_and_clear_bit(i, &irq_info->mask)) { |
46 | spin_unlock(&mdev->irq_info.mic_intr_lock); | 41 | list_for_each_entry(intr_cb, &irq_info->cb_list[i], |
42 | list) | ||
43 | if (intr_cb->thread_fn) | ||
44 | intr_cb->thread_fn(pdev->irq, | ||
45 | intr_cb->data); | ||
46 | } | ||
47 | spin_unlock(&irq_info->mic_thread_lock); | ||
48 | return IRQ_HANDLED; | ||
47 | } | 49 | } |
48 | |||
49 | /** | 50 | /** |
50 | * mic_interrupt - Generic interrupt handler for | 51 | * mic_interrupt - Generic interrupt handler for |
51 | * MSI and INTx based interrupts. | 52 | * MSI and INTx based interrupts. |
@@ -53,7 +54,11 @@ static inline void mic_invoke_callback(struct mic_device *mdev, int idx) | |||
53 | static irqreturn_t mic_interrupt(int irq, void *dev) | 54 | static irqreturn_t mic_interrupt(int irq, void *dev) |
54 | { | 55 | { |
55 | struct mic_device *mdev = dev; | 56 | struct mic_device *mdev = dev; |
56 | struct mic_intr_info *info = mdev->intr_info; | 57 | struct mic_intr_info *intr_info = mdev->intr_info; |
58 | struct mic_irq_info *irq_info = &mdev->irq_info; | ||
59 | struct mic_intr_cb *intr_cb; | ||
60 | struct pci_dev *pdev = container_of(mdev->sdev->parent, | ||
61 | struct pci_dev, dev); | ||
57 | u32 mask; | 62 | u32 mask; |
58 | int i; | 63 | int i; |
59 | 64 | ||
@@ -61,12 +66,19 @@ static irqreturn_t mic_interrupt(int irq, void *dev) | |||
61 | if (!mask) | 66 | if (!mask) |
62 | return IRQ_NONE; | 67 | return IRQ_NONE; |
63 | 68 | ||
64 | for (i = info->intr_start_idx[MIC_INTR_DB]; | 69 | spin_lock(&irq_info->mic_intr_lock); |
65 | i < info->intr_len[MIC_INTR_DB]; i++) | 70 | for (i = intr_info->intr_start_idx[MIC_INTR_DB]; |
66 | if (mask & BIT(i)) | 71 | i < intr_info->intr_len[MIC_INTR_DB]; i++) |
67 | mic_invoke_callback(mdev, i); | 72 | if (mask & BIT(i)) { |
68 | 73 | list_for_each_entry(intr_cb, &irq_info->cb_list[i], | |
69 | return IRQ_HANDLED; | 74 | list) |
75 | if (intr_cb->handler) | ||
76 | intr_cb->handler(pdev->irq, | ||
77 | intr_cb->data); | ||
78 | set_bit(i, &irq_info->mask); | ||
79 | } | ||
80 | spin_unlock(&irq_info->mic_intr_lock); | ||
81 | return IRQ_WAKE_THREAD; | ||
70 | } | 82 | } |
71 | 83 | ||
72 | /* Return the interrupt offset from the index. Index is 0 based. */ | 84 | /* Return the interrupt offset from the index. Index is 0 based. */ |
@@ -99,14 +111,15 @@ static struct msix_entry *mic_get_available_vector(struct mic_device *mdev) | |||
99 | * | 111 | * |
100 | * @mdev: pointer to the mic_device instance | 112 | * @mdev: pointer to the mic_device instance |
101 | * @idx: The source id to be registered. | 113 | * @idx: The source id to be registered. |
102 | * @func: The function to be called when the source id receives | 114 | * @handler: The function to be called when the source id receives |
103 | * the interrupt. | 115 | * the interrupt. |
116 | * @thread_fn: thread fn. corresponding to the handler | ||
104 | * @data: Private data of the requester. | 117 | * @data: Private data of the requester. |
105 | * Return the callback structure that was registered or an | 118 | * Return the callback structure that was registered or an |
106 | * appropriate error on failure. | 119 | * appropriate error on failure. |
107 | */ | 120 | */ |
108 | static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev, | 121 | static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev, |
109 | u8 idx, irqreturn_t (*func) (int irq, void *dev), | 122 | u8 idx, irq_handler_t handler, irq_handler_t thread_fn, |
110 | void *data) | 123 | void *data) |
111 | { | 124 | { |
112 | struct mic_intr_cb *intr_cb; | 125 | struct mic_intr_cb *intr_cb; |
@@ -117,7 +130,8 @@ static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev, | |||
117 | if (!intr_cb) | 130 | if (!intr_cb) |
118 | return ERR_PTR(-ENOMEM); | 131 | return ERR_PTR(-ENOMEM); |
119 | 132 | ||
120 | intr_cb->func = func; | 133 | intr_cb->handler = handler; |
134 | intr_cb->thread_fn = thread_fn; | ||
121 | intr_cb->data = data; | 135 | intr_cb->data = data; |
122 | intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida, | 136 | intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida, |
123 | 0, 0, GFP_KERNEL); | 137 | 0, 0, GFP_KERNEL); |
@@ -126,9 +140,11 @@ static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev, | |||
126 | goto ida_fail; | 140 | goto ida_fail; |
127 | } | 141 | } |
128 | 142 | ||
143 | spin_lock(&mdev->irq_info.mic_thread_lock); | ||
129 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); | 144 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); |
130 | list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]); | 145 | list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]); |
131 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); | 146 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); |
147 | spin_unlock(&mdev->irq_info.mic_thread_lock); | ||
132 | 148 | ||
133 | return intr_cb; | 149 | return intr_cb; |
134 | ida_fail: | 150 | ida_fail: |
@@ -152,8 +168,9 @@ static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx) | |||
152 | unsigned long flags; | 168 | unsigned long flags; |
153 | int i; | 169 | int i; |
154 | 170 | ||
171 | spin_lock(&mdev->irq_info.mic_thread_lock); | ||
172 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); | ||
155 | for (i = 0; i < MIC_NUM_OFFSETS; i++) { | 173 | for (i = 0; i < MIC_NUM_OFFSETS; i++) { |
156 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); | ||
157 | list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { | 174 | list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { |
158 | intr_cb = list_entry(pos, struct mic_intr_cb, list); | 175 | intr_cb = list_entry(pos, struct mic_intr_cb, list); |
159 | if (intr_cb->cb_id == idx) { | 176 | if (intr_cb->cb_id == idx) { |
@@ -163,11 +180,13 @@ static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx) | |||
163 | kfree(intr_cb); | 180 | kfree(intr_cb); |
164 | spin_unlock_irqrestore( | 181 | spin_unlock_irqrestore( |
165 | &mdev->irq_info.mic_intr_lock, flags); | 182 | &mdev->irq_info.mic_intr_lock, flags); |
183 | spin_unlock(&mdev->irq_info.mic_thread_lock); | ||
166 | return i; | 184 | return i; |
167 | } | 185 | } |
168 | } | 186 | } |
169 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); | ||
170 | } | 187 | } |
188 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); | ||
189 | spin_unlock(&mdev->irq_info.mic_thread_lock); | ||
171 | return MIC_NUM_OFFSETS; | 190 | return MIC_NUM_OFFSETS; |
172 | } | 191 | } |
173 | 192 | ||
@@ -242,6 +261,7 @@ static int mic_setup_callbacks(struct mic_device *mdev) | |||
242 | INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]); | 261 | INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]); |
243 | ida_init(&mdev->irq_info.cb_ida); | 262 | ida_init(&mdev->irq_info.cb_ida); |
244 | spin_lock_init(&mdev->irq_info.mic_intr_lock); | 263 | spin_lock_init(&mdev->irq_info.mic_intr_lock); |
264 | spin_lock_init(&mdev->irq_info.mic_thread_lock); | ||
245 | return 0; | 265 | return 0; |
246 | } | 266 | } |
247 | 267 | ||
@@ -258,14 +278,12 @@ static void mic_release_callbacks(struct mic_device *mdev) | |||
258 | struct mic_intr_cb *intr_cb; | 278 | struct mic_intr_cb *intr_cb; |
259 | int i; | 279 | int i; |
260 | 280 | ||
281 | spin_lock(&mdev->irq_info.mic_thread_lock); | ||
282 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); | ||
261 | for (i = 0; i < MIC_NUM_OFFSETS; i++) { | 283 | for (i = 0; i < MIC_NUM_OFFSETS; i++) { |
262 | spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags); | ||
263 | 284 | ||
264 | if (list_empty(&mdev->irq_info.cb_list[i])) { | 285 | if (list_empty(&mdev->irq_info.cb_list[i])) |
265 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, | ||
266 | flags); | ||
267 | break; | 286 | break; |
268 | } | ||
269 | 287 | ||
270 | list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { | 288 | list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) { |
271 | intr_cb = list_entry(pos, struct mic_intr_cb, list); | 289 | intr_cb = list_entry(pos, struct mic_intr_cb, list); |
@@ -274,8 +292,9 @@ static void mic_release_callbacks(struct mic_device *mdev) | |||
274 | intr_cb->cb_id); | 292 | intr_cb->cb_id); |
275 | kfree(intr_cb); | 293 | kfree(intr_cb); |
276 | } | 294 | } |
277 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); | ||
278 | } | 295 | } |
296 | spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags); | ||
297 | spin_unlock(&mdev->irq_info.mic_thread_lock); | ||
279 | ida_destroy(&mdev->irq_info.cb_ida); | 298 | ida_destroy(&mdev->irq_info.cb_ida); |
280 | kfree(mdev->irq_info.cb_list); | 299 | kfree(mdev->irq_info.cb_list); |
281 | } | 300 | } |
@@ -313,7 +332,8 @@ static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev) | |||
313 | goto err_nomem2; | 332 | goto err_nomem2; |
314 | } | 333 | } |
315 | 334 | ||
316 | rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev); | 335 | rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn, |
336 | 0, "mic-msi", mdev); | ||
317 | if (rc) { | 337 | if (rc) { |
318 | dev_err(&pdev->dev, "Error allocating MSI interrupt\n"); | 338 | dev_err(&pdev->dev, "Error allocating MSI interrupt\n"); |
319 | goto err_irq_req_fail; | 339 | goto err_irq_req_fail; |
@@ -353,8 +373,8 @@ static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev) | |||
353 | goto err_nomem; | 373 | goto err_nomem; |
354 | } | 374 | } |
355 | 375 | ||
356 | rc = request_irq(pdev->irq, mic_interrupt, | 376 | rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn, |
357 | IRQF_SHARED, "mic-intx", mdev); | 377 | IRQF_SHARED, "mic-intx", mdev); |
358 | if (rc) | 378 | if (rc) |
359 | goto err; | 379 | goto err; |
360 | 380 | ||
@@ -391,13 +411,14 @@ int mic_next_db(struct mic_device *mdev) | |||
391 | #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT) | 411 | #define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT) |
392 | 412 | ||
393 | /** | 413 | /** |
394 | * mic_request_irq - request an irq. mic_mutex needs | 414 | * mic_request_threaded_irq - request an irq. mic_mutex needs |
395 | * to be held before calling this function. | 415 | * to be held before calling this function. |
396 | * | 416 | * |
397 | * @mdev: pointer to mic_device instance | 417 | * @mdev: pointer to mic_device instance |
398 | * @func: The callback function that handles the interrupt. | 418 | * @handler: The callback function that handles the interrupt. |
399 | * The function needs to call ack_interrupts | 419 | * The function needs to call ack_interrupts |
400 | * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts. | 420 | * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts. |
421 | * @thread_fn: thread fn required by request_threaded_irq. | ||
401 | * @name: The ASCII name of the callee requesting the irq. | 422 | * @name: The ASCII name of the callee requesting the irq. |
402 | * @data: private data that is returned back when calling the | 423 | * @data: private data that is returned back when calling the |
403 | * function handler. | 424 | * function handler. |
@@ -412,10 +433,11 @@ int mic_next_db(struct mic_device *mdev) | |||
412 | * error code. | 433 | * error code. |
413 | * | 434 | * |
414 | */ | 435 | */ |
415 | struct mic_irq *mic_request_irq(struct mic_device *mdev, | 436 | struct mic_irq * |
416 | irqreturn_t (*func)(int irq, void *dev), | 437 | mic_request_threaded_irq(struct mic_device *mdev, |
417 | const char *name, void *data, int intr_src, | 438 | irq_handler_t handler, irq_handler_t thread_fn, |
418 | enum mic_intr_type type) | 439 | const char *name, void *data, int intr_src, |
440 | enum mic_intr_type type) | ||
419 | { | 441 | { |
420 | u16 offset; | 442 | u16 offset; |
421 | int rc = 0; | 443 | int rc = 0; |
@@ -444,7 +466,8 @@ struct mic_irq *mic_request_irq(struct mic_device *mdev, | |||
444 | goto err; | 466 | goto err; |
445 | } | 467 | } |
446 | 468 | ||
447 | rc = request_irq(msix->vector, func, 0, name, data); | 469 | rc = request_threaded_irq(msix->vector, handler, thread_fn, |
470 | 0, name, data); | ||
448 | if (rc) { | 471 | if (rc) { |
449 | dev_dbg(mdev->sdev->parent, | 472 | dev_dbg(mdev->sdev->parent, |
450 | "request irq failed rc = %d\n", rc); | 473 | "request irq failed rc = %d\n", rc); |
@@ -458,8 +481,8 @@ struct mic_irq *mic_request_irq(struct mic_device *mdev, | |||
458 | dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n", | 481 | dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n", |
459 | msix->vector, intr_src); | 482 | msix->vector, intr_src); |
460 | } else { | 483 | } else { |
461 | intr_cb = mic_register_intr_callback(mdev, | 484 | intr_cb = mic_register_intr_callback(mdev, offset, handler, |
462 | offset, func, data); | 485 | thread_fn, data); |
463 | if (IS_ERR(intr_cb)) { | 486 | if (IS_ERR(intr_cb)) { |
464 | dev_err(mdev->sdev->parent, | 487 | dev_err(mdev->sdev->parent, |
465 | "No available callback entries for use\n"); | 488 | "No available callback entries for use\n"); |
@@ -487,9 +510,9 @@ err: | |||
487 | * needs to be held before calling this function. | 510 | * needs to be held before calling this function. |
488 | * | 511 | * |
489 | * @mdev: pointer to mic_device instance | 512 | * @mdev: pointer to mic_device instance |
490 | * @cookie: cookie obtained during a successful call to mic_request_irq | 513 | * @cookie: cookie obtained during a successful call to mic_request_threaded_irq |
491 | * @data: private data specified by the calling function during the | 514 | * @data: private data specified by the calling function during the |
492 | * mic_request_irq | 515 | * mic_request_threaded_irq |
493 | * | 516 | * |
494 | * returns: none. | 517 | * returns: none. |
495 | */ | 518 | */ |
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h index 6091aa97e116..9f783d4ad7f1 100644 --- a/drivers/misc/mic/host/mic_intr.h +++ b/drivers/misc/mic/host/mic_intr.h | |||
@@ -21,12 +21,15 @@ | |||
21 | #ifndef _MIC_INTR_H_ | 21 | #ifndef _MIC_INTR_H_ |
22 | #define _MIC_INTR_H_ | 22 | #define _MIC_INTR_H_ |
23 | 23 | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/interrupt.h> | ||
24 | /* | 26 | /* |
25 | * The minimum number of msix vectors required for normal operation. | 27 | * The minimum number of msix vectors required for normal operation. |
26 | * 3 for virtio network, console and block devices. | 28 | * 3 for virtio network, console and block devices. |
27 | * 1 for card shutdown notifications. | 29 | * 1 for card shutdown notifications. |
30 | * 4 for host owned DMA channels. | ||
28 | */ | 31 | */ |
29 | #define MIC_MIN_MSIX 4 | 32 | #define MIC_MIN_MSIX 8 |
30 | #define MIC_NUM_OFFSETS 32 | 33 | #define MIC_NUM_OFFSETS 32 |
31 | 34 | ||
32 | /** | 35 | /** |
@@ -68,7 +71,11 @@ struct mic_intr_info { | |||
68 | * @num_vectors: The number of MSI/MSI-x vectors that have been allocated. | 71 | * @num_vectors: The number of MSI/MSI-x vectors that have been allocated. |
69 | * @cb_ida: callback ID allocator to track the callbacks registered. | 72 | * @cb_ida: callback ID allocator to track the callbacks registered. |
70 | * @mic_intr_lock: spinlock to protect the interrupt callback list. | 73 | * @mic_intr_lock: spinlock to protect the interrupt callback list. |
74 | * @mic_thread_lock: spinlock to protect the thread callback list. | ||
75 | * This lock is used to protect against thread_fn while | ||
76 | * mic_intr_lock is used to protect against interrupt handler. | ||
71 | * @cb_list: Array of callback lists one for each source. | 77 | * @cb_list: Array of callback lists one for each source. |
78 | * @mask: Mask used by the main thread fn to call the underlying thread fns. | ||
72 | */ | 79 | */ |
73 | struct mic_irq_info { | 80 | struct mic_irq_info { |
74 | int next_avail_src; | 81 | int next_avail_src; |
@@ -77,19 +84,23 @@ struct mic_irq_info { | |||
77 | u16 num_vectors; | 84 | u16 num_vectors; |
78 | struct ida cb_ida; | 85 | struct ida cb_ida; |
79 | spinlock_t mic_intr_lock; | 86 | spinlock_t mic_intr_lock; |
87 | spinlock_t mic_thread_lock; | ||
80 | struct list_head *cb_list; | 88 | struct list_head *cb_list; |
89 | unsigned long mask; | ||
81 | }; | 90 | }; |
82 | 91 | ||
83 | /** | 92 | /** |
84 | * struct mic_intr_cb - Interrupt callback structure. | 93 | * struct mic_intr_cb - Interrupt callback structure. |
85 | * | 94 | * |
86 | * @func: The callback function | 95 | * @handler: The callback function |
96 | * @thread_fn: The thread_fn. | ||
87 | * @data: Private data of the requester. | 97 | * @data: Private data of the requester. |
88 | * @cb_id: The callback id. Identifies this callback. | 98 | * @cb_id: The callback id. Identifies this callback. |
89 | * @list: list head pointing to the next callback structure. | 99 | * @list: list head pointing to the next callback structure. |
90 | */ | 100 | */ |
91 | struct mic_intr_cb { | 101 | struct mic_intr_cb { |
92 | irqreturn_t (*func) (int irq, void *data); | 102 | irq_handler_t handler; |
103 | irq_handler_t thread_fn; | ||
93 | void *data; | 104 | void *data; |
94 | int cb_id; | 105 | int cb_id; |
95 | struct list_head list; | 106 | struct list_head list; |
@@ -124,11 +135,11 @@ struct mic_hw_intr_ops { | |||
124 | }; | 135 | }; |
125 | 136 | ||
126 | int mic_next_db(struct mic_device *mdev); | 137 | int mic_next_db(struct mic_device *mdev); |
127 | struct mic_irq *mic_request_irq(struct mic_device *mdev, | 138 | struct mic_irq * |
128 | irqreturn_t (*func)(int irq, void *data), | 139 | mic_request_threaded_irq(struct mic_device *mdev, |
129 | const char *name, void *data, int intr_src, | 140 | irq_handler_t handler, irq_handler_t thread_fn, |
130 | enum mic_intr_type type); | 141 | const char *name, void *data, int intr_src, |
131 | 142 | enum mic_intr_type type); | |
132 | void mic_free_irq(struct mic_device *mdev, | 143 | void mic_free_irq(struct mic_device *mdev, |
133 | struct mic_irq *cookie, void *data); | 144 | struct mic_irq *cookie, void *data); |
134 | int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev); | 145 | int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev); |
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c index c04a021e20c7..ab37a3117d23 100644 --- a/drivers/misc/mic/host/mic_main.c +++ b/drivers/misc/mic/host/mic_main.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | static const char mic_driver_name[] = "mic"; | 39 | static const char mic_driver_name[] = "mic"; |
40 | 40 | ||
41 | static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = { | 41 | static const struct pci_device_id mic_pci_tbl[] = { |
42 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)}, | 42 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)}, |
43 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)}, | 43 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)}, |
44 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)}, | 44 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)}, |
@@ -389,8 +389,9 @@ static int mic_probe(struct pci_dev *pdev, | |||
389 | mutex_lock(&mdev->mic_mutex); | 389 | mutex_lock(&mdev->mic_mutex); |
390 | 390 | ||
391 | mdev->shutdown_db = mic_next_db(mdev); | 391 | mdev->shutdown_db = mic_next_db(mdev); |
392 | mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db, | 392 | mdev->shutdown_cookie = mic_request_threaded_irq(mdev, mic_shutdown_db, |
393 | "shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB); | 393 | NULL, "shutdown-interrupt", mdev, |
394 | mdev->shutdown_db, MIC_INTR_DB); | ||
394 | if (IS_ERR(mdev->shutdown_cookie)) { | 395 | if (IS_ERR(mdev->shutdown_cookie)) { |
395 | rc = PTR_ERR(mdev->shutdown_cookie); | 396 | rc = PTR_ERR(mdev->shutdown_cookie); |
396 | mutex_unlock(&mdev->mic_mutex); | 397 | mutex_unlock(&mdev->mic_mutex); |
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index 7e1ef0ebbb80..a020e4eb435a 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c | |||
@@ -21,60 +21,157 @@ | |||
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | 24 | #include <linux/dmaengine.h> | |
25 | #include <linux/mic_common.h> | 25 | #include <linux/mic_common.h> |
26 | |||
26 | #include "../common/mic_dev.h" | 27 | #include "../common/mic_dev.h" |
27 | #include "mic_device.h" | 28 | #include "mic_device.h" |
28 | #include "mic_smpt.h" | 29 | #include "mic_smpt.h" |
29 | #include "mic_virtio.h" | 30 | #include "mic_virtio.h" |
30 | 31 | ||
31 | /* | 32 | /* |
32 | * Initiates the copies across the PCIe bus from card memory to | 33 | * Size of the internal buffer used during DMA's as an intermediate buffer |
33 | * a user space buffer. | 34 | * for copy to/from user. |
34 | */ | 35 | */ |
35 | static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, | 36 | #define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL) |
36 | void __user *ubuf, size_t len, u64 addr) | 37 | |
38 | static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst, | ||
39 | dma_addr_t src, size_t len) | ||
37 | { | 40 | { |
38 | int err; | 41 | int err = 0; |
39 | void __iomem *dbuf = mvdev->mdev->aper.va + addr; | 42 | struct dma_async_tx_descriptor *tx; |
40 | /* | 43 | struct dma_chan *mic_ch = mdev->dma_ch; |
41 | * We are copying from IO below an should ideally use something | 44 | |
42 | * like copy_to_user_fromio(..) if it existed. | 45 | if (!mic_ch) { |
43 | */ | 46 | err = -EBUSY; |
44 | if (copy_to_user(ubuf, (void __force *)dbuf, len)) { | 47 | goto error; |
45 | err = -EFAULT; | 48 | } |
46 | dev_err(mic_dev(mvdev), "%s %d err %d\n", | 49 | |
50 | tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len, | ||
51 | DMA_PREP_FENCE); | ||
52 | if (!tx) { | ||
53 | err = -ENOMEM; | ||
54 | goto error; | ||
55 | } else { | ||
56 | dma_cookie_t cookie = tx->tx_submit(tx); | ||
57 | |||
58 | err = dma_submit_error(cookie); | ||
59 | if (err) | ||
60 | goto error; | ||
61 | err = dma_sync_wait(mic_ch, cookie); | ||
62 | } | ||
63 | error: | ||
64 | if (err) | ||
65 | dev_err(mdev->sdev->parent, "%s %d err %d\n", | ||
47 | __func__, __LINE__, err); | 66 | __func__, __LINE__, err); |
48 | goto err; | 67 | return err; |
68 | } | ||
69 | |||
70 | /* | ||
71 | * Initiates the copies across the PCIe bus from card memory to a user | ||
72 | * space buffer. When transfers are done using DMA, source/destination | ||
73 | * addresses and transfer length must follow the alignment requirements of | ||
74 | * the MIC DMA engine. | ||
75 | */ | ||
76 | static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf, | ||
77 | size_t len, u64 daddr, size_t dlen, | ||
78 | int vr_idx) | ||
79 | { | ||
80 | struct mic_device *mdev = mvdev->mdev; | ||
81 | void __iomem *dbuf = mdev->aper.va + daddr; | ||
82 | struct mic_vringh *mvr = &mvdev->mvr[vr_idx]; | ||
83 | size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align; | ||
84 | size_t dma_offset; | ||
85 | size_t partlen; | ||
86 | int err; | ||
87 | |||
88 | dma_offset = daddr - round_down(daddr, dma_alignment); | ||
89 | daddr -= dma_offset; | ||
90 | len += dma_offset; | ||
91 | |||
92 | while (len) { | ||
93 | partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE); | ||
94 | |||
95 | err = mic_sync_dma(mdev, mvr->buf_da, daddr, | ||
96 | ALIGN(partlen, dma_alignment)); | ||
97 | if (err) | ||
98 | goto err; | ||
99 | |||
100 | if (copy_to_user(ubuf, mvr->buf + dma_offset, | ||
101 | partlen - dma_offset)) { | ||
102 | err = -EFAULT; | ||
103 | goto err; | ||
104 | } | ||
105 | daddr += partlen; | ||
106 | ubuf += partlen; | ||
107 | dbuf += partlen; | ||
108 | mvdev->in_bytes_dma += partlen; | ||
109 | mvdev->in_bytes += partlen; | ||
110 | len -= partlen; | ||
111 | dma_offset = 0; | ||
49 | } | 112 | } |
50 | mvdev->in_bytes += len; | 113 | return 0; |
51 | err = 0; | ||
52 | err: | 114 | err: |
115 | dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); | ||
53 | return err; | 116 | return err; |
54 | } | 117 | } |
55 | 118 | ||
56 | /* | 119 | /* |
57 | * Initiates copies across the PCIe bus from a user space | 120 | * Initiates copies across the PCIe bus from a user space buffer to card |
58 | * buffer to card memory. | 121 | * memory. When transfers are done using DMA, source/destination addresses |
122 | * and transfer length must follow the alignment requirements of the MIC | ||
123 | * DMA engine. | ||
59 | */ | 124 | */ |
60 | static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, | 125 | static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf, |
61 | void __user *ubuf, size_t len, u64 addr) | 126 | size_t len, u64 daddr, size_t dlen, |
127 | int vr_idx) | ||
62 | { | 128 | { |
129 | struct mic_device *mdev = mvdev->mdev; | ||
130 | void __iomem *dbuf = mdev->aper.va + daddr; | ||
131 | struct mic_vringh *mvr = &mvdev->mvr[vr_idx]; | ||
132 | size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align; | ||
133 | size_t partlen; | ||
63 | int err; | 134 | int err; |
64 | void __iomem *dbuf = mvdev->mdev->aper.va + addr; | 135 | |
136 | if (daddr & (dma_alignment - 1)) { | ||
137 | mvdev->tx_dst_unaligned += len; | ||
138 | goto memcpy; | ||
139 | } else if (ALIGN(len, dma_alignment) > dlen) { | ||
140 | mvdev->tx_len_unaligned += len; | ||
141 | goto memcpy; | ||
142 | } | ||
143 | |||
144 | while (len) { | ||
145 | partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE); | ||
146 | |||
147 | if (copy_from_user(mvr->buf, ubuf, partlen)) { | ||
148 | err = -EFAULT; | ||
149 | goto err; | ||
150 | } | ||
151 | err = mic_sync_dma(mdev, daddr, mvr->buf_da, | ||
152 | ALIGN(partlen, dma_alignment)); | ||
153 | if (err) | ||
154 | goto err; | ||
155 | daddr += partlen; | ||
156 | ubuf += partlen; | ||
157 | dbuf += partlen; | ||
158 | mvdev->out_bytes_dma += partlen; | ||
159 | mvdev->out_bytes += partlen; | ||
160 | len -= partlen; | ||
161 | } | ||
162 | memcpy: | ||
65 | /* | 163 | /* |
66 | * We are copying to IO below and should ideally use something | 164 | * We are copying to IO below and should ideally use something |
67 | * like copy_from_user_toio(..) if it existed. | 165 | * like copy_from_user_toio(..) if it existed. |
68 | */ | 166 | */ |
69 | if (copy_from_user((void __force *)dbuf, ubuf, len)) { | 167 | if (copy_from_user((void __force *)dbuf, ubuf, len)) { |
70 | err = -EFAULT; | 168 | err = -EFAULT; |
71 | dev_err(mic_dev(mvdev), "%s %d err %d\n", | ||
72 | __func__, __LINE__, err); | ||
73 | goto err; | 169 | goto err; |
74 | } | 170 | } |
75 | mvdev->out_bytes += len; | 171 | mvdev->out_bytes += len; |
76 | err = 0; | 172 | return 0; |
77 | err: | 173 | err: |
174 | dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); | ||
78 | return err; | 175 | return err; |
79 | } | 176 | } |
80 | 177 | ||
@@ -110,7 +207,8 @@ static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov) | |||
110 | * way to override the VRINGH xfer(..) routines as of v3.10. | 207 | * way to override the VRINGH xfer(..) routines as of v3.10. |
111 | */ | 208 | */ |
112 | static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, | 209 | static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, |
113 | void __user *ubuf, size_t len, bool read, size_t *out_len) | 210 | void __user *ubuf, size_t len, bool read, int vr_idx, |
211 | size_t *out_len) | ||
114 | { | 212 | { |
115 | int ret = 0; | 213 | int ret = 0; |
116 | size_t partlen, tot_len = 0; | 214 | size_t partlen, tot_len = 0; |
@@ -118,13 +216,15 @@ static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov, | |||
118 | while (len && iov->i < iov->used) { | 216 | while (len && iov->i < iov->used) { |
119 | partlen = min(iov->iov[iov->i].iov_len, len); | 217 | partlen = min(iov->iov[iov->i].iov_len, len); |
120 | if (read) | 218 | if (read) |
121 | ret = mic_virtio_copy_to_user(mvdev, | 219 | ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen, |
122 | ubuf, partlen, | 220 | (u64)iov->iov[iov->i].iov_base, |
123 | (u64)iov->iov[iov->i].iov_base); | 221 | iov->iov[iov->i].iov_len, |
222 | vr_idx); | ||
124 | else | 223 | else |
125 | ret = mic_virtio_copy_from_user(mvdev, | 224 | ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen, |
126 | ubuf, partlen, | 225 | (u64)iov->iov[iov->i].iov_base, |
127 | (u64)iov->iov[iov->i].iov_base); | 226 | iov->iov[iov->i].iov_len, |
227 | vr_idx); | ||
128 | if (ret) { | 228 | if (ret) { |
129 | dev_err(mic_dev(mvdev), "%s %d err %d\n", | 229 | dev_err(mic_dev(mvdev), "%s %d err %d\n", |
130 | __func__, __LINE__, ret); | 230 | __func__, __LINE__, ret); |
@@ -192,8 +292,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev, | |||
192 | ubuf = iov.iov_base; | 292 | ubuf = iov.iov_base; |
193 | } | 293 | } |
194 | /* Issue all the read descriptors first */ | 294 | /* Issue all the read descriptors first */ |
195 | ret = mic_vringh_copy(mvdev, riov, ubuf, len, | 295 | ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ, |
196 | MIC_VRINGH_READ, &out_len); | 296 | copy->vr_idx, &out_len); |
197 | if (ret) { | 297 | if (ret) { |
198 | dev_err(mic_dev(mvdev), "%s %d err %d\n", | 298 | dev_err(mic_dev(mvdev), "%s %d err %d\n", |
199 | __func__, __LINE__, ret); | 299 | __func__, __LINE__, ret); |
@@ -203,8 +303,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev, | |||
203 | ubuf += out_len; | 303 | ubuf += out_len; |
204 | copy->out_len += out_len; | 304 | copy->out_len += out_len; |
205 | /* Issue the write descriptors next */ | 305 | /* Issue the write descriptors next */ |
206 | ret = mic_vringh_copy(mvdev, wiov, ubuf, len, | 306 | ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ, |
207 | !MIC_VRINGH_READ, &out_len); | 307 | copy->vr_idx, &out_len); |
208 | if (ret) { | 308 | if (ret) { |
209 | dev_err(mic_dev(mvdev), "%s %d err %d\n", | 309 | dev_err(mic_dev(mvdev), "%s %d err %d\n", |
210 | __func__, __LINE__, ret); | 310 | __func__, __LINE__, ret); |
@@ -589,13 +689,19 @@ int mic_virtio_add_device(struct mic_vdev *mvdev, | |||
589 | dev_dbg(mdev->sdev->parent, | 689 | dev_dbg(mdev->sdev->parent, |
590 | "%s %d index %d va %p info %p vr_size 0x%x\n", | 690 | "%s %d index %d va %p info %p vr_size 0x%x\n", |
591 | __func__, __LINE__, i, vr->va, vr->info, vr_size); | 691 | __func__, __LINE__, i, vr->va, vr->info, vr_size); |
692 | mvr->buf = (void *)__get_free_pages(GFP_KERNEL, | ||
693 | get_order(MIC_INT_DMA_BUF_SIZE)); | ||
694 | mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf, | ||
695 | MIC_INT_DMA_BUF_SIZE); | ||
592 | } | 696 | } |
593 | 697 | ||
594 | snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id, | 698 | snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id, |
595 | mvdev->virtio_id); | 699 | mvdev->virtio_id); |
596 | mvdev->virtio_db = mic_next_db(mdev); | 700 | mvdev->virtio_db = mic_next_db(mdev); |
597 | mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler, | 701 | mvdev->virtio_cookie = mic_request_threaded_irq(mdev, |
598 | irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB); | 702 | mic_virtio_intr_handler, |
703 | NULL, irqname, mvdev, | ||
704 | mvdev->virtio_db, MIC_INTR_DB); | ||
599 | if (IS_ERR(mvdev->virtio_cookie)) { | 705 | if (IS_ERR(mvdev->virtio_cookie)) { |
600 | ret = PTR_ERR(mvdev->virtio_cookie); | 706 | ret = PTR_ERR(mvdev->virtio_cookie); |
601 | dev_dbg(mdev->sdev->parent, "request irq failed\n"); | 707 | dev_dbg(mdev->sdev->parent, "request irq failed\n"); |
@@ -671,6 +777,11 @@ skip_hot_remove: | |||
671 | vqconfig = mic_vq_config(mvdev->dd); | 777 | vqconfig = mic_vq_config(mvdev->dd); |
672 | for (i = 0; i < mvdev->dd->num_vq; i++) { | 778 | for (i = 0; i < mvdev->dd->num_vq; i++) { |
673 | struct mic_vringh *mvr = &mvdev->mvr[i]; | 779 | struct mic_vringh *mvr = &mvdev->mvr[i]; |
780 | |||
781 | mic_unmap_single(mvdev->mdev, mvr->buf_da, | ||
782 | MIC_INT_DMA_BUF_SIZE); | ||
783 | free_pages((unsigned long)mvr->buf, | ||
784 | get_order(MIC_INT_DMA_BUF_SIZE)); | ||
674 | vringh_kiov_cleanup(&mvr->riov); | 785 | vringh_kiov_cleanup(&mvr->riov); |
675 | vringh_kiov_cleanup(&mvr->wiov); | 786 | vringh_kiov_cleanup(&mvr->wiov); |
676 | mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address), | 787 | mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address), |
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h index 184f3c84805b..d574efb853d9 100644 --- a/drivers/misc/mic/host/mic_virtio.h +++ b/drivers/misc/mic/host/mic_virtio.h | |||
@@ -46,18 +46,23 @@ | |||
46 | * @vrh: The host VRINGH used for accessing the card vrings. | 46 | * @vrh: The host VRINGH used for accessing the card vrings. |
47 | * @riov: The VRINGH read kernel IOV. | 47 | * @riov: The VRINGH read kernel IOV. |
48 | * @wiov: The VRINGH write kernel IOV. | 48 | * @wiov: The VRINGH write kernel IOV. |
49 | * @head: The VRINGH head index address passed to vringh_getdesc_kern(..). | ||
50 | * @vr_mutex: Mutex for synchronizing access to the VRING. | 49 | * @vr_mutex: Mutex for synchronizing access to the VRING. |
50 | * @buf: Temporary kernel buffer used to copy in/out data | ||
51 | * from/to the card via DMA. | ||
52 | * @buf_da: dma address of buf. | ||
51 | * @mvdev: Back pointer to MIC virtio device for vringh_notify(..). | 53 | * @mvdev: Back pointer to MIC virtio device for vringh_notify(..). |
54 | * @head: The VRINGH head index address passed to vringh_getdesc_kern(..). | ||
52 | */ | 55 | */ |
53 | struct mic_vringh { | 56 | struct mic_vringh { |
54 | struct mic_vring vring; | 57 | struct mic_vring vring; |
55 | struct vringh vrh; | 58 | struct vringh vrh; |
56 | struct vringh_kiov riov; | 59 | struct vringh_kiov riov; |
57 | struct vringh_kiov wiov; | 60 | struct vringh_kiov wiov; |
58 | u16 head; | ||
59 | struct mutex vr_mutex; | 61 | struct mutex vr_mutex; |
62 | void *buf; | ||
63 | dma_addr_t buf_da; | ||
60 | struct mic_vdev *mvdev; | 64 | struct mic_vdev *mvdev; |
65 | u16 head; | ||
61 | }; | 66 | }; |
62 | 67 | ||
63 | /** | 68 | /** |
@@ -69,6 +74,14 @@ struct mic_vringh { | |||
69 | * @poll_wake - Used for waking up threads blocked in poll. | 74 | * @poll_wake - Used for waking up threads blocked in poll. |
70 | * @out_bytes - Debug stats for number of bytes copied from host to card. | 75 | * @out_bytes - Debug stats for number of bytes copied from host to card. |
71 | * @in_bytes - Debug stats for number of bytes copied from card to host. | 76 | * @in_bytes - Debug stats for number of bytes copied from card to host. |
77 | * @out_bytes_dma - Debug stats for number of bytes copied from host to card | ||
78 | * using DMA. | ||
79 | * @in_bytes_dma - Debug stats for number of bytes copied from card to host | ||
80 | * using DMA. | ||
81 | * @tx_len_unaligned - Debug stats for number of bytes copied to the card where | ||
82 | * the transfer length did not have the required DMA alignment. | ||
83 | * @tx_dst_unaligned - Debug stats for number of bytes copied where the | ||
84 | * destination address on the card did not have the required DMA alignment. | ||
72 | * @mvr - Store per VRING data structures. | 85 | * @mvr - Store per VRING data structures. |
73 | * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. | 86 | * @virtio_bh_work - Work struct used to schedule virtio bottom half handling. |
74 | * @dd - Virtio device descriptor. | 87 | * @dd - Virtio device descriptor. |
@@ -84,6 +97,10 @@ struct mic_vdev { | |||
84 | int poll_wake; | 97 | int poll_wake; |
85 | unsigned long out_bytes; | 98 | unsigned long out_bytes; |
86 | unsigned long in_bytes; | 99 | unsigned long in_bytes; |
100 | unsigned long out_bytes_dma; | ||
101 | unsigned long in_bytes_dma; | ||
102 | unsigned long tx_len_unaligned; | ||
103 | unsigned long tx_dst_unaligned; | ||
87 | struct mic_vringh mvr[MIC_MAX_VRINGS]; | 104 | struct mic_vringh mvr[MIC_MAX_VRINGS]; |
88 | struct work_struct virtio_bh_work; | 105 | struct work_struct virtio_bh_work; |
89 | struct mic_device_desc *dd; | 106 | struct mic_device_desc *dd; |
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index 5562fdd3ef4e..b7a21e11dcdf 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c | |||
@@ -549,6 +549,13 @@ struct mic_smpt_ops mic_x100_smpt_ops = { | |||
549 | .set = mic_x100_smpt_set, | 549 | .set = mic_x100_smpt_set, |
550 | }; | 550 | }; |
551 | 551 | ||
552 | static bool mic_x100_dma_filter(struct dma_chan *chan, void *param) | ||
553 | { | ||
554 | if (chan->device->dev->parent == (struct device *)param) | ||
555 | return true; | ||
556 | return false; | ||
557 | } | ||
558 | |||
552 | struct mic_hw_ops mic_x100_ops = { | 559 | struct mic_hw_ops mic_x100_ops = { |
553 | .aper_bar = MIC_X100_APER_BAR, | 560 | .aper_bar = MIC_X100_APER_BAR, |
554 | .mmio_bar = MIC_X100_MMIO_BAR, | 561 | .mmio_bar = MIC_X100_MMIO_BAR, |
@@ -563,6 +570,7 @@ struct mic_hw_ops mic_x100_ops = { | |||
563 | .send_firmware_intr = mic_x100_send_firmware_intr, | 570 | .send_firmware_intr = mic_x100_send_firmware_intr, |
564 | .load_mic_fw = mic_x100_load_firmware, | 571 | .load_mic_fw = mic_x100_load_firmware, |
565 | .get_postcode = mic_x100_get_postcode, | 572 | .get_postcode = mic_x100_get_postcode, |
573 | .dma_filter = mic_x100_dma_filter, | ||
566 | }; | 574 | }; |
567 | 575 | ||
568 | struct mic_hw_intr_ops mic_x100_intr_ops = { | 576 | struct mic_hw_intr_ops mic_x100_intr_ops = { |
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9d3dbb28734b..21c2337bad68 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -244,7 +244,8 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
244 | if (version & 0x8000) | 244 | if (version & 0x8000) |
245 | maj_ver |= 0x0008; | 245 | maj_ver |= 0x0008; |
246 | 246 | ||
247 | sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver); | 247 | sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts", |
248 | chip, maj_ver, min_ver); | ||
248 | 249 | ||
249 | /* to be accessed later via sysfs entry */ | 250 | /* to be accessed later via sysfs entry */ |
250 | kim_gdata->version.full = version; | 251 | kim_gdata->version.full = version; |
@@ -287,7 +288,7 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
287 | long len = 0; | 288 | long len = 0; |
288 | unsigned char *ptr = NULL; | 289 | unsigned char *ptr = NULL; |
289 | unsigned char *action_ptr = NULL; | 290 | unsigned char *action_ptr = NULL; |
290 | unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */ | 291 | unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */ |
291 | int wr_room_space; | 292 | int wr_room_space; |
292 | int cmd_size; | 293 | int cmd_size; |
293 | unsigned long timeout; | 294 | unsigned long timeout; |
@@ -778,7 +779,7 @@ static int kim_probe(struct platform_device *pdev) | |||
778 | pr_info("sysfs entries created\n"); | 779 | pr_info("sysfs entries created\n"); |
779 | 780 | ||
780 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); | 781 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); |
781 | if (IS_ERR(kim_debugfs_dir)) { | 782 | if (!kim_debugfs_dir) { |
782 | pr_err(" debugfs entries creation failed "); | 783 | pr_err(" debugfs entries creation failed "); |
783 | err = -EIO; | 784 | err = -EIO; |
784 | goto err_debugfs_dir; | 785 | goto err_debugfs_dir; |
@@ -788,7 +789,6 @@ static int kim_probe(struct platform_device *pdev) | |||
788 | kim_gdata, &version_debugfs_fops); | 789 | kim_gdata, &version_debugfs_fops); |
789 | debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir, | 790 | debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir, |
790 | kim_gdata, &list_debugfs_fops); | 791 | kim_gdata, &list_debugfs_fops); |
791 | pr_info(" debugfs entries created "); | ||
792 | return 0; | 792 | return 0; |
793 | 793 | ||
794 | err_debugfs_dir: | 794 | err_debugfs_dir: |
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c index 3250fc1df0aa..b3a812384a6f 100644 --- a/drivers/misc/vexpress-syscfg.c +++ b/drivers/misc/vexpress-syscfg.c | |||
@@ -130,7 +130,7 @@ static int vexpress_syscfg_write(void *context, unsigned int index, | |||
130 | return vexpress_syscfg_exec(func, index, true, &val); | 130 | return vexpress_syscfg_exec(func, index, true, &val); |
131 | } | 131 | } |
132 | 132 | ||
133 | struct regmap_config vexpress_syscfg_regmap_config = { | 133 | static struct regmap_config vexpress_syscfg_regmap_config = { |
134 | .lock = vexpress_config_lock, | 134 | .lock = vexpress_config_lock, |
135 | .unlock = vexpress_config_unlock, | 135 | .unlock = vexpress_config_unlock, |
136 | .reg_bits = 32, | 136 | .reg_bits = 32, |
@@ -276,7 +276,7 @@ int vexpress_syscfg_device_register(struct platform_device *pdev) | |||
276 | } | 276 | } |
277 | 277 | ||
278 | 278 | ||
279 | int vexpress_syscfg_probe(struct platform_device *pdev) | 279 | static int vexpress_syscfg_probe(struct platform_device *pdev) |
280 | { | 280 | { |
281 | struct vexpress_syscfg *syscfg; | 281 | struct vexpress_syscfg *syscfg; |
282 | struct resource *res; | 282 | struct resource *res; |
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c index e0d5017785e5..248399a881af 100644 --- a/drivers/misc/vmw_vmci/vmci_guest.c +++ b/drivers/misc/vmw_vmci/vmci_guest.c | |||
@@ -748,7 +748,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) | |||
748 | /* The rest are managed resources and will be freed by PCI core */ | 748 | /* The rest are managed resources and will be freed by PCI core */ |
749 | } | 749 | } |
750 | 750 | ||
751 | static DEFINE_PCI_DEVICE_TABLE(vmci_ids) = { | 751 | static const struct pci_device_id vmci_ids[] = { |
752 | { PCI_DEVICE(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_VMCI), }, | 752 | { PCI_DEVICE(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_VMCI), }, |
753 | { 0 }, | 753 | { 0 }, |
754 | }; | 754 | }; |