aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2005-08-09 14:17:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-05 12:14:25 -0400
commita89ba0bc02e82920a0f4137aa5d655ac0366cc28 (patch)
tree98489ed77a287a81ff4ad7233fd543e59e58c328
parent3b6c0634cc989f0735a1541ccf9288947685cab5 (diff)
[PATCH] I2C: Rewrite i2c_probe
i2c_probe was quite complex and slow, so I rewrote it in a more efficient and hopefully clearer way. Note that this slightly changes the way the module parameters are handled. This shouldn't change anything for the most common cases though. For one thing, the function now respects the order of the parameters for address probing. It used to always do lower addresses first. The new approach gives the user more control. For another, ignore addresses don't overrule probe addresses anymore. This could have been restored the way it was at the cost of a few more lines of code, but I don't think it's worth it. Both lists are given as module parameters, so a user would be quite silly to specify the same addresses in both lists. The normal addresses list is the only one that isn't controlled by a module parameter, thus is the only one the user may reasonably want to remove an address from. Another significant change is the fact that i2c_probe() will no more stop when a detection function returns -ENODEV. Just because a driver found a chip it doesn't support isn't a valid reason to stop all probings for this one driver. This closes the long standing lm_sensors ticket #1807. http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket=1807 I updated the documentation accordingly. In terms of algorithmic complexity, the new code is way better. If I is the ignore address count, P the probe address count, N the normal address count and F the force address count, the old code was doing 128 * (F + I + P + N) iterations max, while the new code does F + P + ((I+1) * N) iterations max. For the most common case where F, I and P are empty, this is down from 128 * N to N. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/i2c/writing-clients7
-rw-r--r--drivers/i2c/i2c-core.c165
2 files changed, 93 insertions, 79 deletions
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 97e138cbb2a9..077275722a7c 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -241,9 +241,10 @@ Below, some things are only needed if this is a `sensors' driver. Those
241parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */ 241parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
242markers. 242markers.
243 243
244This function should only return an error (any value != 0) if there is 244Returning an error different from -ENODEV in a detect function will cause
245some reason why no more detection should be done anymore. If the 245the detection to stop: other addresses and adapters won't be scanned.
246detection just fails for this address, return 0. 246This should only be done on fatal or internal errors, such as a memory
247shortage or i2c_attach_client failing.
247 248
248For now, you can ignore the `flags' parameter. It is there for future use. 249For now, you can ignore the `flags' parameter. It is there for future use.
249 250
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 372b5996d045..bee0148dfab8 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -662,107 +662,120 @@ int i2c_control(struct i2c_client *client,
662 * Will not work for 10-bit addresses! 662 * Will not work for 10-bit addresses!
663 * ---------------------------------------------------- 663 * ----------------------------------------------------
664 */ 664 */
665/* Return: kind (>= 0) if force found, -1 if not found */ 665static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
666static inline int i2c_probe_forces(struct i2c_adapter *adapter, int addr, 666 int (*found_proc) (struct i2c_adapter *, int, int))
667 unsigned short **forces)
668{ 667{
669 unsigned short kind; 668 int err;
670 int j, adap_id = i2c_adapter_id(adapter); 669
671 670 /* Make sure the address is valid */
672 for (kind = 0; forces[kind]; kind++) { 671 if (addr < 0x03 || addr > 0x77) {
673 for (j = 0; forces[kind][j] != I2C_CLIENT_END; j += 2) { 672 dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
674 if ((forces[kind][j] == adap_id || 673 addr);
675 forces[kind][j] == ANY_I2C_BUS) 674 return -EINVAL;
676 && forces[kind][j + 1] == addr) {
677 dev_dbg(&adapter->dev, "found force parameter, "
678 "addr 0x%02x, kind %u\n", addr, kind);
679 return kind;
680 }
681 }
682 } 675 }
683 676
684 return -1; 677 /* Skip if already in use */
678 if (i2c_check_addr(adapter, addr))
679 return 0;
680
681 /* Make sure there is something at this address, unless forced */
682 if (kind < 0
683 && i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0)
684 return 0;
685
686 /* Finally call the custom detection function */
687 err = found_proc(adapter, addr, kind);
688
689 /* -ENODEV can be returned if there is a chip at the given address
690 but it isn't supported by this chip driver. We catch it here as
691 this isn't an error. */
692 return (err == -ENODEV) ? 0 : err;
685} 693}
686 694
687int i2c_probe(struct i2c_adapter *adapter, 695int i2c_probe(struct i2c_adapter *adapter,
688 struct i2c_client_address_data *address_data, 696 struct i2c_client_address_data *address_data,
689 int (*found_proc) (struct i2c_adapter *, int, int)) 697 int (*found_proc) (struct i2c_adapter *, int, int))
690{ 698{
691 int addr,i,found,err; 699 int i, err;
692 int adap_id = i2c_adapter_id(adapter); 700 int adap_id = i2c_adapter_id(adapter);
693 701
694 /* Forget it if we can't probe using SMBUS_QUICK */ 702 /* Forget it if we can't probe using SMBUS_QUICK */
695 if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK)) 703 if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
696 return -1; 704 return -1;
697 705
698 for (addr = 0x00; addr <= 0x7f; addr++) { 706 /* Force entries are done first, and are not affected by ignore
699 707 entries */
700 /* Skip if already in use */ 708 if (address_data->forces) {
701 if (i2c_check_addr(adapter,addr)) 709 unsigned short **forces = address_data->forces;
702 continue; 710 int kind;
703 711
704 /* If it is in one of the force entries, we don't do any detection 712 for (kind = 0; forces[kind]; kind++) {
705 at all */ 713 for (i = 0; forces[kind][i] != I2C_CLIENT_END;
706 found = 0; 714 i += 2) {
707 715 if (forces[kind][i] == adap_id
708 if (address_data->forces) { 716 || forces[kind][i] == ANY_I2C_BUS) {
709 int kind = i2c_probe_forces(adapter, addr, 717 dev_dbg(&adapter->dev, "found force "
710 address_data->forces); 718 "parameter for adapter %d, "
711 if (kind >= 0) { /* force found */ 719 "addr 0x%02x, kind %d\n",
712 if ((err = found_proc(adapter, addr, kind))) 720 adap_id, forces[kind][i + 1],
713 return err; 721 kind);
714 continue; 722 err = i2c_probe_address(adapter,
715 } 723 forces[kind][i + 1],
716 } 724 kind, found_proc);
717 725 if (err)
718 /* If this address is in one of the ignores, we can forget about 726 return err;
719 it right now */ 727 }
720 for (i = 0;
721 !found && (address_data->ignore[i] != I2C_CLIENT_END);
722 i += 2) {
723 if (((adap_id == address_data->ignore[i]) ||
724 ((address_data->ignore[i] == ANY_I2C_BUS))) &&
725 (addr == address_data->ignore[i+1])) {
726 dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
727 "addr %04x\n", adap_id ,addr);
728 found = 1;
729 } 728 }
730 } 729 }
731 if (found) 730 }
732 continue;
733 731
734 /* Now, we will do a detection, but only if it is in the normal or 732 /* Probe entries are done second, and are not affected by ignore
735 probe entries */ 733 entries either */
736 for (i = 0; 734 for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
737 !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); 735 if (address_data->probe[i] == adap_id
738 i += 1) { 736 || address_data->probe[i] == ANY_I2C_BUS) {
739 if (addr == address_data->normal_i2c[i]) { 737 dev_dbg(&adapter->dev, "found probe parameter for "
740 found = 1; 738 "adapter %d, addr 0x%02x\n", adap_id,
741 dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, " 739 address_data->probe[i + 1]);
742 "addr %02x\n", adap_id, addr); 740 err = i2c_probe_address(adapter,
743 } 741 address_data->probe[i + 1],
742 -1, found_proc);
743 if (err)
744 return err;
744 } 745 }
746 }
745 747
746 for (i = 0; 748 /* Normal entries are done last, unless shadowed by an ignore entry */
747 !found && (address_data->probe[i] != I2C_CLIENT_END); 749 for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
748 i += 2) { 750 int j, ignore;
749 if (((adap_id == address_data->probe[i]) || 751
750 ((address_data->probe[i] == ANY_I2C_BUS))) && 752 ignore = 0;
751 (addr == address_data->probe[i+1])) { 753 for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
752 found = 1; 754 j += 2) {
753 dev_dbg(&adapter->dev, "found probe parameter for adapter %d, " 755 if ((address_data->ignore[j] == adap_id ||
754 "addr %04x\n", adap_id,addr); 756 address_data->ignore[j] == ANY_I2C_BUS)
757 && address_data->ignore[j + 1]
758 == address_data->normal_i2c[i]) {
759 dev_dbg(&adapter->dev, "found ignore "
760 "parameter for adapter %d, "
761 "addr 0x%02x\n", adap_id,
762 address_data->ignore[j + 1]);
755 } 763 }
764 ignore = 1;
765 break;
756 } 766 }
757 if (!found) 767 if (ignore)
758 continue; 768 continue;
759 769
760 /* OK, so we really should examine this address. First check 770 dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
761 whether there is some client here at all! */ 771 "addr 0x%02x\n", adap_id,
762 if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) 772 address_data->normal_i2c[i]);
763 if ((err = found_proc(adapter,addr,-1))) 773 err = i2c_probe_address(adapter, address_data->normal_i2c[i],
764 return err; 774 -1, found_proc);
775 if (err)
776 return err;
765 } 777 }
778
766 return 0; 779 return 0;
767} 780}
768 781