~ubuntu-branches/ubuntu/saucy/linux-ti-omap4/saucy-proposed

« back to all changes in this revision

Viewing changes to drivers/staging/comedi/drivers.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati, Stefan Bader, Upstream Kernel Changes
  • Date: 2012-08-15 17:17:43 UTC
  • Revision ID: package-import@ubuntu.com-20120815171743-h5wnuf51xe7pvdid
Tags: 3.5.0-207.13
[ Paolo Pisati ]

* Start new release

[ Stefan Bader ]

* (config) Enable getabis to use local package copies

[ Upstream Kernel Changes ]

* fixup: gargabe collect iva_seq[0|1] init
* [Config] enable all SND_OMAP_SOC_*s
* fixup: cm2xxx_3xxx.o is needed for omap2_cm_read|write_reg
* fixup: add some snd_soc_dai* helper functions
* fixup: s/snd_soc_dpcm_params/snd_soc_dpcm/g
* fixup: typo, no_host_mode and useless SDP4430 init
* fixup: enable again aess hwmod

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include <linux/pci.h>
31
31
#include <linux/usb.h>
32
32
#include <linux/errno.h>
 
33
#include <linux/kconfig.h>
33
34
#include <linux/kernel.h>
34
35
#include <linux/sched.h>
35
36
#include <linux/fcntl.h>
106
107
        __comedi_device_detach(dev);
107
108
}
108
109
 
 
110
/* do a little post-config cleanup */
 
111
/* called with module refcount incremented, decrements it */
 
112
static int comedi_device_postconfig(struct comedi_device *dev)
 
113
{
 
114
        int ret = postconfig(dev);
 
115
        module_put(dev->driver->module);
 
116
        if (ret < 0) {
 
117
                __comedi_device_detach(dev);
 
118
                return ret;
 
119
        }
 
120
        if (!dev->board_name) {
 
121
                printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
 
122
                       dev->board_name);
 
123
                dev->board_name = "BUG";
 
124
        }
 
125
        smp_wmb();
 
126
        dev->attached = 1;
 
127
        return 0;
 
128
}
 
129
 
109
130
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
110
131
{
111
132
        struct comedi_driver *driv;
121
142
                }
122
143
                if (driv->num_names) {
123
144
                        dev->board_ptr = comedi_recognize(driv, it->board_name);
124
 
                        if (dev->board_ptr == NULL) {
125
 
                                module_put(driv->module);
126
 
                                continue;
127
 
                        }
128
 
                } else {
129
 
                        if (strcmp(driv->driver_name, it->board_name)) {
130
 
                                module_put(driv->module);
131
 
                                continue;
132
 
                        }
133
 
                }
134
 
                /* initialize dev->driver here so
135
 
                 * comedi_error() can be called from attach */
136
 
                dev->driver = driv;
137
 
                ret = driv->attach(dev, it);
138
 
                if (ret < 0) {
139
 
                        module_put(dev->driver->module);
140
 
                        __comedi_device_detach(dev);
141
 
                        return ret;
142
 
                }
143
 
                goto attached;
144
 
        }
145
 
 
146
 
        /*  recognize has failed if we get here */
147
 
        /*  report valid board names before returning error */
148
 
        for (driv = comedi_drivers; driv; driv = driv->next) {
149
 
                if (!try_module_get(driv->module)) {
150
 
                        printk(KERN_INFO
151
 
                               "comedi: failed to increment module count\n");
152
 
                        continue;
153
 
                }
154
 
                comedi_report_boards(driv);
 
145
                        if (dev->board_ptr)
 
146
                                break;
 
147
                } else if (strcmp(driv->driver_name, it->board_name))
 
148
                        break;
155
149
                module_put(driv->module);
156
150
        }
157
 
        return -EIO;
158
 
 
159
 
attached:
160
 
        /* do a little post-config cleanup */
161
 
        ret = postconfig(dev);
162
 
        module_put(dev->driver->module);
 
151
        if (driv == NULL) {
 
152
                /*  recognize has failed if we get here */
 
153
                /*  report valid board names before returning error */
 
154
                for (driv = comedi_drivers; driv; driv = driv->next) {
 
155
                        if (!try_module_get(driv->module)) {
 
156
                                printk(KERN_INFO
 
157
                                       "comedi: failed to increment module count\n");
 
158
                                continue;
 
159
                        }
 
160
                        comedi_report_boards(driv);
 
161
                        module_put(driv->module);
 
162
                }
 
163
                return -EIO;
 
164
        }
 
