diff options
Diffstat (limited to 'drivers/s390/net/ctcm_main.c')
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index ecac3b2e32d4..558dc323a947 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -51,12 +51,16 @@ | |||
51 | 51 | ||
52 | #include <asm/idals.h> | 52 | #include <asm/idals.h> |
53 | 53 | ||
54 | #include "cu3088.h" | ||
55 | #include "ctcm_fsms.h" | 54 | #include "ctcm_fsms.h" |
56 | #include "ctcm_main.h" | 55 | #include "ctcm_main.h" |
57 | 56 | ||
58 | /* Some common global variables */ | 57 | /* Some common global variables */ |
59 | 58 | ||
59 | /** | ||
60 | * The root device for ctcm group devices | ||
61 | */ | ||
62 | static struct device *ctcm_root_dev; | ||
63 | |||
60 | /* | 64 | /* |
61 | * Linked list of all detected channels. | 65 | * Linked list of all detected channels. |
62 | */ | 66 | */ |
@@ -246,7 +250,7 @@ static void channel_remove(struct channel *ch) | |||
246 | * | 250 | * |
247 | * returns Pointer to a channel or NULL if no matching channel available. | 251 | * returns Pointer to a channel or NULL if no matching channel available. |
248 | */ | 252 | */ |
249 | static struct channel *channel_get(enum channel_types type, | 253 | static struct channel *channel_get(enum ctcm_channel_types type, |
250 | char *id, int direction) | 254 | char *id, int direction) |
251 | { | 255 | { |
252 | struct channel *ch = channels; | 256 | struct channel *ch = channels; |
@@ -1342,7 +1346,7 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) | |||
1342 | * | 1346 | * |
1343 | * returns 0 on success, !0 on error. | 1347 | * returns 0 on success, !0 on error. |
1344 | */ | 1348 | */ |
1345 | static int add_channel(struct ccw_device *cdev, enum channel_types type, | 1349 | static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, |
1346 | struct ctcm_priv *priv) | 1350 | struct ctcm_priv *priv) |
1347 | { | 1351 | { |
1348 | struct channel **c = &channels; | 1352 | struct channel **c = &channels; |
@@ -1501,13 +1505,13 @@ free_return: /* note that all channel pointers are 0 or valid */ | |||
1501 | /* | 1505 | /* |
1502 | * Return type of a detected device. | 1506 | * Return type of a detected device. |
1503 | */ | 1507 | */ |
1504 | static enum channel_types get_channel_type(struct ccw_device_id *id) | 1508 | static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id) |
1505 | { | 1509 | { |
1506 | enum channel_types type; | 1510 | enum ctcm_channel_types type; |
1507 | type = (enum channel_types)id->driver_info; | 1511 | type = (enum ctcm_channel_types)id->driver_info; |
1508 | 1512 | ||
1509 | if (type == channel_type_ficon) | 1513 | if (type == ctcm_channel_type_ficon) |
1510 | type = channel_type_escon; | 1514 | type = ctcm_channel_type_escon; |
1511 | 1515 | ||
1512 | return type; | 1516 | return type; |
1513 | } | 1517 | } |
@@ -1525,7 +1529,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1525 | char read_id[CTCM_ID_SIZE]; | 1529 | char read_id[CTCM_ID_SIZE]; |
1526 | char write_id[CTCM_ID_SIZE]; | 1530 | char write_id[CTCM_ID_SIZE]; |
1527 | int direction; | 1531 | int direction; |
1528 | enum channel_types type; | 1532 | enum ctcm_channel_types type; |
1529 | struct ctcm_priv *priv; | 1533 | struct ctcm_priv *priv; |
1530 | struct net_device *dev; | 1534 | struct net_device *dev; |
1531 | struct ccw_device *cdev0; | 1535 | struct ccw_device *cdev0; |
@@ -1749,6 +1753,22 @@ err_out: | |||
1749 | return rc; | 1753 | return rc; |
1750 | } | 1754 | } |
1751 | 1755 | ||
1756 | static struct ccw_device_id ctcm_ids[] = { | ||
1757 | {CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel}, | ||
1758 | {CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon}, | ||
1759 | {CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon}, | ||
1760 | {}, | ||
1761 | }; | ||
1762 | MODULE_DEVICE_TABLE(ccw, ctcm_ids); | ||
1763 | |||
1764 | static struct ccw_driver ctcm_ccw_driver = { | ||
1765 | .owner = THIS_MODULE, | ||
1766 | .name = "ctcm", | ||
1767 | .ids = ctcm_ids, | ||
1768 | .probe = ccwgroup_probe_ccwdev, | ||
1769 | .remove = ccwgroup_remove_ccwdev, | ||
1770 | }; | ||
1771 | |||
1752 | static struct ccwgroup_driver ctcm_group_driver = { | 1772 | static struct ccwgroup_driver ctcm_group_driver = { |
1753 | .owner = THIS_MODULE, | 1773 | .owner = THIS_MODULE, |
1754 | .name = CTC_DRIVER_NAME, | 1774 | .name = CTC_DRIVER_NAME, |
@@ -1763,6 +1783,33 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1763 | .restore = ctcm_pm_resume, | 1783 | .restore = ctcm_pm_resume, |
1764 | }; | 1784 | }; |
1765 | 1785 | ||
1786 | static ssize_t | ||
1787 | ctcm_driver_group_store(struct device_driver *ddrv, const char *buf, | ||
1788 | size_t count) | ||
1789 | { | ||
1790 | int err; | ||
1791 | |||
1792 | err = ccwgroup_create_from_string(ctcm_root_dev, | ||
1793 | ctcm_group_driver.driver_id, | ||
1794 | &ctcm_ccw_driver, 2, buf); | ||
1795 | return err ? err : count; | ||
1796 | } | ||
1797 | |||
1798 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); | ||
1799 | |||
1800 | static struct attribute *ctcm_group_attrs[] = { | ||
1801 | &driver_attr_group.attr, | ||
1802 | NULL, | ||
1803 | }; | ||
1804 | |||
1805 | static struct attribute_group ctcm_group_attr_group = { | ||
1806 | .attrs = ctcm_group_attrs, | ||
1807 | }; | ||
1808 | |||
1809 | static struct attribute_group *ctcm_group_attr_groups[] = { | ||
1810 | &ctcm_group_attr_group, | ||
1811 | NULL, | ||
1812 | }; | ||
1766 | 1813 | ||
1767 | /* | 1814 | /* |
1768 | * Module related routines | 1815 | * Module related routines |
@@ -1776,7 +1823,10 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1776 | */ | 1823 | */ |
1777 | static void __exit ctcm_exit(void) | 1824 | static void __exit ctcm_exit(void) |
1778 | { | 1825 | { |
1779 | unregister_cu3088_discipline(&ctcm_group_driver); | 1826 | driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group); |
1827 | ccwgroup_driver_unregister(&ctcm_group_driver); | ||
1828 | ccw_driver_unregister(&ctcm_ccw_driver); | ||
1829 | root_device_unregister(ctcm_root_dev); | ||
1780 | ctcm_unregister_dbf_views(); | 1830 | ctcm_unregister_dbf_views(); |
1781 | pr_info("CTCM driver unloaded\n"); | 1831 | pr_info("CTCM driver unloaded\n"); |
1782 | } | 1832 | } |
@@ -1802,17 +1852,31 @@ static int __init ctcm_init(void) | |||
1802 | channels = NULL; | 1852 | channels = NULL; |
1803 | 1853 | ||
1804 | ret = ctcm_register_dbf_views(); | 1854 | ret = ctcm_register_dbf_views(); |
1805 | if (ret) { | 1855 | if (ret) |
1806 | return ret; | 1856 | goto out_err; |
1807 | } | 1857 | ctcm_root_dev = root_device_register("ctcm"); |
1808 | ret = register_cu3088_discipline(&ctcm_group_driver); | 1858 | ret = IS_ERR(ctcm_root_dev) ? PTR_ERR(ctcm_root_dev) : 0; |
1809 | if (ret) { | 1859 | if (ret) |
1810 | ctcm_unregister_dbf_views(); | 1860 | goto register_err; |
1811 | pr_err("%s / register_cu3088_discipline failed, ret = %d\n", | 1861 | ret = ccw_driver_register(&ctcm_ccw_driver); |
1812 | __func__, ret); | 1862 | if (ret) |
1813 | return ret; | 1863 | goto ccw_err; |
1814 | } | 1864 | ctcm_group_driver.driver.groups = ctcm_group_attr_groups; |
1865 | ret = ccwgroup_driver_register(&ctcm_group_driver); | ||
1866 | if (ret) | ||
1867 | goto ccwgroup_err; | ||
1815 | print_banner(); | 1868 | print_banner(); |
1869 | return 0; | ||
1870 | |||
1871 | ccwgroup_err: | ||
1872 | ccw_driver_unregister(&ctcm_ccw_driver); | ||
1873 | ccw_err: | ||
1874 | root_device_unregister(ctcm_root_dev); | ||
1875 | register_err: | ||
1876 | ctcm_unregister_dbf_views(); | ||
1877 | out_err: | ||
1878 | pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n", | ||
1879 | __func__, ret); | ||
1816 | return ret; | 1880 | return ret; |
1817 | } | 1881 | } |
1818 | 1882 | ||