diff options
| author | Daniel Mack <daniel@caiaq.de> | 2009-03-24 20:18:35 -0400 |
|---|---|---|
| committer | Mike Frysinger <vapier@gentoo.org> | 2010-10-18 02:49:28 -0400 |
| commit | ac01e97d644da8e947ffa1bde5083290fe2e36e7 (patch) | |
| tree | c2a97d4c239afb65376dbaa81aca7610b0883369 /drivers | |
| parent | 2b666ca4a68cbc22483b0f2e1ba3c0e59b01ae9e (diff) | |
spi/bfin_spi: fix resources leakage
Re-order setup() a bit so we don't leak memory/dma/gpio resources upon
errors. Also make sure we don't call kfree() twice on the same object.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/spi/spi_bfin5xx.c | 120 |
1 files changed, 75 insertions, 45 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 10a6dc3d37ac..4f20b923a95c 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
| @@ -1006,20 +1006,24 @@ static u16 ssel[][MAX_SPI_SSEL] = { | |||
| 1006 | /* first setup for new devices */ | 1006 | /* first setup for new devices */ |
| 1007 | static int bfin_spi_setup(struct spi_device *spi) | 1007 | static int bfin_spi_setup(struct spi_device *spi) |
| 1008 | { | 1008 | { |
| 1009 | struct bfin5xx_spi_chip *chip_info = NULL; | 1009 | struct bfin5xx_spi_chip *chip_info; |
| 1010 | struct chip_data *chip; | 1010 | struct chip_data *chip = NULL; |
| 1011 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 1011 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); |
| 1012 | int ret; | 1012 | int ret = -EINVAL; |
| 1013 | 1013 | ||
| 1014 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) | 1014 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) |
| 1015 | return -EINVAL; | 1015 | goto error; |
| 1016 | 1016 | ||
| 1017 | /* Only alloc (or use chip_info) on first setup */ | 1017 | /* Only alloc (or use chip_info) on first setup */ |
| 1018 | chip_info = NULL; | ||
| 1018 | chip = spi_get_ctldata(spi); | 1019 | chip = spi_get_ctldata(spi); |
| 1019 | if (chip == NULL) { | 1020 | if (chip == NULL) { |
| 1020 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | 1021 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
| 1021 | if (!chip) | 1022 | if (!chip) { |
| 1022 | return -ENOMEM; | 1023 | dev_err(&spi->dev, "cannot allocate chip data\n"); |
| 1024 | ret = -ENOMEM; | ||
| 1025 | goto error; | ||
| 1026 | } | ||
| 1023 | 1027 | ||
| 1024 | chip->enable_dma = 0; | 1028 | chip->enable_dma = 0; |
| 1025 | chip_info = spi->controller_data; | 1029 | chip_info = spi->controller_data; |
| @@ -1036,7 +1040,7 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1036 | if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) { | 1040 | if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) { |
| 1037 | dev_err(&spi->dev, "do not set bits in ctl_reg " | 1041 | dev_err(&spi->dev, "do not set bits in ctl_reg " |
| 1038 | "that the SPI framework manages\n"); | 1042 | "that the SPI framework manages\n"); |
| 1039 | return -EINVAL; | 1043 | goto error; |
| 1040 | } | 1044 | } |
| 1041 | 1045 | ||
| 1042 | chip->enable_dma = chip_info->enable_dma != 0 | 1046 | chip->enable_dma = chip_info->enable_dma != 0 |
| @@ -1060,26 +1064,6 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1060 | chip->ctl_reg |= MSTR; | 1064 | chip->ctl_reg |= MSTR; |
| 1061 | 1065 | ||
| 1062 | /* | 1066 | /* |
| 1063 | * if any one SPI chip is registered and wants DMA, request the | ||
| 1064 | * DMA channel for it | ||
| 1065 | */ | ||
| 1066 | if (chip->enable_dma && !drv_data->dma_requested) { | ||
| 1067 | /* register dma irq handler */ | ||
| 1068 | if (request_dma(drv_data->dma_channel, "BFIN_SPI_DMA") < 0) { | ||
| 1069 | dev_dbg(&spi->dev, | ||
| 1070 | "Unable to request BlackFin SPI DMA channel\n"); | ||
| 1071 | return -ENODEV; | ||
| 1072 | } | ||
| 1073 | if (set_dma_callback(drv_data->dma_channel, | ||
| 1074 | bfin_spi_dma_irq_handler, drv_data) < 0) { | ||
| 1075 | dev_dbg(&spi->dev, "Unable to set dma callback\n"); | ||
| 1076 | return -EPERM; | ||
| 1077 | } | ||
| 1078 | dma_disable_irq(drv_data->dma_channel); | ||
| 1079 | drv_data->dma_requested = 1; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | /* | ||
| 1083 | * Notice: for blackfin, the speed_hz is the value of register | 1067 | * Notice: for blackfin, the speed_hz is the value of register |
| 1084 | * SPI_BAUD, not the real baudrate | 1068 | * SPI_BAUD, not the real baudrate |
| 1085 | */ | 1069 | */ |
| @@ -1087,16 +1071,6 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1087 | chip->flag = 1 << (spi->chip_select); | 1071 | chip->flag = 1 << (spi->chip_select); |
| 1088 | chip->chip_select_num = spi->chip_select; | 1072 | chip->chip_select_num = spi->chip_select; |
| 1089 | 1073 | ||
| 1090 | if (chip->chip_select_num == 0) { | ||
| 1091 | ret = gpio_request(chip->cs_gpio, spi->modalias); | ||
| 1092 | if (ret) { | ||
| 1093 | if (drv_data->dma_requested) | ||
| 1094 | free_dma(drv_data->dma_channel); | ||
| 1095 | return ret; | ||
| 1096 | } | ||
| 1097 | gpio_direction_output(chip->cs_gpio, 1); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | switch (chip->bits_per_word) { | 1074 | switch (chip->bits_per_word) { |
| 1101 | case 8: | 1075 | case 8: |
| 1102 | chip->n_bytes = 1; | 1076 | chip->n_bytes = 1; |
| @@ -1123,9 +1097,39 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1123 | default: | 1097 | default: |
| 1124 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", | 1098 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", |
| 1125 | chip->bits_per_word); | 1099 | chip->bits_per_word); |
| 1126 | if (chip_info) | 1100 | goto error; |
| 1127 | kfree(chip); | 1101 | } |
| 1128 | return -ENODEV; | 1102 | |
| 1103 | /* | ||
| 1104 | * if any one SPI chip is registered and wants DMA, request the | ||
| 1105 | * DMA channel for it | ||
| 1106 | */ | ||
| 1107 | if (chip->enable_dma && !drv_data->dma_requested) { | ||
| 1108 | /* register dma irq handler */ | ||
| 1109 | ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA"); | ||
| 1110 | if (ret) { | ||
| 1111 | dev_err(&spi->dev, | ||
| 1112 | "Unable to request BlackFin SPI DMA channel\n"); | ||
| 1113 | goto error; | ||
| 1114 | } | ||
| 1115 | drv_data->dma_requested = 1; | ||
| 1116 | |||
| 1117 | ret = set_dma_callback(drv_data->dma_channel, | ||
| 1118 | bfin_spi_dma_irq_handler, drv_data); | ||
| 1119 | if (ret) { | ||
| 1120 | dev_err(&spi->dev, "Unable to set dma callback\n"); | ||
| 1121 | goto error; | ||
| 1122 | } | ||
| 1123 | dma_disable_irq(drv_data->dma_channel); | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (chip->chip_select_num == 0) { | ||
| 1127 | ret = gpio_request(chip->cs_gpio, spi->modalias); | ||
| 1128 | if (ret) { | ||
| 1129 | dev_err(&spi->dev, "gpio_request() error\n"); | ||
| 1130 | goto pin_error; | ||
| 1131 | } | ||
| 1132 | gpio_direction_output(chip->cs_gpio, 1); | ||
| 1129 | } | 1133 | } |
| 1130 | 1134 | ||
| 1131 | dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n", | 1135 | dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n", |
| @@ -1136,14 +1140,38 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
| 1136 | spi_set_ctldata(spi, chip); | 1140 | spi_set_ctldata(spi, chip); |
| 1137 | 1141 | ||
| 1138 | dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); | 1142 | dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); |
| 1139 | if ((chip->chip_select_num > 0) | 1143 | if (chip->chip_select_num > 0 && |
| 1140 | && (chip->chip_select_num <= spi->master->num_chipselect)) | 1144 | chip->chip_select_num <= spi->master->num_chipselect) { |
| 1141 | peripheral_request(ssel[spi->master->bus_num] | 1145 | ret = peripheral_request(ssel[spi->master->bus_num] |
| 1142 | [chip->chip_select_num-1], spi->modalias); | 1146 | [chip->chip_select_num-1], spi->modalias); |
| 1147 | if (ret) { | ||
| 1148 | dev_err(&spi->dev, "peripheral_request() error\n"); | ||
| 1149 | goto pin_error; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1143 | 1152 | ||
| 1144 | bfin_spi_cs_deactive(drv_data, chip); | 1153 | bfin_spi_cs_deactive(drv_data, chip); |
| 1145 | 1154 | ||
| 1146 | return 0; | 1155 | return 0; |
| 1156 | |||
| 1157 | pin_error: | ||
| 1158 | if (chip->chip_select_num == 0) | ||
| 1159 | gpio_free(chip->cs_gpio); | ||
| 1160 | else | ||
| 1161 | peripheral_free(ssel[spi->master->bus_num] | ||
| 1162 | [chip->chip_select_num - 1]); | ||
| 1163 | error: | ||
| 1164 | if (chip) { | ||
| 1165 | if (drv_data->dma_requested) | ||
| 1166 | free_dma(drv_data->dma_channel); | ||
| 1167 | drv_data->dma_requested = 0; | ||
| 1168 | |||
| 1169 | kfree(chip); | ||
| 1170 | /* prevent free 'chip' twice */ | ||
| 1171 | spi_set_ctldata(spi, NULL); | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | return ret; | ||
| 1147 | } | 1175 | } |
| 1148 | 1176 | ||
| 1149 | /* | 1177 | /* |
| @@ -1166,6 +1194,8 @@ static void bfin_spi_cleanup(struct spi_device *spi) | |||
| 1166 | gpio_free(chip->cs_gpio); | 1194 | gpio_free(chip->cs_gpio); |
| 1167 | 1195 | ||
| 1168 | kfree(chip); | 1196 | kfree(chip); |
| 1197 | /* prevent free 'chip' twice */ | ||
| 1198 | spi_set_ctldata(spi, NULL); | ||
| 1169 | } | 1199 | } |
| 1170 | 1200 | ||
| 1171 | static inline int bfin_spi_init_queue(struct driver_data *drv_data) | 1201 | static inline int bfin_spi_init_queue(struct driver_data *drv_data) |