165
        /* initialize dev->driver here so
 
166
         * comedi_error() can be called from attach */
 
167
        dev->driver = driv;
 
168
        ret = driv->attach(dev, it);
163
169
        if (ret < 0) {
 
170
                module_put(dev->driver->module);
164
171
                __comedi_device_detach(dev);
165
172
                return ret;
166
173
        }
167
 
 
168
 
        if (!dev->board_name) {
169
 
                printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
170
 
                       dev->board_name);
171
 
                dev->board_name = "BUG";
172
 
        }
173
 
        smp_wmb();
174
 
        dev->attached = 1;
175
 
 
176
 
        return 0;
 
174
        return comedi_device_postconfig(dev);
177
175
}
178
176
 
179
177
int comedi_driver_register(struct comedi_driver *driver)
242
240
                        s->len_chanlist = 1;
243
241
 
244
242
                if (s->do_cmd) {
 
243
                        unsigned int buf_size;
 
244
 
245
245
                        BUG_ON((s->subdev_flags & (SDF_CMD_READ |
246
246
                                                   SDF_CMD_WRITE)) == 0);
247
247
                        BUG_ON(!s->do_cmdtest);
257
257
                        async->subdevice = s;
258
258
                        s->async = async;
259
259
 
260
 
#define DEFAULT_BUF_MAXSIZE (64*1024)
261
 
#define DEFAULT_BUF_SIZE (64*1024)
262
 
 
263
 
                        async->max_bufsize = DEFAULT_BUF_MAXSIZE;
 
260
                        async->max_bufsize =
 
261
                                comedi_default_buf_maxsize_kb * 1024;
 
262
                        buf_size = comedi_default_buf_size_kb * 1024;
 
263
                        if (buf_size > async->max_bufsize)
 
264
                                buf_size = async->max_bufsize;
264
265
 
265
266
                        async->prealloc_buf = NULL;
266
267
                        async->prealloc_bufsz = 0;
267
 
                        if (comedi_buf_alloc(dev, s, DEFAULT_BUF_SIZE) < 0) {
 
268
                        if (comedi_buf_alloc(dev, s, buf_size) < 0) {
268
269
                                printk(KERN_INFO "Buffer allocation failed\n");
269
270
                                return -ENOMEM;
270
271
                        }
271
272
                        if (s->buf_change) {
272
 
                                ret = s->buf_change(dev, s, DEFAULT_BUF_SIZE);
 
273
                                ret = s->buf_change(dev, s, buf_size);
273
274
                                if (ret < 0)
274
275
                                        return ret;
275
276
                        }
814
815
        async->events = 0;
815
816
}
816
817
 
817
 
static int comedi_auto_config(struct device *hardware_device,
818
 
                              const char *board_name, const int *options,
819
 
                              unsigned num_options)
 
818
static int
 
819
comedi_auto_config_helper(struct device *hardware_device,
 
820
                          struct comedi_driver *driver,
 
821
                          int (*attach_wrapper) (struct comedi_device *,
 
822
                                                 void *), void *context)
820
823
{
821
 
        struct comedi_devconfig it;
822
824
        int minor;
823
825
        struct comedi_device_file_info *dev_file_info;
824
 
        int retval;
825
 
        unsigned *private_data = NULL;
 
826
        struct comedi_device *comedi_dev;
 
827
        int ret;
826
828
 
827
 
        if (!comedi_autoconfig) {
828
 
                dev_set_drvdata(hardware_device, NULL);
 
829
        if (!comedi_autoconfig)
829
830
                return 0;
830
 
        }
831
831
 
832
832
        minor = comedi_alloc_board_minor(hardware_device);
833
833
        if (minor < 0)
834
834
                return minor;
835
835
 
836
 
        private_data = kmalloc(sizeof(unsigned), GFP_KERNEL);
837
 
        if (private_data == NULL) {
838
 
                retval = -ENOMEM;
839
 
                goto cleanup;
840
 
        }
841
 
        *private_data = minor;
842
 
        dev_set_drvdata(hardware_device, private_data);
843
 
 
844
836
        dev_file_info = comedi_get_device_file_info(minor);
 
837
        comedi_dev = dev_file_info->device;
 
838
 
 
839
        mutex_lock(&comedi_dev->mutex);
 
840
        if (comedi_dev->attached)
 
841
                ret = -EBUSY;
 
842
        else if (!try_module_get(driver->module)) {
 
843
                printk(KERN_INFO "comedi: failed to increment module count\n");
 
844
                ret = -EIO;
 
845
        } else {
 
846
                /* set comedi_dev->driver here for attach wrapper */
 
847
                comedi_dev->driver = driver;
 
848
                ret = (*attach_wrapper)(comedi_dev, context);
 
849
                if (ret < 0) {
 
850
                        module_put(driver->module);
 
851
                        __comedi_device_detach(comedi_dev);
 
852
                } else {
 
853
                        ret = comedi_device_postconfig(comedi_dev);
 
854
                }
 
855
        }
 
856
        mutex_unlock(&comedi_dev->mutex);
 
857
 
 
858
        if (ret < 0)
 
859
                comedi_free_board_minor(minor);
 
860
        return ret;
 
861
}
 
862
 
 
863
static int comedi_auto_config_wrapper(struct comedi_device *dev, void *context)
 
864
{
 
865
        struct comedi_devconfig *it = context;
 
866
        struct comedi_driver *driv = dev->driver;
 
867
 
 
868
        if (driv->num_names) {
 
869
                /* look for generic board entry matching driver name, which
 
870
                 * has already been copied to it->board_name */
 
871
                dev->board_ptr = comedi_recognize(driv, it->board_name);
 
872
                if (dev->board_ptr == NULL) {
 
873
                        printk(KERN_WARNING
 
874
                               "comedi: auto config failed to find board entry"
 
875
                               " '%s' for driver '%s'\n", it->board_name,
 
876
                               driv->driver_name);
 
877
                        comedi_report_boards(driv);
 
878
                        return -EINVAL;
 
879
                }
 
880
        }
 
881
        return driv->attach(dev, it);
 
882
}
 
883
 
 
884
static int comedi_auto_config(struct device *hardware_device,
 
885
                              struct comedi_driver *driver, const int *options,
 
886
                              unsigned num_options)
 
887
{
 
888
        struct comedi_devconfig it;
845
889
 
846
890
        memset(&it, 0, sizeof(it));
847
 
        strncpy(it.board_name, board_name, COMEDI_NAMELEN);
 
891
        strncpy(it.board_name, driver->driver_name, COMEDI_NAMELEN);
848
892
        it.board_name[COMEDI_NAMELEN - 1] = '\0';
849
893
        BUG_ON(num_options > COMEDI_NDEVCONFOPTS);
850
894
        memcpy(it.options, options, num_options * sizeof(int));
851
 
 
852
 
        mutex_lock(&dev_file_info->device->mutex);
853
 
        retval = comedi_device_attach(dev_file_info->device, &it);
854
 
        mutex_unlock(&dev_file_info->device->mutex);
855
 
 
856
 
cleanup:
857
 
        if (retval < 0) {
858
 
                kfree(private_data);
859
 
                comedi_free_board_minor(minor);
860
 
        }
861
 
        return retval;
 
895
        return comedi_auto_config_helper(hardware_device, driver,
 
896
                                         comedi_auto_config_wrapper, &it);
862
897
}
863
898
 
864
899
static void comedi_auto_unconfig(struct device *hardware_device)
865
900
{
866
 
        unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
867
 
        if (minor == NULL)
868
 
                return;
869
 
 
870
 
        BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS);
871
 
 
872
 
        comedi_free_board_minor(*minor);
873
 
        dev_set_drvdata(hardware_device, NULL);
874
 
        kfree(minor);
 
901
        int minor;
 
902
 
 
903
        if (hardware_device == NULL)
 
904
                return;
 
905
        minor = comedi_find_board_minor(hardware_device);
 
906
        if (minor < 0)
 
907
                return;
 
908
        BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
 
909
        comedi_free_board_minor(minor);
875
910
}
876
911
 
