Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: n_gsm: Save dlci address open status when config requester

When n_gsm config "initiator=0",as requester ,receive SABM frame,n_gsm
register gsmtty dev,and save dlci open address status,if receive DLC0
DISC or CLD frame,it can unregister the gsmtty dev by saving dlci address.

Signed-off-by: Zhenguo Zhao <Zhenguo.Zhao1@unisoc.com>
Link: https://lore.kernel.org/r/1629461872-26965-8-git-send-email-zhenguo6858@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Zhenguo Zhao and committed by
Greg Kroah-Hartman
0b91b533 5b87686e

+53 -4
+53 -4
drivers/tty/n_gsm.c
··· 271 271 272 272 static struct tty_driver *gsm_tty_driver; 273 273 274 + /* Save dlci open address */ 275 + static int addr_open[256] = { 0 }; 276 + /* Save dlci open count */ 277 + static int addr_cnt; 274 278 /* 275 279 * This section of the driver logic implements the GSM encodings 276 280 * both the basic and the 'advanced'. Reliable transport is not ··· 1185 1181 } 1186 1182 1187 1183 static void gsm_dlci_begin_close(struct gsm_dlci *dlci); 1184 + static void gsm_dlci_close(struct gsm_dlci *dlci); 1188 1185 1189 1186 /** 1190 1187 * gsm_control_message - DLCI 0 control processing ··· 1204 1199 { 1205 1200 u8 buf[1]; 1206 1201 unsigned long flags; 1202 + struct gsm_dlci *dlci; 1203 + int i; 1204 + int address; 1207 1205 1208 1206 switch (command) { 1209 1207 case CMD_CLD: { 1210 - struct gsm_dlci *dlci = gsm->dlci[0]; 1208 + if (addr_cnt > 0) { 1209 + for (i = 0; i < addr_cnt; i++) { 1210 + address = addr_open[i]; 1211 + dlci = gsm->dlci[address]; 1212 + gsm_dlci_close(dlci); 1213 + addr_open[i] = 0; 1214 + } 1215 + } 1211 1216 /* Modem wishes to close down */ 1217 + dlci = gsm->dlci[0]; 1212 1218 if (dlci) { 1213 1219 dlci->dead = true; 1214 1220 gsm->dead = true; 1215 - gsm_dlci_begin_close(dlci); 1221 + gsm_dlci_close(dlci); 1222 + addr_cnt = 0; 1223 + gsm_response(gsm, 0, UA|PF); 1216 1224 } 1217 1225 } 1218 1226 break; ··· 1774 1756 struct gsm_dlci *dlci; 1775 1757 u8 cr; 1776 1758 int address; 1759 + int i, j, k, address_tmp; 1777 1760 /* We have to sneak a look at the packet body to do the FCS. 1778 1761 A somewhat layering violation in the spec */ 1779 1762 ··· 1817 1798 else { 1818 1799 gsm_response(gsm, address, UA|PF); 1819 1800 gsm_dlci_open(dlci); 1801 + /* Save dlci open address */ 1802 + if (address) { 1803 + addr_open[addr_cnt] = address; 1804 + addr_cnt++; 1805 + } 1820 1806 } 1821 1807 break; 1822 1808 case DISC|PF: ··· 1832 1808 return; 1833 1809 } 1834 1810 /* Real close complete */ 1835 - gsm_response(gsm, address, UA|PF); 1836 - gsm_dlci_close(dlci); 1811 + if (!address) { 1812 + if (addr_cnt > 0) { 1813 + for (i = 0; i < addr_cnt; i++) { 1814 + address = addr_open[i]; 1815 + dlci = gsm->dlci[address]; 1816 + gsm_dlci_close(dlci); 1817 + addr_open[i] = 0; 1818 + } 1819 + } 1820 + dlci = gsm->dlci[0]; 1821 + gsm_dlci_close(dlci); 1822 + addr_cnt = 0; 1823 + gsm_response(gsm, 0, UA|PF); 1824 + } else { 1825 + gsm_response(gsm, address, UA|PF); 1826 + gsm_dlci_close(dlci); 1827 + /* clear dlci address */ 1828 + for (j = 0; j < addr_cnt; j++) { 1829 + address_tmp = addr_open[j]; 1830 + if (address_tmp == address) { 1831 + for (k = j; k < addr_cnt; k++) 1832 + addr_open[k] = addr_open[k+1]; 1833 + addr_cnt--; 1834 + break; 1835 + } 1836 + } 1837 + } 1837 1838 break; 1838 1839 case UA: 1839 1840 case UA|PF: