diff options
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3e602e8affa7..c883a085c059 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -1752,6 +1752,97 @@ int qdio_stop_irq(struct ccw_device *cdev, int nr) | |||
1752 | } | 1752 | } |
1753 | EXPORT_SYMBOL(qdio_stop_irq); | 1753 | EXPORT_SYMBOL(qdio_stop_irq); |
1754 | 1754 | ||
1755 | /** | ||
1756 | * qdio_pnso_brinfo() - perform network subchannel op #0 - bridge info. | ||
1757 | * @schid: Subchannel ID. | ||
1758 | * @cnc: Boolean Change-Notification Control | ||
1759 | * @response: Response code will be stored at this address | ||
1760 | * @cb: Callback function will be executed for each element | ||
1761 | * of the address list | ||
1762 | * @priv: Pointer passed from the caller to qdio_pnso_brinfo() | ||
1763 | * @type: Type of the address entry passed to the callback | ||
1764 | * @entry: Entry containg the address of the specified type | ||
1765 | * @priv: Pointer to pass to the callback function. | ||
1766 | * | ||
1767 | * Performs "Store-network-bridging-information list" operation and calls | ||
1768 | * the callback function for every entry in the list. If "change- | ||
1769 | * notification-control" is set, further changes in the address list | ||
1770 | * will be reported via the IPA command. | ||
1771 | */ | ||
1772 | int qdio_pnso_brinfo(struct subchannel_id schid, | ||
1773 | int cnc, u16 *response, | ||
1774 | void (*cb)(void *priv, enum qdio_brinfo_entry_type type, | ||
1775 | void *entry), | ||
1776 | void *priv) | ||
1777 | { | ||
1778 | struct chsc_pnso_area *rr; | ||
1779 | int rc; | ||
1780 | u32 prev_instance = 0; | ||
1781 | int isfirstblock = 1; | ||
1782 | int i, size, elems; | ||
1783 | |||
1784 | rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL); | ||
1785 | if (rr == NULL) | ||
1786 | return -ENOMEM; | ||
1787 | do { | ||
1788 | /* on the first iteration, naihdr.resume_token will be zero */ | ||
1789 | rc = chsc_pnso_brinfo(schid, rr, rr->naihdr.resume_token, cnc); | ||
1790 | if (rc != 0 && rc != -EBUSY) | ||
1791 | goto out; | ||
1792 | if (rr->response.code != 1) { | ||
1793 | rc = -EIO; | ||
1794 | continue; | ||
1795 | } else | ||
1796 | rc = 0; | ||
1797 | |||
1798 | if (cb == NULL) | ||
1799 | continue; | ||
1800 | |||
1801 | size = rr->naihdr.naids; | ||
1802 | elems = (rr->response.length - | ||
1803 | sizeof(struct chsc_header) - | ||
1804 | sizeof(struct chsc_brinfo_naihdr)) / | ||
1805 | size; | ||
1806 | |||
1807 | if (!isfirstblock && (rr->naihdr.instance != prev_instance)) { | ||
1808 | /* Inform the caller that they need to scrap */ | ||
1809 | /* the data that was already reported via cb */ | ||
1810 | rc = -EAGAIN; | ||
1811 | break; | ||
1812 | } | ||
1813 | isfirstblock = 0; | ||
1814 | prev_instance = rr->naihdr.instance; | ||
1815 | for (i = 0; i < elems; i++) | ||
1816 | switch (size) { | ||
1817 | case sizeof(struct qdio_brinfo_entry_l3_ipv6): | ||
1818 | (*cb)(priv, l3_ipv6_addr, | ||
1819 | &rr->entries.l3_ipv6[i]); | ||
1820 | break; | ||
1821 | case sizeof(struct qdio_brinfo_entry_l3_ipv4): | ||
1822 | (*cb)(priv, l3_ipv4_addr, | ||
1823 | &rr->entries.l3_ipv4[i]); | ||
1824 | break; | ||
1825 | case sizeof(struct qdio_brinfo_entry_l2): | ||
1826 | (*cb)(priv, l2_addr_lnid, | ||
1827 | &rr->entries.l2[i]); | ||
1828 | break; | ||
1829 | default: | ||
1830 | WARN_ON_ONCE(1); | ||
1831 | rc = -EIO; | ||
1832 | goto out; | ||
1833 | } | ||
1834 | } while (rr->response.code == 0x0107 || /* channel busy */ | ||
1835 | (rr->response.code == 1 && /* list stored */ | ||
1836 | /* resume token is non-zero => list incomplete */ | ||
1837 | (rr->naihdr.resume_token.t1 || rr->naihdr.resume_token.t2))); | ||
1838 | (*response) = rr->response.code; | ||
1839 | |||
1840 | out: | ||
1841 | free_page((unsigned long)rr); | ||
1842 | return rc; | ||
1843 | } | ||
1844 | EXPORT_SYMBOL_GPL(qdio_pnso_brinfo); | ||
1845 | |||
1755 | static int __init init_QDIO(void) | 1846 | static int __init init_QDIO(void) |
1756 | { | 1847 | { |
1757 | int rc; | 1848 | int rc; |