877
 
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
 
912
static int comedi_old_pci_auto_config(struct pci_dev *pcidev,
 
913
                                      struct comedi_driver *driver)
878
914
{
879
915
        int options[2];
880
916
 
883
919
        /*  pci slot */
884
920
        options[1] = PCI_SLOT(pcidev->devfn);
885
921
 
886
 
        return comedi_auto_config(&pcidev->dev, board_name,
 
922
        return comedi_auto_config(&pcidev->dev, driver,
887
923
                                  options, ARRAY_SIZE(options));
888
924
}
 
925
 
 
926
static int comedi_pci_attach_wrapper(struct comedi_device *dev, void *pcidev)
 
927
{
 
928
        return dev->driver->attach_pci(dev, pcidev);
 
929
}
 
930
 
 
931
static int comedi_new_pci_auto_config(struct pci_dev *pcidev,
 
932
                                      struct comedi_driver *driver)
 
933
{
 
934
        return comedi_auto_config_helper(&pcidev->dev, driver,
 
935
                                         comedi_pci_attach_wrapper, pcidev);
 
936
}
 
937
 
 
938
int comedi_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver)
 
939
{
 
940
 
 
941
        if (driver->attach_pci)
 
942
                return comedi_new_pci_auto_config(pcidev, driver);
 
943
        else
 
944
                return comedi_old_pci_auto_config(pcidev, driver);
 
945
}
889
946
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
890
947
 
