.. | .. |
---|
20 | 20 | #include <linux/reboot.h> |
---|
21 | 21 | #include <linux/suspend.h> |
---|
22 | 22 | #include <linux/proc_fs.h> |
---|
| 23 | +#include <linux/genalloc.h> |
---|
| 24 | +#include <linux/dma-mapping.h> |
---|
23 | 25 | #include <asm/isc.h> |
---|
24 | 26 | #include <asm/crw.h> |
---|
25 | 27 | |
---|
.. | .. |
---|
165 | 167 | |
---|
166 | 168 | sch->config.intparm = 0; |
---|
167 | 169 | cio_commit_config(sch); |
---|
| 170 | + kfree(sch->driver_override); |
---|
168 | 171 | kfree(sch->lock); |
---|
169 | 172 | kfree(sch); |
---|
170 | 173 | } |
---|
.. | .. |
---|
224 | 227 | INIT_WORK(&sch->todo_work, css_sch_todo); |
---|
225 | 228 | sch->dev.release = &css_subchannel_release; |
---|
226 | 229 | device_initialize(&sch->dev); |
---|
| 230 | + /* |
---|
| 231 | + * The physical addresses of some the dma structures that can |
---|
| 232 | + * belong to a subchannel need to fit 31 bit width (e.g. ccw). |
---|
| 233 | + */ |
---|
| 234 | + sch->dev.coherent_dma_mask = DMA_BIT_MASK(31); |
---|
| 235 | + /* |
---|
| 236 | + * But we don't have such restrictions imposed on the stuff that |
---|
| 237 | + * is handled by the streaming API. |
---|
| 238 | + */ |
---|
| 239 | + sch->dma_mask = DMA_BIT_MASK(64); |
---|
| 240 | + sch->dev.dma_mask = &sch->dma_mask; |
---|
227 | 241 | return sch; |
---|
228 | 242 | |
---|
229 | 243 | err: |
---|
.. | .. |
---|
315 | 329 | |
---|
316 | 330 | static DEVICE_ATTR_RO(modalias); |
---|
317 | 331 | |
---|
| 332 | +static ssize_t driver_override_store(struct device *dev, |
---|
| 333 | + struct device_attribute *attr, |
---|
| 334 | + const char *buf, size_t count) |
---|
| 335 | +{ |
---|
| 336 | + struct subchannel *sch = to_subchannel(dev); |
---|
| 337 | + char *driver_override, *old, *cp; |
---|
| 338 | + |
---|
| 339 | + /* We need to keep extra room for a newline */ |
---|
| 340 | + if (count >= (PAGE_SIZE - 1)) |
---|
| 341 | + return -EINVAL; |
---|
| 342 | + |
---|
| 343 | + driver_override = kstrndup(buf, count, GFP_KERNEL); |
---|
| 344 | + if (!driver_override) |
---|
| 345 | + return -ENOMEM; |
---|
| 346 | + |
---|
| 347 | + cp = strchr(driver_override, '\n'); |
---|
| 348 | + if (cp) |
---|
| 349 | + *cp = '\0'; |
---|
| 350 | + |
---|
| 351 | + device_lock(dev); |
---|
| 352 | + old = sch->driver_override; |
---|
| 353 | + if (strlen(driver_override)) { |
---|
| 354 | + sch->driver_override = driver_override; |
---|
| 355 | + } else { |
---|
| 356 | + kfree(driver_override); |
---|
| 357 | + sch->driver_override = NULL; |
---|
| 358 | + } |
---|
| 359 | + device_unlock(dev); |
---|
| 360 | + |
---|
| 361 | + kfree(old); |
---|
| 362 | + |
---|
| 363 | + return count; |
---|
| 364 | +} |
---|
| 365 | + |
---|
| 366 | +static ssize_t driver_override_show(struct device *dev, |
---|
| 367 | + struct device_attribute *attr, char *buf) |
---|
| 368 | +{ |
---|
| 369 | + struct subchannel *sch = to_subchannel(dev); |
---|
| 370 | + ssize_t len; |
---|
| 371 | + |
---|
| 372 | + device_lock(dev); |
---|
| 373 | + len = snprintf(buf, PAGE_SIZE, "%s\n", sch->driver_override); |
---|
| 374 | + device_unlock(dev); |
---|
| 375 | + return len; |
---|
| 376 | +} |
---|
| 377 | +static DEVICE_ATTR_RW(driver_override); |
---|
| 378 | + |
---|
318 | 379 | static struct attribute *subch_attrs[] = { |
---|
319 | 380 | &dev_attr_type.attr, |
---|
320 | 381 | &dev_attr_modalias.attr, |
---|
| 382 | + &dev_attr_driver_override.attr, |
---|
321 | 383 | NULL, |
---|
322 | 384 | }; |
---|
323 | 385 | |
---|
.. | .. |
---|
451 | 513 | } |
---|
452 | 514 | |
---|
453 | 515 | static int |
---|
454 | | -check_subchannel(struct device * dev, void * data) |
---|
| 516 | +check_subchannel(struct device *dev, const void *data) |
---|
455 | 517 | { |
---|
456 | 518 | struct subchannel *sch; |
---|
457 | | - struct subchannel_id *schid = data; |
---|
| 519 | + struct subchannel_id *schid = (void *)data; |
---|
458 | 520 | |
---|
459 | 521 | sch = to_subchannel(dev); |
---|
460 | 522 | return schid_equal(&sch->schid, schid); |
---|
.. | .. |
---|
809 | 871 | if (css_general_characteristics.mcss) { |
---|
810 | 872 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
---|
811 | 873 | css->global_pgid.pgid_high.ext_cssid.cssid = |
---|
812 | | - (css->cssid < 0) ? 0 : css->cssid; |
---|
| 874 | + css->id_valid ? css->cssid : 0; |
---|
813 | 875 | } else { |
---|
814 | 876 | css->global_pgid.pgid_high.cpu_addr = stap(); |
---|
815 | 877 | } |
---|
.. | .. |
---|
832 | 894 | { |
---|
833 | 895 | struct channel_subsystem *css = to_css(dev); |
---|
834 | 896 | |
---|
835 | | - if (css->cssid < 0) |
---|
| 897 | + if (!css->id_valid) |
---|
836 | 898 | return -EINVAL; |
---|
837 | 899 | |
---|
838 | 900 | return sprintf(buf, "%x\n", css->cssid); |
---|
.. | .. |
---|
921 | 983 | dev_set_name(&css->device, "css%x", nr); |
---|
922 | 984 | css->device.groups = cssdev_attr_groups; |
---|
923 | 985 | css->device.release = channel_subsystem_release; |
---|
| 986 | + /* |
---|
| 987 | + * We currently allocate notifier bits with this (using |
---|
| 988 | + * css->device as the device argument with the DMA API) |
---|
| 989 | + * and are fine with 64 bit addresses. |
---|
| 990 | + */ |
---|
| 991 | + css->device.coherent_dma_mask = DMA_BIT_MASK(64); |
---|
| 992 | + css->device.dma_mask = &css->device.coherent_dma_mask; |
---|
924 | 993 | |
---|
925 | 994 | mutex_init(&css->mutex); |
---|
926 | | - css->cssid = chsc_get_cssid(nr); |
---|
| 995 | + ret = chsc_get_cssid_iid(nr, &css->cssid, &css->iid); |
---|
| 996 | + if (!ret) { |
---|
| 997 | + css->id_valid = true; |
---|
| 998 | + pr_info("Partition identifier %01x.%01x\n", css->cssid, |
---|
| 999 | + css->iid); |
---|
| 1000 | + } |
---|
927 | 1001 | css_generate_pgid(css, (u32) (get_tod_clock() >> 32)); |
---|
928 | 1002 | |
---|
929 | 1003 | ret = device_register(&css->device); |
---|
.. | .. |
---|
1040 | 1114 | .notifier_call = css_power_event, |
---|
1041 | 1115 | }; |
---|
1042 | 1116 | |
---|
| 1117 | +#define CIO_DMA_GFP (GFP_KERNEL | __GFP_ZERO) |
---|
| 1118 | +static struct gen_pool *cio_dma_pool; |
---|
| 1119 | + |
---|
| 1120 | +/* Currently cio supports only a single css */ |
---|
| 1121 | +struct device *cio_get_dma_css_dev(void) |
---|
| 1122 | +{ |
---|
| 1123 | + return &channel_subsystems[0]->device; |
---|
| 1124 | +} |
---|
| 1125 | + |
---|
| 1126 | +struct gen_pool *cio_gp_dma_create(struct device *dma_dev, int nr_pages) |
---|
| 1127 | +{ |
---|
| 1128 | + struct gen_pool *gp_dma; |
---|
| 1129 | + void *cpu_addr; |
---|
| 1130 | + dma_addr_t dma_addr; |
---|
| 1131 | + int i; |
---|
| 1132 | + |
---|
| 1133 | + gp_dma = gen_pool_create(3, -1); |
---|
| 1134 | + if (!gp_dma) |
---|
| 1135 | + return NULL; |
---|
| 1136 | + for (i = 0; i < nr_pages; ++i) { |
---|
| 1137 | + cpu_addr = dma_alloc_coherent(dma_dev, PAGE_SIZE, &dma_addr, |
---|
| 1138 | + CIO_DMA_GFP); |
---|
| 1139 | + if (!cpu_addr) |
---|
| 1140 | + return gp_dma; |
---|
| 1141 | + gen_pool_add_virt(gp_dma, (unsigned long) cpu_addr, |
---|
| 1142 | + dma_addr, PAGE_SIZE, -1); |
---|
| 1143 | + } |
---|
| 1144 | + return gp_dma; |
---|
| 1145 | +} |
---|
| 1146 | + |
---|
| 1147 | +static void __gp_dma_free_dma(struct gen_pool *pool, |
---|
| 1148 | + struct gen_pool_chunk *chunk, void *data) |
---|
| 1149 | +{ |
---|
| 1150 | + size_t chunk_size = chunk->end_addr - chunk->start_addr + 1; |
---|
| 1151 | + |
---|
| 1152 | + dma_free_coherent((struct device *) data, chunk_size, |
---|
| 1153 | + (void *) chunk->start_addr, |
---|
| 1154 | + (dma_addr_t) chunk->phys_addr); |
---|
| 1155 | +} |
---|
| 1156 | + |
---|
| 1157 | +void cio_gp_dma_destroy(struct gen_pool *gp_dma, struct device *dma_dev) |
---|
| 1158 | +{ |
---|
| 1159 | + if (!gp_dma) |
---|
| 1160 | + return; |
---|
| 1161 | + /* this is quite ugly but no better idea */ |
---|
| 1162 | + gen_pool_for_each_chunk(gp_dma, __gp_dma_free_dma, dma_dev); |
---|
| 1163 | + gen_pool_destroy(gp_dma); |
---|
| 1164 | +} |
---|
| 1165 | + |
---|
| 1166 | +static int cio_dma_pool_init(void) |
---|
| 1167 | +{ |
---|
| 1168 | + /* No need to free up the resources: compiled in */ |
---|
| 1169 | + cio_dma_pool = cio_gp_dma_create(cio_get_dma_css_dev(), 1); |
---|
| 1170 | + if (!cio_dma_pool) |
---|
| 1171 | + return -ENOMEM; |
---|
| 1172 | + return 0; |
---|
| 1173 | +} |
---|
| 1174 | + |
---|
| 1175 | +void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev, |
---|
| 1176 | + size_t size) |
---|
| 1177 | +{ |
---|
| 1178 | + dma_addr_t dma_addr; |
---|
| 1179 | + unsigned long addr; |
---|
| 1180 | + size_t chunk_size; |
---|
| 1181 | + |
---|
| 1182 | + if (!gp_dma) |
---|
| 1183 | + return NULL; |
---|
| 1184 | + addr = gen_pool_alloc(gp_dma, size); |
---|
| 1185 | + while (!addr) { |
---|
| 1186 | + chunk_size = round_up(size, PAGE_SIZE); |
---|
| 1187 | + addr = (unsigned long) dma_alloc_coherent(dma_dev, |
---|
| 1188 | + chunk_size, &dma_addr, CIO_DMA_GFP); |
---|
| 1189 | + if (!addr) |
---|
| 1190 | + return NULL; |
---|
| 1191 | + gen_pool_add_virt(gp_dma, addr, dma_addr, chunk_size, -1); |
---|
| 1192 | + addr = gen_pool_alloc(gp_dma, size); |
---|
| 1193 | + } |
---|
| 1194 | + return (void *) addr; |
---|
| 1195 | +} |
---|
| 1196 | + |
---|
| 1197 | +void cio_gp_dma_free(struct gen_pool *gp_dma, void *cpu_addr, size_t size) |
---|
| 1198 | +{ |
---|
| 1199 | + if (!cpu_addr) |
---|
| 1200 | + return; |
---|
| 1201 | + memset(cpu_addr, 0, size); |
---|
| 1202 | + gen_pool_free(gp_dma, (unsigned long) cpu_addr, size); |
---|
| 1203 | +} |
---|
| 1204 | + |
---|
| 1205 | +/* |
---|
| 1206 | + * Allocate dma memory from the css global pool. Intended for memory not |
---|
| 1207 | + * specific to any single device within the css. The allocated memory |
---|
| 1208 | + * is not guaranteed to be 31-bit addressable. |
---|
| 1209 | + * |
---|
| 1210 | + * Caution: Not suitable for early stuff like console. |
---|
| 1211 | + */ |
---|
| 1212 | +void *cio_dma_zalloc(size_t size) |
---|
| 1213 | +{ |
---|
| 1214 | + return cio_gp_dma_zalloc(cio_dma_pool, cio_get_dma_css_dev(), size); |
---|
| 1215 | +} |
---|
| 1216 | + |
---|
| 1217 | +void cio_dma_free(void *cpu_addr, size_t size) |
---|
| 1218 | +{ |
---|
| 1219 | + cio_gp_dma_free(cio_dma_pool, cpu_addr, size); |
---|
| 1220 | +} |
---|
| 1221 | + |
---|
1043 | 1222 | /* |
---|
1044 | 1223 | * Now that the driver core is running, we can setup our channel subsystem. |
---|
1045 | 1224 | * The struct subchannel's are created during probing. |
---|
.. | .. |
---|
1081 | 1260 | if (ret) |
---|
1082 | 1261 | goto out_unregister; |
---|
1083 | 1262 | ret = register_pm_notifier(&css_power_notifier); |
---|
1084 | | - if (ret) { |
---|
1085 | | - unregister_reboot_notifier(&css_reboot_notifier); |
---|
1086 | | - goto out_unregister; |
---|
1087 | | - } |
---|
| 1263 | + if (ret) |
---|
| 1264 | + goto out_unregister_rn; |
---|
| 1265 | + ret = cio_dma_pool_init(); |
---|
| 1266 | + if (ret) |
---|
| 1267 | + goto out_unregister_pmn; |
---|
| 1268 | + airq_init(); |
---|
1088 | 1269 | css_init_done = 1; |
---|
1089 | 1270 | |
---|
1090 | 1271 | /* Enable default isc for I/O subchannels. */ |
---|
1091 | 1272 | isc_register(IO_SCH_ISC); |
---|
1092 | 1273 | |
---|
1093 | 1274 | return 0; |
---|
| 1275 | +out_unregister_pmn: |
---|
| 1276 | + unregister_pm_notifier(&css_power_notifier); |
---|
| 1277 | +out_unregister_rn: |
---|
| 1278 | + unregister_reboot_notifier(&css_reboot_notifier); |
---|
1094 | 1279 | out_unregister: |
---|
1095 | 1280 | while (i-- > 0) { |
---|
1096 | 1281 | struct channel_subsystem *css = channel_subsystems[i]; |
---|
.. | .. |
---|
1187 | 1372 | } |
---|
1188 | 1373 | subsys_initcall_sync(channel_subsystem_init_sync); |
---|
1189 | 1374 | |
---|
1190 | | -void channel_subsystem_reinit(void) |
---|
1191 | | -{ |
---|
1192 | | - struct channel_path *chp; |
---|
1193 | | - struct chp_id chpid; |
---|
1194 | | - |
---|
1195 | | - chsc_enable_facility(CHSC_SDA_OC_MSS); |
---|
1196 | | - chp_id_for_each(&chpid) { |
---|
1197 | | - chp = chpid_to_chp(chpid); |
---|
1198 | | - if (chp) |
---|
1199 | | - chp_update_desc(chp); |
---|
1200 | | - } |
---|
1201 | | - cmf_reactivate(); |
---|
1202 | | -} |
---|
1203 | | - |
---|
1204 | 1375 | #ifdef CONFIG_PROC_FS |
---|
1205 | 1376 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, |
---|
1206 | 1377 | size_t count, loff_t *ppos) |
---|
.. | .. |
---|
1214 | 1385 | return ret ? ret : count; |
---|
1215 | 1386 | } |
---|
1216 | 1387 | |
---|
1217 | | -static const struct file_operations cio_settle_proc_fops = { |
---|
1218 | | - .open = nonseekable_open, |
---|
1219 | | - .write = cio_settle_write, |
---|
1220 | | - .llseek = no_llseek, |
---|
| 1388 | +static const struct proc_ops cio_settle_proc_ops = { |
---|
| 1389 | + .proc_open = nonseekable_open, |
---|
| 1390 | + .proc_write = cio_settle_write, |
---|
| 1391 | + .proc_lseek = no_llseek, |
---|
1221 | 1392 | }; |
---|
1222 | 1393 | |
---|
1223 | 1394 | static int __init cio_settle_init(void) |
---|
1224 | 1395 | { |
---|
1225 | 1396 | struct proc_dir_entry *entry; |
---|
1226 | 1397 | |
---|
1227 | | - entry = proc_create("cio_settle", S_IWUSR, NULL, |
---|
1228 | | - &cio_settle_proc_fops); |
---|
| 1398 | + entry = proc_create("cio_settle", S_IWUSR, NULL, &cio_settle_proc_ops); |
---|
1229 | 1399 | if (!entry) |
---|
1230 | 1400 | return -ENOMEM; |
---|
1231 | 1401 | return 0; |
---|
.. | .. |
---|
1246 | 1416 | struct css_driver *driver = to_cssdriver(drv); |
---|
1247 | 1417 | struct css_device_id *id; |
---|
1248 | 1418 | |
---|
| 1419 | + /* When driver_override is set, only bind to the matching driver */ |
---|
| 1420 | + if (sch->driver_override && strcmp(sch->driver_override, drv->name)) |
---|
| 1421 | + return 0; |
---|
| 1422 | + |
---|
1249 | 1423 | for (id = driver->subchannel_type; id->match_flags; id++) { |
---|
1250 | 1424 | if (sch->st == id->type) |
---|
1251 | 1425 | return 1; |
---|