diff options
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r-- | drivers/i2c/i2c-dev.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 0b0427f7d348..5f3a52d517c3 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -189,12 +189,50 @@ static int i2cdev_check(struct device *dev, void *addrp) | |||
189 | return dev->driver ? -EBUSY : 0; | 189 | return dev->driver ? -EBUSY : 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | /* walk up mux tree */ | ||
193 | static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) | ||
194 | { | ||
195 | int result; | ||
196 | |||
197 | result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); | ||
198 | |||
199 | if (!result && i2c_parent_is_i2c_adapter(adapter)) | ||
200 | result = i2cdev_check_mux_parents( | ||
201 | to_i2c_adapter(adapter->dev.parent), addr); | ||
202 | |||
203 | return result; | ||
204 | } | ||
205 | |||
206 | /* recurse down mux tree */ | ||
207 | static int i2cdev_check_mux_children(struct device *dev, void *addrp) | ||
208 | { | ||
209 | int result; | ||
210 | |||
211 | if (dev->type == &i2c_adapter_type) | ||
212 | result = device_for_each_child(dev, addrp, | ||
213 | i2cdev_check_mux_children); | ||
214 | else | ||
215 | result = i2cdev_check(dev, addrp); | ||
216 | |||
217 | return result; | ||
218 | } | ||
219 | |||
192 | /* This address checking function differs from the one in i2c-core | 220 | /* This address checking function differs from the one in i2c-core |
193 | in that it considers an address with a registered device, but no | 221 | in that it considers an address with a registered device, but no |
194 | driver bound to it, as NOT busy. */ | 222 | driver bound to it, as NOT busy. */ |
195 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | 223 | static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) |
196 | { | 224 | { |
197 | return device_for_each_child(&adapter->dev, &addr, i2cdev_check); | 225 | int result = 0; |
226 | |||
227 | if (i2c_parent_is_i2c_adapter(adapter)) | ||
228 | result = i2cdev_check_mux_parents( | ||
229 | to_i2c_adapter(adapter->dev.parent), addr); | ||
230 | |||
231 | if (!result) | ||
232 | result = device_for_each_child(&adapter->dev, &addr, | ||
233 | i2cdev_check_mux_children); | ||
234 | |||
235 | return result; | ||
198 | } | 236 | } |
199 | 237 | ||
200 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | 238 | static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, |