891
948
void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
894
951
}
895
952
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
896
953
 
897
 
int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name)
898
 
{
899
 
        BUG_ON(usbdev == NULL);
900
 
        return comedi_auto_config(&usbdev->dev, board_name, NULL, 0);
 
954
int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
 
955
                struct pci_driver *pci_driver)
 
956
{
 
957
        int ret;
 
958
 
 
959
        ret = comedi_driver_register(comedi_driver);
 
960
        if (ret < 0)
 
961
                return ret;
 
962
 
 
963
        /* FIXME: Remove this test after auditing all comedi pci drivers */
 
964
        if (!pci_driver->name)
 
965
                pci_driver->name = comedi_driver->driver_name;
 
966
 
 
967
        ret = pci_register_driver(pci_driver);
 
968
        if (ret < 0) {
 
969
                comedi_driver_unregister(comedi_driver);
 
970
                return ret;
 
971
        }
 
972
 
 
973
        return 0;
 
974
}
 
975
EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
 
976
 
 
977
void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
 
978
                struct pci_driver *pci_driver)
 
979
{
 
980
        pci_unregister_driver(pci_driver);
 
981
        comedi_driver_unregister(comedi_driver);
 
982
}
 
983
EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
 
984
 
 
985
#if IS_ENABLED(CONFIG_USB)
 
986
 
 
987
static int comedi_old_usb_auto_config(struct usb_interface *intf,
 
988
                                      struct comedi_driver *driver)
 
989
{
 
990
        return comedi_auto_config(&intf->dev, driver, NULL, 0);
 
991
}
 
992
 
 
993
static int comedi_usb_attach_wrapper(struct comedi_device *dev, void *intf)
 
994
{
 
995
        return dev->driver->attach_usb(dev, intf);
 
996
}
 
997
 
 
998
static int comedi_new_usb_auto_config(struct usb_interface *intf,
 
999
                                      struct comedi_driver *driver)
 
1000
{
 
1001
        return comedi_auto_config_helper(&intf->dev, driver,
 
1002
                                         comedi_usb_attach_wrapper, intf);
 
1003
}
 
1004
 
 
1005
int comedi_usb_auto_config(struct usb_interface *intf,
 
1006
                           struct comedi_driver *driver)
 
1007
{
 
1008
        BUG_ON(intf == NULL);
 
1009
        if (driver->attach_usb)
 
1010
                return comedi_new_usb_auto_config(intf, driver);
 
1011
        else
 
1012
                return comedi_old_usb_auto_config(intf, driver);
901
1013
}
902
1014
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
903
1015
 
904
 
void comedi_usb_auto_unconfig(struct usb_device *usbdev)
 
1016
void comedi_usb_auto_unconfig(struct usb_interface *intf)
905
1017
{
906
 
        BUG_ON(usbdev == NULL);
907
 
        comedi_auto_unconfig(&usbdev->dev);
 
1018
        BUG_ON(intf == NULL);
 
1019
        comedi_auto_unconfig(&intf->dev);
908
1020
}
909
1021
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
 
1022
 
 
1023
int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
 
1024
                struct usb_driver *usb_driver)
 
1025
{
 
1026
        int ret;
 
1027
 
 
1028
        ret = comedi_driver_register(comedi_driver);
 
1029
        if (ret < 0)
 
1030
                return ret;
 
1031
 
 
1032
        ret = usb_register(usb_driver);
 
1033
        if (ret < 0) {
 
1034
                comedi_driver_unregister(comedi_driver);
 
1035
                return ret;
 
1036
        }
 
1037
 
 
1038
        return 0;
 
1039
}
 
1040
EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
 
1041
 
 
1042
void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
 
1043
                struct usb_driver *usb_driver)
 
1044
{
 
1045
        usb_deregister(usb_driver);
 
1046
        comedi_driver_unregister(comedi_driver);
 
1047
}
 
1048
EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
 
1049
 
 
1050
#endif