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/spi/spi_bfin5xx.c | |
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/spi/spi_bfin5xx.c')
-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) |