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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tty-6.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial fixes from Greg KH:
"Here are some small TTY and Serial driver fixes that missed the
6.9-final merge window, but have been in my tree for weeks (my fault,
travel caused me to miss this)

These fixes include:

- more n_gsm fixes for reported problems

- 8520_mtk driver fix

- 8250_bcm7271 driver fix

- sc16is7xx driver fix

All of these have been in linux-next for weeks without any reported
problems"

* tag 'tty-6.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
serial: 8250_bcm7271: use default_mux_rate if possible
serial: 8520_mtk: Set RTS on shutdown for Rx in-band wakeup
tty: n_gsm: fix missing receive state reset after mode switch
tty: n_gsm: fix possible out-of-bounds in gsm0_receive()

+180 -90
+97 -43
drivers/tty/n_gsm.c
··· 245 245 246 246 enum gsm_mux_state { 247 247 GSM_SEARCH, 248 - GSM_START, 249 - GSM_ADDRESS, 250 - GSM_CONTROL, 251 - GSM_LEN, 252 - GSM_DATA, 253 - GSM_FCS, 254 - GSM_OVERRUN, 255 - GSM_LEN0, 256 - GSM_LEN1, 257 - GSM_SSOF, 248 + GSM0_ADDRESS, 249 + GSM0_CONTROL, 250 + GSM0_LEN0, 251 + GSM0_LEN1, 252 + GSM0_DATA, 253 + GSM0_FCS, 254 + GSM0_SSOF, 255 + GSM1_START, 256 + GSM1_ADDRESS, 257 + GSM1_CONTROL, 258 + GSM1_DATA, 259 + GSM1_OVERRUN, 258 260 }; 259 261 260 262 /* ··· 2849 2847 return; 2850 2848 } 2851 2849 2850 + /** 2851 + * gsm0_receive_state_check_and_fix - check and correct receive state 2852 + * @gsm: gsm data for this ldisc instance 2853 + * 2854 + * Ensures that the current receive state is valid for basic option mode. 2855 + */ 2856 + 2857 + static void gsm0_receive_state_check_and_fix(struct gsm_mux *gsm) 2858 + { 2859 + switch (gsm->state) { 2860 + case GSM_SEARCH: 2861 + case GSM0_ADDRESS: 2862 + case GSM0_CONTROL: 2863 + case GSM0_LEN0: 2864 + case GSM0_LEN1: 2865 + case GSM0_DATA: 2866 + case GSM0_FCS: 2867 + case GSM0_SSOF: 2868 + break; 2869 + default: 2870 + gsm->state = GSM_SEARCH; 2871 + break; 2872 + } 2873 + } 2852 2874 2853 2875 /** 2854 2876 * gsm0_receive - perform processing for non-transparency ··· 2886 2860 { 2887 2861 unsigned int len; 2888 2862 2863 + gsm0_receive_state_check_and_fix(gsm); 2889 2864 switch (gsm->state) { 2890 2865 case GSM_SEARCH: /* SOF marker */ 2891 2866 if (c == GSM0_SOF) { 2892 - gsm->state = GSM_ADDRESS; 2867 + gsm->state = GSM0_ADDRESS; 2893 2868 gsm->address = 0; 2894 2869 gsm->len = 0; 2895 2870 gsm->fcs = INIT_FCS; 2896 2871 } 2897 2872 break; 2898 - case GSM_ADDRESS: /* Address EA */ 2873 + case GSM0_ADDRESS: /* Address EA */ 2899 2874 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 2900 2875 if (gsm_read_ea(&gsm->address, c)) 2901 - gsm->state = GSM_CONTROL; 2876 + gsm->state = GSM0_CONTROL; 2902 2877 break; 2903 - case GSM_CONTROL: /* Control Byte */ 2878 + case GSM0_CONTROL: /* Control Byte */ 2904 2879 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 2905 2880 gsm->control = c; 2906 - gsm->state = GSM_LEN0; 2881 + gsm->state = GSM0_LEN0; 2907 2882 break; 2908 - case GSM_LEN0: /* Length EA */ 2883 + case GSM0_LEN0: /* Length EA */ 2909 2884 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 2910 2885 if (gsm_read_ea(&gsm->len, c)) { 2911 2886 if (gsm->len > gsm->mru) { ··· 2916 2889 } 2917 2890 gsm->count = 0; 2918 2891 if (!gsm->len) 2919 - gsm->state = GSM_FCS; 2892 + gsm->state = GSM0_FCS; 2920 2893 else 2921 - gsm->state = GSM_DATA; 2894 + gsm->state = GSM0_DATA; 2922 2895 break; 2923 2896 } 2924 - gsm->state = GSM_LEN1; 2897 + gsm->state = GSM0_LEN1; 2925 2898 break; 2926 - case GSM_LEN1: 2899 + case GSM0_LEN1: 2927 2900 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 2928 2901 len = c; 2929 2902 gsm->len |= len << 7; ··· 2934 2907 } 2935 2908 gsm->count = 0; 2936 2909 if (!gsm->len) 2937 - gsm->state = GSM_FCS; 2910 + gsm->state = GSM0_FCS; 2938 2911 else 2939 - gsm->state = GSM_DATA; 2912 + gsm->state = GSM0_DATA; 2940 2913 break; 2941 - case GSM_DATA: /* Data */ 2914 + case GSM0_DATA: /* Data */ 2942 2915 gsm->buf[gsm->count++] = c; 2943 - if (gsm->count == gsm->len) { 2916 + if (gsm->count >= MAX_MRU) { 2917 + gsm->bad_size++; 2918 + gsm->state = GSM_SEARCH; 2919 + } else if (gsm->count >= gsm->len) { 2944 2920 /* Calculate final FCS for UI frames over all data */ 2945 2921 if ((gsm->control & ~PF) != UIH) { 2946 2922 gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, 2947 2923 gsm->count); 2948 2924 } 2949 - gsm->state = GSM_FCS; 2925 + gsm->state = GSM0_FCS; 2950 2926 } 2951 2927 break; 2952 - case GSM_FCS: /* FCS follows the packet */ 2928 + case GSM0_FCS: /* FCS follows the packet */ 2953 2929 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 2954 - gsm->state = GSM_SSOF; 2930 + gsm->state = GSM0_SSOF; 2955 2931 break; 2956 - case GSM_SSOF: 2932 + case GSM0_SSOF: 2957 2933 gsm->state = GSM_SEARCH; 2958 2934 if (c == GSM0_SOF) 2959 2935 gsm_queue(gsm); ··· 2965 2935 break; 2966 2936 default: 2967 2937 pr_debug("%s: unhandled state: %d\n", __func__, gsm->state); 2938 + break; 2939 + } 2940 + } 2941 + 2942 + /** 2943 + * gsm1_receive_state_check_and_fix - check and correct receive state 2944 + * @gsm: gsm data for this ldisc instance 2945 + * 2946 + * Ensures that the current receive state is valid for advanced option mode. 2947 + */ 2948 + 2949 + static void gsm1_receive_state_check_and_fix(struct gsm_mux *gsm) 2950 + { 2951 + switch (gsm->state) { 2952 + case GSM_SEARCH: 2953 + case GSM1_START: 2954 + case GSM1_ADDRESS: 2955 + case GSM1_CONTROL: 2956 + case GSM1_DATA: 2957 + case GSM1_OVERRUN: 2958 + break; 2959 + default: 2960 + gsm->state = GSM_SEARCH; 2968 2961 break; 2969 2962 } 2970 2963 } ··· 3002 2949 3003 2950 static void gsm1_receive(struct gsm_mux *gsm, u8 c) 3004 2951 { 2952 + gsm1_receive_state_check_and_fix(gsm); 3005 2953 /* handle XON/XOFF */ 3006 2954 if ((c & ISO_IEC_646_MASK) == XON) { 3007 2955 gsm->constipated = true; ··· 3015 2961 } 3016 2962 if (c == GSM1_SOF) { 3017 2963 /* EOF is only valid in frame if we have got to the data state */ 3018 - if (gsm->state == GSM_DATA) { 2964 + if (gsm->state == GSM1_DATA) { 3019 2965 if (gsm->count < 1) { 3020 2966 /* Missing FSC */ 3021 2967 gsm->malformed++; 3022 - gsm->state = GSM_START; 2968 + gsm->state = GSM1_START; 3023 2969 return; 3024 2970 } 3025 2971 /* Remove the FCS from data */ ··· 3035 2981 gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]); 3036 2982 gsm->len = gsm->count; 3037 2983 gsm_queue(gsm); 3038 - gsm->state = GSM_START; 2984 + gsm->state = GSM1_START; 3039 2985 return; 3040 2986 } 3041 2987 /* Any partial frame was a runt so go back to start */ 3042 - if (gsm->state != GSM_START) { 2988 + if (gsm->state != GSM1_START) { 3043 2989 if (gsm->state != GSM_SEARCH) 3044 2990 gsm->malformed++; 3045 - gsm->state = GSM_START; 2991 + gsm->state = GSM1_START; 3046 2992 } 3047 2993 /* A SOF in GSM_START means we are still reading idling or 3048 2994 framing bytes */ ··· 3063 3009 gsm->escape = false; 3064 3010 } 3065 3011 switch (gsm->state) { 3066 - case GSM_START: /* First byte after SOF */ 3012 + case GSM1_START: /* First byte after SOF */ 3067 3013 gsm->address = 0; 3068 - gsm->state = GSM_ADDRESS; 3014 + gsm->state = GSM1_ADDRESS; 3069 3015 gsm->fcs = INIT_FCS; 3070 3016 fallthrough; 3071 - case GSM_ADDRESS: /* Address continuation */ 3017 + case GSM1_ADDRESS: /* Address continuation */ 3072 3018 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 3073 3019 if (gsm_read_ea(&gsm->address, c)) 3074 - gsm->state = GSM_CONTROL; 3020 + gsm->state = GSM1_CONTROL; 3075 3021 break; 3076 - case GSM_CONTROL: /* Control Byte */ 3022 + case GSM1_CONTROL: /* Control Byte */ 3077 3023 gsm->fcs = gsm_fcs_add(gsm->fcs, c); 3078 3024 gsm->control = c; 3079 3025 gsm->count = 0; 3080 - gsm->state = GSM_DATA; 3026 + gsm->state = GSM1_DATA; 3081 3027 break; 3082 - case GSM_DATA: /* Data */ 3083 - if (gsm->count > gsm->mru) { /* Allow one for the FCS */ 3084 - gsm->state = GSM_OVERRUN; 3028 + case GSM1_DATA: /* Data */ 3029 + if (gsm->count > gsm->mru || gsm->count > MAX_MRU) { /* Allow one for the FCS */ 3030 + gsm->state = GSM1_OVERRUN; 3085 3031 gsm->bad_size++; 3086 3032 } else 3087 3033 gsm->buf[gsm->count++] = c; 3088 3034 break; 3089 - case GSM_OVERRUN: /* Over-long - eg a dropped SOF */ 3035 + case GSM1_OVERRUN: /* Over-long - eg a dropped SOF */ 3090 3036 break; 3091 3037 default: 3092 3038 pr_debug("%s: unhandled state: %d\n", __func__, gsm->state);
+59 -40
drivers/tty/serial/8250/8250_bcm7271.c
··· 673 673 clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate); 674 674 } 675 675 676 + static u32 find_quot(struct device *dev, u32 freq, u32 baud, u32 *percent) 677 + { 678 + u32 quot; 679 + u32 rate; 680 + u64 hires_rate; 681 + u64 hires_baud; 682 + u64 hires_err; 683 + 684 + rate = freq / 16; 685 + quot = DIV_ROUND_CLOSEST(rate, baud); 686 + if (!quot) 687 + return 0; 688 + 689 + /* increase resolution to get xx.xx percent */ 690 + hires_rate = div_u64((u64)rate * 10000, (u64)quot); 691 + hires_baud = (u64)baud * 10000; 692 + 693 + /* get the delta */ 694 + if (hires_rate > hires_baud) 695 + hires_err = (hires_rate - hires_baud); 696 + else 697 + hires_err = (hires_baud - hires_rate); 698 + 699 + *percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud); 700 + 701 + dev_dbg(dev, "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n", 702 + baud, freq, *percent / 100, *percent % 100); 703 + 704 + return quot; 705 + } 706 + 676 707 static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv, 677 708 u32 baud) 678 709 { 679 710 u32 percent; 680 711 u32 best_percent = UINT_MAX; 681 712 u32 quot; 713 + u32 freq; 682 714 u32 best_quot = 1; 683 - u32 rate; 684 - int best_index = -1; 685 - u64 hires_rate; 686 - u64 hires_baud; 687 - u64 hires_err; 715 + u32 best_freq = 0; 688 716 int rc; 689 717 int i; 690 718 int real_baud; ··· 721 693 if (priv->baud_mux_clk == NULL) 722 694 return; 723 695 724 - /* Find the closest match for specified baud */ 725 - for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) { 726 - if (priv->real_rates[i] == 0) 727 - continue; 728 - rate = priv->real_rates[i] / 16; 729 - quot = DIV_ROUND_CLOSEST(rate, baud); 730 - if (!quot) 731 - continue; 696 + /* Try default_mux_rate first */ 697 + quot = find_quot(up->dev, priv->default_mux_rate, baud, &percent); 698 + if (quot) { 699 + best_percent = percent; 700 + best_freq = priv->default_mux_rate; 701 + best_quot = quot; 702 + } 703 + /* If more than 1% error, find the closest match for specified baud */ 704 + if (best_percent > 100) { 705 + for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) { 706 + freq = priv->real_rates[i]; 707 + if (freq == 0 || freq == priv->default_mux_rate) 708 + continue; 709 + quot = find_quot(up->dev, freq, baud, &percent); 710 + if (!quot) 711 + continue; 732 712 733 - /* increase resolution to get xx.xx percent */ 734 - hires_rate = (u64)rate * 10000; 735 - hires_baud = (u64)baud * 10000; 736 - 737 - hires_err = div_u64(hires_rate, (u64)quot); 738 - 739 - /* get the delta */ 740 - if (hires_err > hires_baud) 741 - hires_err = (hires_err - hires_baud); 742 - else 743 - hires_err = (hires_baud - hires_err); 744 - 745 - percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud); 746 - dev_dbg(up->dev, 747 - "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n", 748 - baud, priv->real_rates[i], percent / 100, 749 - percent % 100); 750 - if (percent < best_percent) { 751 - best_percent = percent; 752 - best_index = i; 753 - best_quot = quot; 713 + if (percent < best_percent) { 714 + best_percent = percent; 715 + best_freq = freq; 716 + best_quot = quot; 717 + } 754 718 } 755 719 } 756 - if (best_index == -1) { 720 + if (!best_freq) { 757 721 dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud); 758 722 return; 759 723 } 760 - rate = priv->real_rates[best_index]; 761 - rc = clk_set_rate(priv->baud_mux_clk, rate); 724 + rc = clk_set_rate(priv->baud_mux_clk, best_freq); 762 725 if (rc) 763 726 dev_err(up->dev, "Error selecting BAUD MUX clock\n"); 764 727 ··· 758 739 dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n", 759 740 baud, percent / 100, percent % 100); 760 741 761 - real_baud = rate / 16 / best_quot; 762 - dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate); 742 + real_baud = best_freq / 16 / best_quot; 743 + dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", best_freq); 763 744 dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n", 764 745 baud, real_baud); 765 746 ··· 768 749 i += (i / 2); 769 750 priv->char_wait = ns_to_ktime(i); 770 751 771 - up->uartclk = rate; 752 + up->uartclk = best_freq; 772 753 } 773 754 774 755 static void brcmstb_set_termios(struct uart_port *up,
+6 -2
drivers/tty/serial/8250/8250_mtk.c
··· 209 209 210 210 static void mtk8250_shutdown(struct uart_port *port) 211 211 { 212 - #ifdef CONFIG_SERIAL_8250_DMA 213 212 struct uart_8250_port *up = up_to_u8250p(port); 214 213 struct mtk8250_data *data = port->private_data; 214 + int irq = data->rx_wakeup_irq; 215 215 216 + #ifdef CONFIG_SERIAL_8250_DMA 216 217 if (up->dma) 217 218 data->rx_status = DMA_RX_SHUTDOWN; 218 219 #endif 219 220 220 - return serial8250_do_shutdown(port); 221 + serial8250_do_shutdown(port); 222 + 223 + if (irq >= 0) 224 + serial8250_do_set_mctrl(&up->port, TIOCM_RTS); 221 225 } 222 226 223 227 static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
+18 -5
drivers/tty/serial/sc16is7xx.c
··· 555 555 return reg == SC16IS7XX_RHR_REG; 556 556 } 557 557 558 + /* 559 + * Configure programmable baud rate generator (divisor) according to the 560 + * desired baud rate. 561 + * 562 + * From the datasheet, the divisor is computed according to: 563 + * 564 + * XTAL1 input frequency 565 + * ----------------------- 566 + * prescaler 567 + * divisor = --------------------------- 568 + * baud-rate x sampling-rate 569 + */ 558 570 static int sc16is7xx_set_baud(struct uart_port *port, int baud) 559 571 { 560 572 struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); 561 573 u8 lcr; 562 - u8 prescaler = 0; 574 + unsigned int prescaler = 1; 563 575 unsigned long clk = port->uartclk, div = clk / 16 / baud; 564 576 565 577 if (div >= BIT(16)) { 566 - prescaler = SC16IS7XX_MCR_CLKSEL_BIT; 567 - div /= 4; 578 + prescaler = 4; 579 + div /= prescaler; 568 580 } 569 581 570 582 /* Enable enhanced features */ ··· 586 574 SC16IS7XX_EFR_ENABLE_BIT); 587 575 sc16is7xx_efr_unlock(port); 588 576 577 + /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ 589 578 sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, 590 579 SC16IS7XX_MCR_CLKSEL_BIT, 591 - prescaler); 580 + prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT); 592 581 593 582 /* Backup LCR and access special register set (DLL/DLH) */ 594 583 lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); ··· 605 592 /* Restore LCR and access to general register set */ 606 593 sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); 607 594 608 - return DIV_ROUND_CLOSEST(clk / 16, div); 595 + return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div); 609 596 } 610 597 611 598 static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,