diff options
Diffstat (limited to 'drivers')
239 files changed, 12090 insertions, 7178 deletions
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 6b115f6c4313..6afceb3d4034 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -30,18 +30,13 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
32 | #include <acpi/acpi_drivers.h> | 32 | #include <acpi/acpi_drivers.h> |
33 | #include <asm/mwait.h> | ||
33 | 34 | ||
34 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" | 35 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" |
35 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" | 36 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" |
36 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 | 37 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 |
37 | static DEFINE_MUTEX(isolated_cpus_lock); | 38 | static DEFINE_MUTEX(isolated_cpus_lock); |
38 | 39 | ||
39 | #define MWAIT_SUBSTATE_MASK (0xf) | ||
40 | #define MWAIT_CSTATE_MASK (0xf) | ||
41 | #define MWAIT_SUBSTATE_SIZE (4) | ||
42 | #define CPUID_MWAIT_LEAF (5) | ||
43 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | ||
44 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | ||
45 | static unsigned long power_saving_mwait_eax; | 40 | static unsigned long power_saving_mwait_eax; |
46 | 41 | ||
47 | static unsigned char tsc_detected_unstable; | 42 | static unsigned char tsc_detected_unstable; |
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index f7619600270a..af308d03f492 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
@@ -204,6 +204,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { | |||
204 | }, | 204 | }, |
205 | }, | 205 | }, |
206 | { | 206 | { |
207 | /* | ||
208 | * There have a NVIF method in MSI GX723 DSDT need call by Nvidia | ||
209 | * driver (e.g. nouveau) when user press brightness hotkey. | ||
210 | * Currently, nouveau driver didn't do the job and it causes there | ||
211 | * have a infinite while loop in DSDT when user press hotkey. | ||
212 | * We add MSI GX723's dmi information to this table for workaround | ||
213 | * this issue. | ||
214 | * Will remove MSI GX723 from the table after nouveau grows support. | ||
215 | */ | ||
216 | .callback = dmi_disable_osi_vista, | ||
217 | .ident = "MSI GX723", | ||
218 | .matches = { | ||
219 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), | ||
220 | DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), | ||
221 | }, | ||
222 | }, | ||
223 | { | ||
207 | .callback = dmi_disable_osi_vista, | 224 | .callback = dmi_disable_osi_vista, |
208 | .ident = "Sony VGN-NS10J_S", | 225 | .ident = "Sony VGN-NS10J_S", |
209 | .matches = { | 226 | .matches = { |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index b618f888d66b..bec561c14beb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -346,4 +346,5 @@ void __init acpi_early_processor_set_pdc(void) | |||
346 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | 346 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, |
347 | ACPI_UINT32_MAX, | 347 | ACPI_UINT32_MAX, |
348 | early_init_pdc, NULL, NULL, NULL); | 348 | early_init_pdc, NULL, NULL, NULL); |
349 | acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL); | ||
349 | } | 350 | } |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index d31590e7011b..2737b9752205 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -298,7 +298,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) | |||
298 | 298 | ||
299 | amba_put_disable_pclk(dev); | 299 | amba_put_disable_pclk(dev); |
300 | 300 | ||
301 | if (cid == 0xb105f00d) | 301 | if (cid == AMBA_CID) |
302 | dev->periphid = pid; | 302 | dev->periphid = pid; |
303 | 303 | ||
304 | if (!dev->periphid) | 304 | if (!dev->periphid) |
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index e944aa0c5517..806292160b3f 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/ata.h> | 34 | #include <linux/ata.h> |
35 | #include <linux/libata.h> | 35 | #include <linux/libata.h> |
36 | 36 | ||
37 | #include <pcmcia/cs.h> | ||
38 | #include <pcmcia/cistpl.h> | 37 | #include <pcmcia/cistpl.h> |
39 | #include <pcmcia/ds.h> | 38 | #include <pcmcia/ds.h> |
40 | #include <pcmcia/cisreg.h> | 39 | #include <pcmcia/cisreg.h> |
@@ -168,63 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = { | |||
168 | }; | 167 | }; |
169 | 168 | ||
170 | 169 | ||
171 | struct pcmcia_config_check { | 170 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) |
172 | unsigned long ctl_base; | ||
173 | int skip_vcc; | ||
174 | int is_kme; | ||
175 | }; | ||
176 | |||
177 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, | ||
178 | cistpl_cftable_entry_t *cfg, | ||
179 | cistpl_cftable_entry_t *dflt, | ||
180 | unsigned int vcc, | ||
181 | void *priv_data) | ||
182 | { | 171 | { |
183 | struct pcmcia_config_check *stk = priv_data; | 172 | int *is_kme = priv_data; |
184 | 173 | ||
185 | /* Check for matching Vcc, unless we're desperate */ | 174 | if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { |
186 | if (!stk->skip_vcc) { | 175 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
187 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | 176 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
188 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
189 | return -ENODEV; | ||
190 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
191 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
192 | return -ENODEV; | ||
193 | } | ||
194 | } | 177 | } |
178 | pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | ||
179 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
195 | 180 | ||
196 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 181 | if (pdev->resource[1]->end) { |
197 | pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 182 | pdev->resource[0]->end = 8; |
198 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 183 | pdev->resource[1]->end = (*is_kme) ? 2 : 1; |
199 | pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 184 | } else { |
200 | 185 | if (pdev->resource[0]->end < 16) | |
201 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
202 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
203 | pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
204 | pdev->resource[0]->start = io->win[0].base; | ||
205 | if (!(io->flags & CISTPL_IO_16BIT)) { | ||
206 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
207 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
208 | } | ||
209 | if (io->nwin == 2) { | ||
210 | pdev->resource[0]->end = 8; | ||
211 | pdev->resource[1]->start = io->win[1].base; | ||
212 | pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; | ||
213 | if (pcmcia_request_io(pdev) != 0) | ||
214 | return -ENODEV; | ||
215 | stk->ctl_base = pdev->resource[1]->start; | ||
216 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
217 | pdev->resource[0]->end = io->win[0].len; | ||
218 | pdev->resource[1]->end = 0; | ||
219 | if (pcmcia_request_io(pdev) != 0) | ||
220 | return -ENODEV; | ||
221 | stk->ctl_base = pdev->resource[0]->start + 0x0e; | ||
222 | } else | ||
223 | return -ENODEV; | 186 | return -ENODEV; |
224 | /* If we've got this far, we're done */ | ||
225 | return 0; | ||
226 | } | 187 | } |
227 | return -ENODEV; | 188 | |
189 | return pcmcia_request_io(pdev); | ||
228 | } | 190 | } |
229 | 191 | ||
230 | /** | 192 | /** |
@@ -239,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
239 | { | 201 | { |
240 | struct ata_host *host; | 202 | struct ata_host *host; |
241 | struct ata_port *ap; | 203 | struct ata_port *ap; |
242 | struct pcmcia_config_check *stk = NULL; | ||
243 | int is_kme = 0, ret = -ENOMEM, p; | 204 | int is_kme = 0, ret = -ENOMEM, p; |
244 | unsigned long io_base, ctl_base; | 205 | unsigned long io_base, ctl_base; |
245 | void __iomem *io_addr, *ctl_addr; | 206 | void __iomem *io_addr, *ctl_addr; |
@@ -247,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
247 | struct ata_port_operations *ops = &pcmcia_port_ops; | 208 | struct ata_port_operations *ops = &pcmcia_port_ops; |
248 | 209 | ||
249 | /* Set up attributes in order to probe card and get resources */ | 210 | /* Set up attributes in order to probe card and get resources */ |
250 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 211 | pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO | |
251 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | 212 | CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; |
252 | pdev->conf.Attributes = CONF_ENABLE_IRQ; | ||
253 | pdev->conf.IntType = INT_MEMORY_AND_IO; | ||
254 | 213 | ||
255 | /* See if we have a manufacturer identifier. Use it to set is_kme for | 214 | /* See if we have a manufacturer identifier. Use it to set is_kme for |
256 | vendor quirks */ | 215 | vendor quirks */ |
@@ -258,25 +217,21 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
258 | ((pdev->card_id == PRODID_KME_KXLC005_A) || | 217 | ((pdev->card_id == PRODID_KME_KXLC005_A) || |
259 | (pdev->card_id == PRODID_KME_KXLC005_B))); | 218 | (pdev->card_id == PRODID_KME_KXLC005_B))); |
260 | 219 | ||
261 | /* Allocate resoure probing structures */ | 220 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) { |
262 | 221 | pdev->config_flags &= ~CONF_AUTO_CHECK_VCC; | |
263 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); | 222 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) |
264 | if (!stk) | ||
265 | goto out1; | ||
266 | stk->is_kme = is_kme; | ||
267 | stk->skip_vcc = io_base = ctl_base = 0; | ||
268 | |||
269 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) { | ||
270 | stk->skip_vcc = 1; | ||
271 | if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) | ||
272 | goto failed; /* No suitable config found */ | 223 | goto failed; /* No suitable config found */ |
273 | } | 224 | } |
274 | io_base = pdev->resource[0]->start; | 225 | io_base = pdev->resource[0]->start; |
275 | ctl_base = stk->ctl_base; | 226 | if (pdev->resource[1]->end) |
227 | ctl_base = pdev->resource[1]->start; | ||
228 | else | ||
229 | ctl_base = pdev->resource[0]->start + 0x0e; | ||
230 | |||
276 | if (!pdev->irq) | 231 | if (!pdev->irq) |
277 | goto failed; | 232 | goto failed; |
278 | 233 | ||
279 | ret = pcmcia_request_configuration(pdev, &pdev->conf); | 234 | ret = pcmcia_enable_device(pdev); |
280 | if (ret) | 235 | if (ret) |
281 | goto failed; | 236 | goto failed; |
282 | 237 | ||
@@ -329,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
329 | goto failed; | 284 | goto failed; |
330 | 285 | ||
331 | pdev->priv = host; | 286 | pdev->priv = host; |
332 | kfree(stk); | ||
333 | return 0; | 287 | return 0; |
334 | 288 | ||
335 | failed: | 289 | failed: |
336 | kfree(stk); | ||
337 | pcmcia_disable_device(pdev); | 290 | pcmcia_disable_device(pdev); |
338 | out1: | ||
339 | return ret; | 291 | return ret; |
340 | } | 292 | } |
341 | 293 | ||
@@ -430,9 +382,7 @@ MODULE_DEVICE_TABLE(pcmcia, pcmcia_devices); | |||
430 | 382 | ||
431 | static struct pcmcia_driver pcmcia_driver = { | 383 | static struct pcmcia_driver pcmcia_driver = { |
432 | .owner = THIS_MODULE, | 384 | .owner = THIS_MODULE, |
433 | .drv = { | 385 | .name = DRV_NAME, |
434 | .name = DRV_NAME, | ||
435 | }, | ||
436 | .id_table = pcmcia_devices, | 386 | .id_table = pcmcia_devices, |
437 | .probe = pcmcia_init_one, | 387 | .probe = pcmcia_init_one, |
438 | .remove = pcmcia_remove_one, | 388 | .remove = pcmcia_remove_one, |
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index ee9ddeb53417..8cb0347dec28 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c | |||
@@ -3156,7 +3156,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev, | |||
3156 | { | 3156 | { |
3157 | struct atm_dev *dev; | 3157 | struct atm_dev *dev; |
3158 | IADEV *iadev; | 3158 | IADEV *iadev; |
3159 | unsigned long flags; | ||
3160 | int ret; | 3159 | int ret; |
3161 | 3160 | ||
3162 | iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); | 3161 | iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); |
@@ -3188,19 +3187,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev, | |||
3188 | ia_dev[iadev_count] = iadev; | 3187 | ia_dev[iadev_count] = iadev; |
3189 | _ia_dev[iadev_count] = dev; | 3188 | _ia_dev[iadev_count] = dev; |
3190 | iadev_count++; | 3189 | iadev_count++; |
3191 | spin_lock_init(&iadev->misc_lock); | ||
3192 | /* First fixes first. I don't want to think about this now. */ | ||
3193 | spin_lock_irqsave(&iadev->misc_lock, flags); | ||
3194 | if (ia_init(dev) || ia_start(dev)) { | 3190 | if (ia_init(dev) || ia_start(dev)) { |
3195 | IF_INIT(printk("IA register failed!\n");) | 3191 | IF_INIT(printk("IA register failed!\n");) |
3196 | iadev_count--; | 3192 | iadev_count--; |
3197 | ia_dev[iadev_count] = NULL; | 3193 | ia_dev[iadev_count] = NULL; |
3198 | _ia_dev[iadev_count] = NULL; | 3194 | _ia_dev[iadev_count] = NULL; |
3199 | spin_unlock_irqrestore(&iadev->misc_lock, flags); | ||
3200 | ret = -EINVAL; | 3195 | ret = -EINVAL; |
3201 | goto err_out_deregister_dev; | 3196 | goto err_out_deregister_dev; |
3202 | } | 3197 | } |
3203 | spin_unlock_irqrestore(&iadev->misc_lock, flags); | ||
3204 | IF_EVENT(printk("iadev_count = %d\n", iadev_count);) | 3198 | IF_EVENT(printk("iadev_count = %d\n", iadev_count);) |
3205 | 3199 | ||
3206 | iadev->next_board = ia_boards; | 3200 | iadev->next_board = ia_boards; |
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index b2cd20f549cb..077735e0e04b 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h | |||
@@ -1022,7 +1022,7 @@ typedef struct iadev_t { | |||
1022 | struct dle_q rx_dle_q; | 1022 | struct dle_q rx_dle_q; |
1023 | struct free_desc_q *rx_free_desc_qhead; | 1023 | struct free_desc_q *rx_free_desc_qhead; |
1024 | struct sk_buff_head rx_dma_q; | 1024 | struct sk_buff_head rx_dma_q; |
1025 | spinlock_t rx_lock, misc_lock; | 1025 | spinlock_t rx_lock; |
1026 | struct atm_vcc **rx_open; /* list of all open VCs */ | 1026 | struct atm_vcc **rx_open; /* list of all open VCs */ |
1027 | u16 num_rx_desc, rx_buf_sz, rxing; | 1027 | u16 num_rx_desc, rx_buf_sz, rxing; |
1028 | u32 rx_pkt_ram, rx_tmp_cnt; | 1028 | u32 rx_pkt_ram, rx_tmp_cnt; |
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f916ddf63938..f46138ab38b6 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
@@ -444,6 +444,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, | |||
444 | struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); | 444 | struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); |
445 | struct solos_card *card = atmdev->dev_data; | 445 | struct solos_card *card = atmdev->dev_data; |
446 | struct sk_buff *skb; | 446 | struct sk_buff *skb; |
447 | unsigned int len; | ||
447 | 448 | ||
448 | spin_lock(&card->cli_queue_lock); | 449 | spin_lock(&card->cli_queue_lock); |
449 | skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]); | 450 | skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]); |
@@ -451,11 +452,12 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, | |||
451 | if(skb == NULL) | 452 | if(skb == NULL) |
452 | return sprintf(buf, "No data.\n"); | 453 | return sprintf(buf, "No data.\n"); |
453 | 454 | ||
454 | memcpy(buf, skb->data, skb->len); | 455 | len = skb->len; |
455 | dev_dbg(&card->dev->dev, "len: %d\n", skb->len); | 456 | memcpy(buf, skb->data, len); |
457 | dev_dbg(&card->dev->dev, "len: %d\n", len); | ||
456 | 458 | ||
457 | kfree_skb(skb); | 459 | kfree_skb(skb); |
458 | return skb->len; | 460 | return len; |
459 | } | 461 | } |
460 | 462 | ||
461 | static int send_command(struct solos_card *card, int dev, const char *buf, size_t size) | 463 | static int send_command(struct solos_card *card, int dev, const char *buf, size_t size) |
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index cbccf9a3cee4..abe46edfe5b4 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o | |||
3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o | 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o |
4 | obj-$(CONFIG_PM_OPS) += generic_ops.o | 4 | obj-$(CONFIG_PM_OPS) += generic_ops.o |
5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o | 5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
6 | obj-$(CONFIG_PM_OPP) += opp.o | ||
6 | 7 | ||
7 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG | 8 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
8 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG | 9 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG |
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index 4b29d4981253..81f2c84697f4 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
@@ -46,7 +46,7 @@ int pm_generic_runtime_suspend(struct device *dev) | |||
46 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 46 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
47 | int ret; | 47 | int ret; |
48 | 48 | ||
49 | ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL; | 49 | ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0; |
50 | 50 | ||
51 | return ret; | 51 | return ret; |
52 | } | 52 | } |
@@ -65,7 +65,7 @@ int pm_generic_runtime_resume(struct device *dev) | |||
65 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 65 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
66 | int ret; | 66 | int ret; |
67 | 67 | ||
68 | ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL; | 68 | ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0; |
69 | 69 | ||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 276d5a701dc3..31b526661ec4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -51,6 +51,8 @@ static pm_message_t pm_transition; | |||
51 | */ | 51 | */ |
52 | static bool transition_started; | 52 | static bool transition_started; |
53 | 53 | ||
54 | static int async_error; | ||
55 | |||
54 | /** | 56 | /** |
55 | * device_pm_init - Initialize the PM-related part of a device object. | 57 | * device_pm_init - Initialize the PM-related part of a device object. |
56 | * @dev: Device object being initialized. | 58 | * @dev: Device object being initialized. |
@@ -60,7 +62,8 @@ void device_pm_init(struct device *dev) | |||
60 | dev->power.status = DPM_ON; | 62 | dev->power.status = DPM_ON; |
61 | init_completion(&dev->power.completion); | 63 | init_completion(&dev->power.completion); |
62 | complete_all(&dev->power.completion); | 64 | complete_all(&dev->power.completion); |
63 | dev->power.wakeup_count = 0; | 65 | dev->power.wakeup = NULL; |
66 | spin_lock_init(&dev->power.lock); | ||
64 | pm_runtime_init(dev); | 67 | pm_runtime_init(dev); |
65 | } | 68 | } |
66 | 69 | ||
@@ -120,6 +123,7 @@ void device_pm_remove(struct device *dev) | |||
120 | mutex_lock(&dpm_list_mtx); | 123 | mutex_lock(&dpm_list_mtx); |
121 | list_del_init(&dev->power.entry); | 124 | list_del_init(&dev->power.entry); |
122 | mutex_unlock(&dpm_list_mtx); | 125 | mutex_unlock(&dpm_list_mtx); |
126 | device_wakeup_disable(dev); | ||
123 | pm_runtime_remove(dev); | 127 | pm_runtime_remove(dev); |
124 | } | 128 | } |
125 | 129 | ||
@@ -407,7 +411,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, | |||
407 | static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) | 411 | static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) |
408 | { | 412 | { |
409 | ktime_t calltime; | 413 | ktime_t calltime; |
410 | s64 usecs64; | 414 | u64 usecs64; |
411 | int usecs; | 415 | int usecs; |
412 | 416 | ||
413 | calltime = ktime_get(); | 417 | calltime = ktime_get(); |
@@ -600,6 +604,7 @@ static void dpm_resume(pm_message_t state) | |||
600 | INIT_LIST_HEAD(&list); | 604 | INIT_LIST_HEAD(&list); |
601 | mutex_lock(&dpm_list_mtx); | 605 | mutex_lock(&dpm_list_mtx); |
602 | pm_transition = state; | 606 | pm_transition = state; |
607 | async_error = 0; | ||
603 | 608 | ||
604 | list_for_each_entry(dev, &dpm_list, power.entry) { | 609 | list_for_each_entry(dev, &dpm_list, power.entry) { |
605 | if (dev->power.status < DPM_OFF) | 610 | if (dev->power.status < DPM_OFF) |
@@ -829,8 +834,6 @@ static int legacy_suspend(struct device *dev, pm_message_t state, | |||
829 | return error; | 834 | return error; |
830 | } | 835 | } |
831 | 836 | ||
832 | static int async_error; | ||
833 | |||
834 | /** | 837 | /** |
835 | * device_suspend - Execute "suspend" callbacks for given device. | 838 | * device_suspend - Execute "suspend" callbacks for given device. |
836 | * @dev: Device to handle. | 839 | * @dev: Device to handle. |
@@ -885,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
885 | device_unlock(dev); | 888 | device_unlock(dev); |
886 | complete_all(&dev->power.completion); | 889 | complete_all(&dev->power.completion); |
887 | 890 | ||
891 | if (error) | ||
892 | async_error = error; | ||
893 | |||
888 | return error; | 894 | return error; |
889 | } | 895 | } |
890 | 896 | ||
@@ -894,10 +900,8 @@ static void async_suspend(void *data, async_cookie_t cookie) | |||
894 | int error; | 900 | int error; |
895 | 901 | ||
896 | error = __device_suspend(dev, pm_transition, true); | 902 | error = __device_suspend(dev, pm_transition, true); |
897 | if (error) { | 903 | if (error) |
898 | pm_dev_err(dev, pm_transition, " async", error); | 904 | pm_dev_err(dev, pm_transition, " async", error); |
899 | async_error = error; | ||
900 | } | ||
901 | 905 | ||
902 | put_device(dev); | 906 | put_device(dev); |
903 | } | 907 | } |
@@ -1085,8 +1089,9 @@ EXPORT_SYMBOL_GPL(__suspend_report_result); | |||
1085 | * @dev: Device to wait for. | 1089 | * @dev: Device to wait for. |
1086 | * @subordinate: Device that needs to wait for @dev. | 1090 | * @subordinate: Device that needs to wait for @dev. |
1087 | */ | 1091 | */ |
1088 | void device_pm_wait_for_dev(struct device *subordinate, struct device *dev) | 1092 | int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) |
1089 | { | 1093 | { |
1090 | dpm_wait(dev, subordinate->power.async_suspend); | 1094 | dpm_wait(dev, subordinate->power.async_suspend); |
1095 | return async_error; | ||
1091 | } | 1096 | } |
1092 | EXPORT_SYMBOL_GPL(device_pm_wait_for_dev); | 1097 | EXPORT_SYMBOL_GPL(device_pm_wait_for_dev); |
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c new file mode 100644 index 000000000000..2bb9b4cf59d7 --- /dev/null +++ b/drivers/base/power/opp.c | |||
@@ -0,0 +1,628 @@ | |||
1 | /* | ||
2 | * Generic OPP Interface | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Texas Instruments Incorporated. | ||
5 | * Nishanth Menon | ||
6 | * Romit Dasgupta | ||
7 | * Kevin Hilman | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/cpufreq.h> | ||
20 | #include <linux/list.h> | ||
21 | #include <linux/rculist.h> | ||
22 | #include <linux/rcupdate.h> | ||
23 | #include <linux/opp.h> | ||
24 | |||
25 | /* | ||
26 | * Internal data structure organization with the OPP layer library is as | ||
27 | * follows: | ||
28 | * dev_opp_list (root) | ||
29 | * |- device 1 (represents voltage domain 1) | ||
30 | * | |- opp 1 (availability, freq, voltage) | ||
31 | * | |- opp 2 .. | ||
32 | * ... ... | ||
33 | * | `- opp n .. | ||
34 | * |- device 2 (represents the next voltage domain) | ||
35 | * ... | ||
36 | * `- device m (represents mth voltage domain) | ||
37 | * device 1, 2.. are represented by dev_opp structure while each opp | ||
38 | * is represented by the opp structure. | ||
39 | */ | ||
40 | |||
41 | /** | ||
42 | * struct opp - Generic OPP description structure | ||
43 | * @node: opp list node. The nodes are maintained throughout the lifetime | ||
44 | * of boot. It is expected only an optimal set of OPPs are | ||
45 | * added to the library by the SoC framework. | ||
46 | * RCU usage: opp list is traversed with RCU locks. node | ||
47 | * modification is possible realtime, hence the modifications | ||
48 | * are protected by the dev_opp_list_lock for integrity. | ||
49 | * IMPORTANT: the opp nodes should be maintained in increasing | ||
50 | * order. | ||
51 | * @available: true/false - marks if this OPP as available or not | ||
52 | * @rate: Frequency in hertz | ||
53 | * @u_volt: Nominal voltage in microvolts corresponding to this OPP | ||
54 | * @dev_opp: points back to the device_opp struct this opp belongs to | ||
55 | * | ||
56 | * This structure stores the OPP information for a given device. | ||
57 | */ | ||
58 | struct opp { | ||
59 | struct list_head node; | ||
60 | |||
61 | bool available; | ||
62 | unsigned long rate; | ||
63 | unsigned long u_volt; | ||
64 | |||
65 | struct device_opp *dev_opp; | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * struct device_opp - Device opp structure | ||
70 | * @node: list node - contains the devices with OPPs that | ||
71 | * have been registered. Nodes once added are not modified in this | ||
72 | * list. | ||
73 | * RCU usage: nodes are not modified in the list of device_opp, | ||
74 | * however addition is possible and is secured by dev_opp_list_lock | ||
75 | * @dev: device pointer | ||
76 | * @opp_list: list of opps | ||
77 | * | ||
78 | * This is an internal data structure maintaining the link to opps attached to | ||
79 | * a device. This structure is not meant to be shared to users as it is | ||
80 | * meant for book keeping and private to OPP library | ||
81 | */ | ||
82 | struct device_opp { | ||
83 | struct list_head node; | ||
84 | |||
85 | struct device *dev; | ||
86 | struct list_head opp_list; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * The root of the list of all devices. All device_opp structures branch off | ||
91 | * from here, with each device_opp containing the list of opp it supports in | ||
92 | * various states of availability. | ||
93 | */ | ||
94 | static LIST_HEAD(dev_opp_list); | ||
95 | /* Lock to allow exclusive modification to the device and opp lists */ | ||
96 | static DEFINE_MUTEX(dev_opp_list_lock); | ||
97 | |||
98 | /** | ||
99 | * find_device_opp() - find device_opp struct using device pointer | ||
100 | * @dev: device pointer used to lookup device OPPs | ||
101 | * | ||
102 | * Search list of device OPPs for one containing matching device. Does a RCU | ||
103 | * reader operation to grab the pointer needed. | ||
104 | * | ||
105 | * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or | ||
106 | * -EINVAL based on type of error. | ||
107 | * | ||
108 | * Locking: This function must be called under rcu_read_lock(). device_opp | ||
109 | * is a RCU protected pointer. This means that device_opp is valid as long | ||
110 | * as we are under RCU lock. | ||
111 | */ | ||
112 | static struct device_opp *find_device_opp(struct device *dev) | ||
113 | { | ||
114 | struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV); | ||
115 | |||
116 | if (unlikely(IS_ERR_OR_NULL(dev))) { | ||
117 | pr_err("%s: Invalid parameters\n", __func__); | ||
118 | return ERR_PTR(-EINVAL); | ||
119 | } | ||
120 | |||
121 | list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) { | ||
122 | if (tmp_dev_opp->dev == dev) { | ||
123 | dev_opp = tmp_dev_opp; | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return dev_opp; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * opp_get_voltage() - Gets the voltage corresponding to an available opp | ||
133 | * @opp: opp for which voltage has to be returned for | ||
134 | * | ||
135 | * Return voltage in micro volt corresponding to the opp, else | ||
136 | * return 0 | ||
137 | * | ||
138 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
139 | * protected pointer. This means that opp which could have been fetched by | ||
140 | * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are | ||
141 | * under RCU lock. The pointer returned by the opp_find_freq family must be | ||
142 | * used in the same section as the usage of this function with the pointer | ||
143 | * prior to unlocking with rcu_read_unlock() to maintain the integrity of the | ||
144 | * pointer. | ||
145 | */ | ||
146 | unsigned long opp_get_voltage(struct opp *opp) | ||
147 | { | ||
148 | struct opp *tmp_opp; | ||
149 | unsigned long v = 0; | ||
150 | |||
151 | tmp_opp = rcu_dereference(opp); | ||
152 | if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) | ||
153 | pr_err("%s: Invalid parameters\n", __func__); | ||
154 | else | ||
155 | v = tmp_opp->u_volt; | ||
156 | |||
157 | return v; | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * opp_get_freq() - Gets the frequency corresponding to an available opp | ||
162 | * @opp: opp for which frequency has to be returned for | ||
163 | * | ||
164 | * Return frequency in hertz corresponding to the opp, else | ||
165 | * return 0 | ||
166 | * | ||
167 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
168 | * protected pointer. This means that opp which could have been fetched by | ||
169 | * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are | ||
170 | * under RCU lock. The pointer returned by the opp_find_freq family must be | ||
171 | * used in the same section as the usage of this function with the pointer | ||
172 | * prior to unlocking with rcu_read_unlock() to maintain the integrity of the | ||
173 | * pointer. | ||
174 | */ | ||
175 | unsigned long opp_get_freq(struct opp *opp) | ||
176 | { | ||
177 | struct opp *tmp_opp; | ||
178 | unsigned long f = 0; | ||
179 | |||
180 | tmp_opp = rcu_dereference(opp); | ||
181 | if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) | ||
182 | pr_err("%s: Invalid parameters\n", __func__); | ||
183 | else | ||
184 | f = tmp_opp->rate; | ||
185 | |||
186 | return f; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * opp_get_opp_count() - Get number of opps available in the opp list | ||
191 | * @dev: device for which we do this operation | ||
192 | * | ||
193 | * This function returns the number of available opps if there are any, | ||
194 | * else returns 0 if none or the corresponding error value. | ||
195 | * | ||
196 | * Locking: This function must be called under rcu_read_lock(). This function | ||
197 | * internally references two RCU protected structures: device_opp and opp which | ||
198 | * are safe as long as we are under a common RCU locked section. | ||
199 | */ | ||
200 | int opp_get_opp_count(struct device *dev) | ||
201 | { | ||
202 | struct device_opp *dev_opp; | ||
203 | struct opp *temp_opp; | ||
204 | int count = 0; | ||
205 | |||
206 | dev_opp = find_device_opp(dev); | ||
207 | if (IS_ERR(dev_opp)) { | ||
208 | int r = PTR_ERR(dev_opp); | ||
209 | dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); | ||
210 | return r; | ||
211 | } | ||
212 | |||
213 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
214 | if (temp_opp->available) | ||
215 | count++; | ||
216 | } | ||
217 | |||
218 | return count; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * opp_find_freq_exact() - search for an exact frequency | ||
223 | * @dev: device for which we do this operation | ||
224 | * @freq: frequency to search for | ||
225 | * @is_available: true/false - match for available opp | ||
226 | * | ||
227 | * Searches for exact match in the opp list and returns pointer to the matching | ||
228 | * opp if found, else returns ERR_PTR in case of error and should be handled | ||
229 | * using IS_ERR. | ||
230 | * | ||
231 | * Note: available is a modifier for the search. if available=true, then the | ||
232 | * match is for exact matching frequency and is available in the stored OPP | ||
233 | * table. if false, the match is for exact frequency which is not available. | ||
234 | * | ||
235 | * This provides a mechanism to enable an opp which is not available currently | ||
236 | * or the opposite as well. | ||
237 | * | ||
238 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
239 | * protected pointer. The reason for the same is that the opp pointer which is | ||
240 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
241 | * under the locked area. The pointer returned must be used prior to unlocking | ||
242 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
243 | */ | ||
244 | struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq, | ||
245 | bool available) | ||
246 | { | ||
247 | struct device_opp *dev_opp; | ||
248 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
249 | |||
250 | dev_opp = find_device_opp(dev); | ||
251 | if (IS_ERR(dev_opp)) { | ||
252 | int r = PTR_ERR(dev_opp); | ||
253 | dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); | ||
254 | return ERR_PTR(r); | ||
255 | } | ||
256 | |||
257 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
258 | if (temp_opp->available == available && | ||
259 | temp_opp->rate == freq) { | ||
260 | opp = temp_opp; | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | return opp; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * opp_find_freq_ceil() - Search for an rounded ceil freq | ||
270 | * @dev: device for which we do this operation | ||
271 | * @freq: Start frequency | ||
272 | * | ||
273 | * Search for the matching ceil *available* OPP from a starting freq | ||
274 | * for a device. | ||
275 | * | ||
276 | * Returns matching *opp and refreshes *freq accordingly, else returns | ||
277 | * ERR_PTR in case of error and should be handled using IS_ERR. | ||
278 | * | ||
279 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
280 | * protected pointer. The reason for the same is that the opp pointer which is | ||
281 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
282 | * under the locked area. The pointer returned must be used prior to unlocking | ||
283 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
284 | */ | ||
285 | struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq) | ||
286 | { | ||
287 | struct device_opp *dev_opp; | ||
288 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
289 | |||
290 | if (!dev || !freq) { | ||
291 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | ||
292 | return ERR_PTR(-EINVAL); | ||
293 | } | ||
294 | |||
295 | dev_opp = find_device_opp(dev); | ||
296 | if (IS_ERR(dev_opp)) | ||
297 | return opp; | ||
298 | |||
299 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
300 | if (temp_opp->available && temp_opp->rate >= *freq) { | ||
301 | opp = temp_opp; | ||
302 | *freq = opp->rate; | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | return opp; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * opp_find_freq_floor() - Search for a rounded floor freq | ||
312 | * @dev: device for which we do this operation | ||
313 | * @freq: Start frequency | ||
314 | * | ||
315 | * Search for the matching floor *available* OPP from a starting freq | ||
316 | * for a device. | ||
317 | * | ||
318 | * Returns matching *opp and refreshes *freq accordingly, else returns | ||
319 | * ERR_PTR in case of error and should be handled using IS_ERR. | ||
320 | * | ||
321 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
322 | * protected pointer. The reason for the same is that the opp pointer which is | ||
323 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
324 | * under the locked area. The pointer returned must be used prior to unlocking | ||
325 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
326 | */ | ||
327 | struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq) | ||
328 | { | ||
329 | struct device_opp *dev_opp; | ||
330 | struct opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
331 | |||
332 | if (!dev || !freq) { | ||
333 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | ||
334 | return ERR_PTR(-EINVAL); | ||
335 | } | ||
336 | |||
337 | dev_opp = find_device_opp(dev); | ||
338 | if (IS_ERR(dev_opp)) | ||
339 | return opp; | ||
340 | |||
341 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | ||
342 | if (temp_opp->available) { | ||
343 | /* go to the next node, before choosing prev */ | ||
344 | if (temp_opp->rate > *freq) | ||
345 | break; | ||
346 | else | ||
347 | opp = temp_opp; | ||
348 | } | ||
349 | } | ||
350 | if (!IS_ERR(opp)) | ||
351 | *freq = opp->rate; | ||
352 | |||
353 | return opp; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * opp_add() - Add an OPP table from a table definitions | ||
358 | * @dev: device for which we do this operation | ||
359 | * @freq: Frequency in Hz for this OPP | ||
360 | * @u_volt: Voltage in uVolts for this OPP | ||
361 | * | ||
362 | * This function adds an opp definition to the opp list and returns status. | ||
363 | * The opp is made available by default and it can be controlled using | ||
364 | * opp_enable/disable functions. | ||
365 | * | ||
366 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
367 | * Hence this function internally uses RCU updater strategy with mutex locks | ||
368 | * to keep the integrity of the internal data structures. Callers should ensure | ||
369 | * that this function is *NOT* called under RCU protection or in contexts where | ||
370 | * mutex cannot be locked. | ||
371 | */ | ||
372 | int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) | ||
373 | { | ||
374 | struct device_opp *dev_opp = NULL; | ||
375 | struct opp *opp, *new_opp; | ||
376 | struct list_head *head; | ||
377 | |||
378 | /* allocate new OPP node */ | ||
379 | new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL); | ||
380 | if (!new_opp) { | ||
381 | dev_warn(dev, "%s: Unable to create new OPP node\n", __func__); | ||
382 | return -ENOMEM; | ||
383 | } | ||
384 | |||
385 | /* Hold our list modification lock here */ | ||
386 | mutex_lock(&dev_opp_list_lock); | ||
387 | |||
388 | /* Check for existing list for 'dev' */ | ||
389 | dev_opp = find_device_opp(dev); | ||
390 | if (IS_ERR(dev_opp)) { | ||
391 | /* | ||
392 | * Allocate a new device OPP table. In the infrequent case | ||
393 | * where a new device is needed to be added, we pay this | ||
394 | * penalty. | ||
395 | */ | ||
396 | dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL); | ||
397 | if (!dev_opp) { | ||
398 | mutex_unlock(&dev_opp_list_lock); | ||
399 | kfree(new_opp); | ||
400 | dev_warn(dev, | ||
401 | "%s: Unable to create device OPP structure\n", | ||
402 | __func__); | ||
403 | return -ENOMEM; | ||
404 | } | ||
405 | |||
406 | dev_opp->dev = dev; | ||
407 | INIT_LIST_HEAD(&dev_opp->opp_list); | ||
408 | |||
409 | /* Secure the device list modification */ | ||
410 | list_add_rcu(&dev_opp->node, &dev_opp_list); | ||
411 | } | ||
412 | |||
413 | /* populate the opp table */ | ||
414 | new_opp->dev_opp = dev_opp; | ||
415 | new_opp->rate = freq; | ||
416 | new_opp->u_volt = u_volt; | ||
417 | new_opp->available = true; | ||
418 | |||
419 | /* Insert new OPP in order of increasing frequency */ | ||
420 | head = &dev_opp->opp_list; | ||
421 | list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) { | ||
422 | if (new_opp->rate < opp->rate) | ||
423 | break; | ||
424 | else | ||
425 | head = &opp->node; | ||
426 | } | ||
427 | |||
428 | list_add_rcu(&new_opp->node, head); | ||
429 | mutex_unlock(&dev_opp_list_lock); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * opp_set_availability() - helper to set the availability of an opp | ||
436 | * @dev: device for which we do this operation | ||
437 | * @freq: OPP frequency to modify availability | ||
438 | * @availability_req: availability status requested for this opp | ||
439 | * | ||
440 | * Set the availability of an OPP with an RCU operation, opp_{enable,disable} | ||
441 | * share a common logic which is isolated here. | ||
442 | * | ||
443 | * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the | ||
444 | * copy operation, returns 0 if no modifcation was done OR modification was | ||
445 | * successful. | ||
446 | * | ||
447 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
448 | * Hence this function internally uses RCU updater strategy with mutex locks to | ||
449 | * keep the integrity of the internal data structures. Callers should ensure | ||
450 | * that this function is *NOT* called under RCU protection or in contexts where | ||
451 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
452 | */ | ||
453 | static int opp_set_availability(struct device *dev, unsigned long freq, | ||
454 | bool availability_req) | ||
455 | { | ||
456 | struct device_opp *tmp_dev_opp, *dev_opp = NULL; | ||
457 | struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); | ||
458 | int r = 0; | ||
459 | |||
460 | /* keep the node allocated */ | ||
461 | new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL); | ||
462 | if (!new_opp) { | ||
463 | dev_warn(dev, "%s: Unable to create OPP\n", __func__); | ||
464 | return -ENOMEM; | ||
465 | } | ||
466 | |||
467 | mutex_lock(&dev_opp_list_lock); | ||
468 | |||
469 | /* Find the device_opp */ | ||
470 | list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) { | ||
471 | if (dev == tmp_dev_opp->dev) { | ||
472 | dev_opp = tmp_dev_opp; | ||
473 | break; | ||
474 | } | ||
475 | } | ||
476 | if (IS_ERR(dev_opp)) { | ||
477 | r = PTR_ERR(dev_opp); | ||
478 | dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); | ||
479 | goto unlock; | ||
480 | } | ||
481 | |||
482 | /* Do we have the frequency? */ | ||
483 | list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) { | ||
484 | if (tmp_opp->rate == freq) { | ||
485 | opp = tmp_opp; | ||
486 | break; | ||
487 | } | ||
488 | } | ||
489 | if (IS_ERR(opp)) { | ||
490 | r = PTR_ERR(opp); | ||
491 | goto unlock; | ||
492 | } | ||
493 | |||
494 | /* Is update really needed? */ | ||
495 | if (opp->available == availability_req) | ||
496 | goto unlock; | ||
497 | /* copy the old data over */ | ||
498 | *new_opp = *opp; | ||
499 | |||
500 | /* plug in new node */ | ||
501 | new_opp->available = availability_req; | ||
502 | |||
503 | list_replace_rcu(&opp->node, &new_opp->node); | ||
504 | mutex_unlock(&dev_opp_list_lock); | ||
505 | synchronize_rcu(); | ||
506 | |||
507 | /* clean up old opp */ | ||
508 | new_opp = opp; | ||
509 | goto out; | ||
510 | |||
511 | unlock: | ||
512 | mutex_unlock(&dev_opp_list_lock); | ||
513 | out: | ||
514 | kfree(new_opp); | ||
515 | return r; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * opp_enable() - Enable a specific OPP | ||
520 | * @dev: device for which we do this operation | ||
521 | * @freq: OPP frequency to enable | ||
522 | * | ||
523 | * Enables a provided opp. If the operation is valid, this returns 0, else the | ||
524 | * corresponding error value. It is meant to be used for users an OPP available | ||
525 | * after being temporarily made unavailable with opp_disable. | ||
526 | * | ||
527 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
528 | * Hence this function indirectly uses RCU and mutex locks to keep the | ||
529 | * integrity of the internal data structures. Callers should ensure that | ||
530 | * this function is *NOT* called under RCU protection or in contexts where | ||
531 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
532 | */ | ||
533 | int opp_enable(struct device *dev, unsigned long freq) | ||
534 | { | ||
535 | return opp_set_availability(dev, freq, true); | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * opp_disable() - Disable a specific OPP | ||
540 | * @dev: device for which we do this operation | ||
541 | * @freq: OPP frequency to disable | ||
542 | * | ||
543 | * Disables a provided opp. If the operation is valid, this returns | ||
544 | * 0, else the corresponding error value. It is meant to be a temporary | ||
545 | * control by users to make this OPP not available until the circumstances are | ||
546 | * right to make it available again (with a call to opp_enable). | ||
547 | * | ||
548 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
549 | * Hence this function indirectly uses RCU and mutex locks to keep the | ||
550 | * integrity of the internal data structures. Callers should ensure that | ||
551 | * this function is *NOT* called under RCU protection or in contexts where | ||
552 | * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||
553 | */ | ||
554 | int opp_disable(struct device *dev, unsigned long freq) | ||
555 | { | ||
556 | return opp_set_availability(dev, freq, false); | ||
557 | } | ||
558 | |||
559 | #ifdef CONFIG_CPU_FREQ | ||
560 | /** | ||
561 | * opp_init_cpufreq_table() - create a cpufreq table for a device | ||
562 | * @dev: device for which we do this operation | ||
563 | * @table: Cpufreq table returned back to caller | ||
564 | * | ||
565 | * Generate a cpufreq table for a provided device- this assumes that the | ||
566 | * opp list is already initialized and ready for usage. | ||
567 | * | ||
568 | * This function allocates required memory for the cpufreq table. It is | ||
569 | * expected that the caller does the required maintenance such as freeing | ||
570 | * the table as required. | ||
571 | * | ||
572 | * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM | ||
573 | * if no memory available for the operation (table is not populated), returns 0 | ||
574 | * if successful and table is populated. | ||
575 | * | ||
576 | * WARNING: It is important for the callers to ensure refreshing their copy of | ||
577 | * the table if any of the mentioned functions have been invoked in the interim. | ||
578 | * | ||
579 | * Locking: The internal device_opp and opp structures are RCU protected. | ||
580 | * To simplify the logic, we pretend we are updater and hold relevant mutex here | ||
581 | * Callers should ensure that this function is *NOT* called under RCU protection | ||
582 | * or in contexts where mutex locking cannot be used. | ||
583 | */ | ||
584 | int opp_init_cpufreq_table(struct device *dev, | ||
585 | struct cpufreq_frequency_table **table) | ||
586 | { | ||
587 | struct device_opp *dev_opp; | ||
588 | struct opp *opp; | ||
589 | struct cpufreq_frequency_table *freq_table; | ||
590 | int i = 0; | ||
591 | |||
592 | /* Pretend as if I am an updater */ | ||
593 | mutex_lock(&dev_opp_list_lock); | ||
594 | |||
595 | dev_opp = find_device_opp(dev); | ||
596 | if (IS_ERR(dev_opp)) { | ||
597 | int r = PTR_ERR(dev_opp); | ||
598 | mutex_unlock(&dev_opp_list_lock); | ||
599 | dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r); | ||
600 | return r; | ||
601 | } | ||
602 | |||
603 | freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * | ||
604 | (opp_get_opp_count(dev) + 1), GFP_KERNEL); | ||
605 | if (!freq_table) { | ||
606 | mutex_unlock(&dev_opp_list_lock); | ||
607 | dev_warn(dev, "%s: Unable to allocate frequency table\n", | ||
608 | __func__); | ||
609 | return -ENOMEM; | ||
610 | } | ||
611 | |||
612 | list_for_each_entry(opp, &dev_opp->opp_list, node) { | ||
613 | if (opp->available) { | ||
614 | freq_table[i].index = i; | ||
615 | freq_table[i].frequency = opp->rate / 1000; | ||
616 | i++; | ||
617 | } | ||
618 | } | ||
619 | mutex_unlock(&dev_opp_list_lock); | ||
620 | |||
621 | freq_table[i].index = i; | ||
622 | freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
623 | |||
624 | *table = &freq_table[0]; | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | #endif /* CONFIG_CPU_FREQ */ | ||
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index c0bd03c83b9c..698dde742587 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -34,6 +34,7 @@ extern void device_pm_move_last(struct device *); | |||
34 | 34 | ||
35 | static inline void device_pm_init(struct device *dev) | 35 | static inline void device_pm_init(struct device *dev) |
36 | { | 36 | { |
37 | spin_lock_init(&dev->power.lock); | ||
37 | pm_runtime_init(dev); | 38 | pm_runtime_init(dev); |
38 | } | 39 | } |
39 | 40 | ||
@@ -59,6 +60,7 @@ static inline void device_pm_move_last(struct device *dev) {} | |||
59 | 60 | ||
60 | extern int dpm_sysfs_add(struct device *); | 61 | extern int dpm_sysfs_add(struct device *); |
61 | extern void dpm_sysfs_remove(struct device *); | 62 | extern void dpm_sysfs_remove(struct device *); |
63 | extern void rpm_sysfs_remove(struct device *); | ||
62 | 64 | ||
63 | #else /* CONFIG_PM */ | 65 | #else /* CONFIG_PM */ |
64 | 66 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index b78c401ffa73..1dd8676d7f55 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -2,17 +2,55 @@ | |||
2 | * drivers/base/power/runtime.c - Helper functions for device run-time PM | 2 | * drivers/base/power/runtime.c - Helper functions for device run-time PM |
3 | * | 3 | * |
4 | * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | 4 | * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. |
5 | * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu> | ||
5 | * | 6 | * |
6 | * This file is released under the GPLv2. | 7 | * This file is released under the GPLv2. |
7 | */ | 8 | */ |
8 | 9 | ||
9 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
10 | #include <linux/pm_runtime.h> | 11 | #include <linux/pm_runtime.h> |
11 | #include <linux/jiffies.h> | 12 | #include "power.h" |
12 | 13 | ||
13 | static int __pm_runtime_resume(struct device *dev, bool from_wq); | 14 | static int rpm_resume(struct device *dev, int rpmflags); |
14 | static int __pm_request_idle(struct device *dev); | 15 | static int rpm_suspend(struct device *dev, int rpmflags); |
15 | static int __pm_request_resume(struct device *dev); | 16 | |
17 | /** | ||
18 | * update_pm_runtime_accounting - Update the time accounting of power states | ||
19 | * @dev: Device to update the accounting for | ||
20 | * | ||
21 | * In order to be able to have time accounting of the various power states | ||
22 | * (as used by programs such as PowerTOP to show the effectiveness of runtime | ||
23 | * PM), we need to track the time spent in each state. | ||
24 | * update_pm_runtime_accounting must be called each time before the | ||
25 | * runtime_status field is updated, to account the time in the old state | ||
26 | * correctly. | ||
27 | */ | ||
28 | void update_pm_runtime_accounting(struct device *dev) | ||
29 | { | ||
30 | unsigned long now = jiffies; | ||
31 | int delta; | ||
32 | |||
33 | delta = now - dev->power.accounting_timestamp; | ||
34 | |||
35 | if (delta < 0) | ||
36 | delta = 0; | ||
37 | |||
38 | dev->power.accounting_timestamp = now; | ||
39 | |||
40 | if (dev->power.disable_depth > 0) | ||
41 | return; | ||
42 | |||
43 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
44 | dev->power.suspended_jiffies += delta; | ||
45 | else | ||
46 | dev->power.active_jiffies += delta; | ||
47 | } | ||
48 | |||
49 | static void __update_runtime_status(struct device *dev, enum rpm_status status) | ||
50 | { | ||
51 | update_pm_runtime_accounting(dev); | ||
52 | dev->power.runtime_status = status; | ||
53 | } | ||
16 | 54 | ||
17 | /** | 55 | /** |
18 | * pm_runtime_deactivate_timer - Deactivate given device's suspend timer. | 56 | * pm_runtime_deactivate_timer - Deactivate given device's suspend timer. |
@@ -40,62 +78,154 @@ static void pm_runtime_cancel_pending(struct device *dev) | |||
40 | dev->power.request = RPM_REQ_NONE; | 78 | dev->power.request = RPM_REQ_NONE; |
41 | } | 79 | } |
42 | 80 | ||
43 | /** | 81 | /* |
44 | * __pm_runtime_idle - Notify device bus type if the device can be suspended. | 82 | * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time. |
45 | * @dev: Device to notify the bus type about. | 83 | * @dev: Device to handle. |
46 | * | 84 | * |
47 | * This function must be called under dev->power.lock with interrupts disabled. | 85 | * Compute the autosuspend-delay expiration time based on the device's |
86 | * power.last_busy time. If the delay has already expired or is disabled | ||
87 | * (negative) or the power.use_autosuspend flag isn't set, return 0. | ||
88 | * Otherwise return the expiration time in jiffies (adjusted to be nonzero). | ||
89 | * | ||
90 | * This function may be called either with or without dev->power.lock held. | ||
91 | * Either way it can be racy, since power.last_busy may be updated at any time. | ||
48 | */ | 92 | */ |
49 | static int __pm_runtime_idle(struct device *dev) | 93 | unsigned long pm_runtime_autosuspend_expiration(struct device *dev) |
50 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | 94 | { |
95 | int autosuspend_delay; | ||
96 | long elapsed; | ||
97 | unsigned long last_busy; | ||
98 | unsigned long expires = 0; | ||
99 | |||
100 | if (!dev->power.use_autosuspend) | ||
101 | goto out; | ||
102 | |||
103 | autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay); | ||
104 | if (autosuspend_delay < 0) | ||
105 | goto out; | ||
106 | |||
107 | last_busy = ACCESS_ONCE(dev->power.last_busy); | ||
108 | elapsed = jiffies - last_busy; | ||
109 | if (elapsed < 0) | ||
110 | goto out; /* jiffies has wrapped around. */ | ||
111 | |||
112 | /* | ||
113 | * If the autosuspend_delay is >= 1 second, align the timer by rounding | ||
114 | * up to the nearest second. | ||
115 | */ | ||
116 | expires = last_busy + msecs_to_jiffies(autosuspend_delay); | ||
117 | if (autosuspend_delay >= 1000) | ||
118 | expires = round_jiffies(expires); | ||
119 | expires += !expires; | ||
120 | if (elapsed >= expires - last_busy) | ||
121 | expires = 0; /* Already expired. */ | ||
122 | |||
123 | out: | ||
124 | return expires; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration); | ||
127 | |||
128 | /** | ||
129 | * rpm_check_suspend_allowed - Test whether a device may be suspended. | ||
130 | * @dev: Device to test. | ||
131 | */ | ||
132 | static int rpm_check_suspend_allowed(struct device *dev) | ||
51 | { | 133 | { |
52 | int retval = 0; | 134 | int retval = 0; |
53 | 135 | ||
54 | if (dev->power.runtime_error) | 136 | if (dev->power.runtime_error) |
55 | retval = -EINVAL; | 137 | retval = -EINVAL; |
56 | else if (dev->power.idle_notification) | ||
57 | retval = -EINPROGRESS; | ||
58 | else if (atomic_read(&dev->power.usage_count) > 0 | 138 | else if (atomic_read(&dev->power.usage_count) > 0 |
59 | || dev->power.disable_depth > 0 | 139 | || dev->power.disable_depth > 0) |
60 | || dev->power.runtime_status != RPM_ACTIVE) | ||
61 | retval = -EAGAIN; | 140 | retval = -EAGAIN; |
62 | else if (!pm_children_suspended(dev)) | 141 | else if (!pm_children_suspended(dev)) |
63 | retval = -EBUSY; | 142 | retval = -EBUSY; |
143 | |||
144 | /* Pending resume requests take precedence over suspends. */ | ||
145 | else if ((dev->power.deferred_resume | ||
146 | && dev->power.status == RPM_SUSPENDING) | ||
147 | || (dev->power.request_pending | ||
148 | && dev->power.request == RPM_REQ_RESUME)) | ||
149 | retval = -EAGAIN; | ||
150 | else if (dev->power.runtime_status == RPM_SUSPENDED) | ||
151 | retval = 1; | ||
152 | |||
153 | return retval; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * rpm_idle - Notify device bus type if the device can be suspended. | ||
158 | * @dev: Device to notify the bus type about. | ||
159 | * @rpmflags: Flag bits. | ||
160 | * | ||
161 | * Check if the device's run-time PM status allows it to be suspended. If | ||
162 | * another idle notification has been started earlier, return immediately. If | ||
163 | * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise | ||
164 | * run the ->runtime_idle() callback directly. | ||
165 | * | ||
166 | * This function must be called under dev->power.lock with interrupts disabled. | ||
167 | */ | ||
168 | static int rpm_idle(struct device *dev, int rpmflags) | ||
169 | { | ||
170 | int (*callback)(struct device *); | ||
171 | int retval; | ||
172 | |||
173 | retval = rpm_check_suspend_allowed(dev); | ||
174 | if (retval < 0) | ||
175 | ; /* Conditions are wrong. */ | ||
176 | |||
177 | /* Idle notifications are allowed only in the RPM_ACTIVE state. */ | ||
178 | else if (dev->power.runtime_status != RPM_ACTIVE) | ||
179 | retval = -EAGAIN; | ||
180 | |||
181 | /* | ||
182 | * Any pending request other than an idle notification takes | ||
183 | * precedence over us, except that the timer may be running. | ||
184 | */ | ||
185 | else if (dev->power.request_pending && | ||
186 | dev->power.request > RPM_REQ_IDLE) | ||
187 | retval = -EAGAIN; | ||
188 | |||
189 | /* Act as though RPM_NOWAIT is always set. */ | ||
190 | else if (dev->power.idle_notification) | ||
191 | retval = -EINPROGRESS; | ||
64 | if (retval) | 192 | if (retval) |
65 | goto out; | 193 | goto out; |
66 | 194 | ||
67 | if (dev->power.request_pending) { | 195 | /* Pending requests need to be canceled. */ |
68 | /* | 196 | dev->power.request = RPM_REQ_NONE; |
69 | * If an idle notification request is pending, cancel it. Any | 197 | |
70 | * other pending request takes precedence over us. | 198 | if (dev->power.no_callbacks) { |
71 | */ | 199 | /* Assume ->runtime_idle() callback would have suspended. */ |
72 | if (dev->power.request == RPM_REQ_IDLE) { | 200 | retval = rpm_suspend(dev, rpmflags); |
73 | dev->power.request = RPM_REQ_NONE; | 201 | goto out; |
74 | } else if (dev->power.request != RPM_REQ_NONE) { | 202 | } |
75 | retval = -EAGAIN; | 203 | |
76 | goto out; | 204 | /* Carry out an asynchronous or a synchronous idle notification. */ |
205 | if (rpmflags & RPM_ASYNC) { | ||
206 | dev->power.request = RPM_REQ_IDLE; | ||
207 | if (!dev->power.request_pending) { | ||
208 | dev->power.request_pending = true; | ||
209 | queue_work(pm_wq, &dev->power.work); | ||
77 | } | 210 | } |
211 | goto out; | ||
78 | } | 212 | } |
79 | 213 | ||
80 | dev->power.idle_notification = true; | 214 | dev->power.idle_notification = true; |
81 | 215 | ||
82 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) { | 216 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) |
83 | spin_unlock_irq(&dev->power.lock); | 217 | callback = dev->bus->pm->runtime_idle; |
84 | 218 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) | |
85 | dev->bus->pm->runtime_idle(dev); | 219 | callback = dev->type->pm->runtime_idle; |
86 | 220 | else if (dev->class && dev->class->pm) | |
87 | spin_lock_irq(&dev->power.lock); | 221 | callback = dev->class->pm->runtime_idle; |
88 | } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { | 222 | else |
89 | spin_unlock_irq(&dev->power.lock); | 223 | callback = NULL; |
90 | |||
91 | dev->type->pm->runtime_idle(dev); | ||
92 | 224 | ||
93 | spin_lock_irq(&dev->power.lock); | 225 | if (callback) { |
94 | } else if (dev->class && dev->class->pm | ||
95 | && dev->class->pm->runtime_idle) { | ||
96 | spin_unlock_irq(&dev->power.lock); | 226 | spin_unlock_irq(&dev->power.lock); |
97 | 227 | ||
98 | dev->class->pm->runtime_idle(dev); | 228 | callback(dev); |
99 | 229 | ||
100 | spin_lock_irq(&dev->power.lock); | 230 | spin_lock_irq(&dev->power.lock); |
101 | } | 231 | } |
@@ -108,113 +238,99 @@ static int __pm_runtime_idle(struct device *dev) | |||
108 | } | 238 | } |
109 | 239 | ||
110 | /** | 240 | /** |
111 | * pm_runtime_idle - Notify device bus type if the device can be suspended. | 241 | * rpm_callback - Run a given runtime PM callback for a given device. |
112 | * @dev: Device to notify the bus type about. | 242 | * @cb: Runtime PM callback to run. |
243 | * @dev: Device to run the callback for. | ||
113 | */ | 244 | */ |
114 | int pm_runtime_idle(struct device *dev) | 245 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) |
246 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
115 | { | 247 | { |
116 | int retval; | 248 | int retval; |
117 | 249 | ||
118 | spin_lock_irq(&dev->power.lock); | 250 | if (!cb) |
119 | retval = __pm_runtime_idle(dev); | 251 | return -ENOSYS; |
120 | spin_unlock_irq(&dev->power.lock); | ||
121 | 252 | ||
122 | return retval; | 253 | spin_unlock_irq(&dev->power.lock); |
123 | } | ||
124 | EXPORT_SYMBOL_GPL(pm_runtime_idle); | ||
125 | |||
126 | |||
127 | /** | ||
128 | * update_pm_runtime_accounting - Update the time accounting of power states | ||
129 | * @dev: Device to update the accounting for | ||
130 | * | ||
131 | * In order to be able to have time accounting of the various power states | ||
132 | * (as used by programs such as PowerTOP to show the effectiveness of runtime | ||
133 | * PM), we need to track the time spent in each state. | ||
134 | * update_pm_runtime_accounting must be called each time before the | ||
135 | * runtime_status field is updated, to account the time in the old state | ||
136 | * correctly. | ||
137 | */ | ||
138 | void update_pm_runtime_accounting(struct device *dev) | ||
139 | { | ||
140 | unsigned long now = jiffies; | ||
141 | int delta; | ||
142 | |||
143 | delta = now - dev->power.accounting_timestamp; | ||
144 | |||
145 | if (delta < 0) | ||
146 | delta = 0; | ||
147 | 254 | ||
148 | dev->power.accounting_timestamp = now; | 255 | retval = cb(dev); |
149 | 256 | ||
150 | if (dev->power.disable_depth > 0) | 257 | spin_lock_irq(&dev->power.lock); |
151 | return; | 258 | dev->power.runtime_error = retval; |
152 | |||
153 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
154 | dev->power.suspended_jiffies += delta; | ||
155 | else | ||
156 | dev->power.active_jiffies += delta; | ||
157 | } | ||
158 | 259 | ||
159 | static void __update_runtime_status(struct device *dev, enum rpm_status status) | 260 | return retval; |
160 | { | ||
161 | update_pm_runtime_accounting(dev); | ||
162 | dev->power.runtime_status = status; | ||
163 | } | 261 | } |
164 | 262 | ||
165 | /** | 263 | /** |
166 | * __pm_runtime_suspend - Carry out run-time suspend of given device. | 264 | * rpm_suspend - Carry out run-time suspend of given device. |
167 | * @dev: Device to suspend. | 265 | * @dev: Device to suspend. |
168 | * @from_wq: If set, the function has been called via pm_wq. | 266 | * @rpmflags: Flag bits. |
169 | * | 267 | * |
170 | * Check if the device can be suspended and run the ->runtime_suspend() callback | 268 | * Check if the device's run-time PM status allows it to be suspended. If |
171 | * provided by its bus type. If another suspend has been started earlier, wait | 269 | * another suspend has been started earlier, either return immediately or wait |
172 | * for it to finish. If an idle notification or suspend request is pending or | 270 | * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags. Cancel a |
173 | * scheduled, cancel it. | 271 | * pending idle notification. If the RPM_ASYNC flag is set then queue a |
272 | * suspend request; otherwise run the ->runtime_suspend() callback directly. | ||
273 | * If a deferred resume was requested while the callback was running then carry | ||
274 | * it out; otherwise send an idle notification for the device (if the suspend | ||
275 | * failed) or for its parent (if the suspend succeeded). | ||
174 | * | 276 | * |
175 | * This function must be called under dev->power.lock with interrupts disabled. | 277 | * This function must be called under dev->power.lock with interrupts disabled. |
176 | */ | 278 | */ |
177 | int __pm_runtime_suspend(struct device *dev, bool from_wq) | 279 | static int rpm_suspend(struct device *dev, int rpmflags) |
178 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | 280 | __releases(&dev->power.lock) __acquires(&dev->power.lock) |
179 | { | 281 | { |
282 | int (*callback)(struct device *); | ||
180 | struct device *parent = NULL; | 283 | struct device *parent = NULL; |
181 | bool notify = false; | 284 | int retval; |
182 | int retval = 0; | ||
183 | 285 | ||
184 | dev_dbg(dev, "__pm_runtime_suspend()%s!\n", | 286 | dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); |
185 | from_wq ? " from workqueue" : ""); | ||
186 | 287 | ||
187 | repeat: | 288 | repeat: |
188 | if (dev->power.runtime_error) { | 289 | retval = rpm_check_suspend_allowed(dev); |
189 | retval = -EINVAL; | ||
190 | goto out; | ||
191 | } | ||
192 | 290 | ||
193 | /* Pending resume requests take precedence over us. */ | 291 | if (retval < 0) |
194 | if (dev->power.request_pending | 292 | ; /* Conditions are wrong. */ |
195 | && dev->power.request == RPM_REQ_RESUME) { | 293 | |
294 | /* Synchronous suspends are not allowed in the RPM_RESUMING state. */ | ||
295 | else if (dev->power.runtime_status == RPM_RESUMING && | ||
296 | !(rpmflags & RPM_ASYNC)) | ||
196 | retval = -EAGAIN; | 297 | retval = -EAGAIN; |
298 | if (retval) | ||
197 | goto out; | 299 | goto out; |
300 | |||
301 | /* If the autosuspend_delay time hasn't expired yet, reschedule. */ | ||
302 | if ((rpmflags & RPM_AUTO) | ||
303 | && dev->power.runtime_status != RPM_SUSPENDING) { | ||
304 | unsigned long expires = pm_runtime_autosuspend_expiration(dev); | ||
305 | |||
306 | if (expires != 0) { | ||
307 | /* Pending requests need to be canceled. */ | ||
308 | dev->power.request = RPM_REQ_NONE; | ||
309 | |||
310 | /* | ||
311 | * Optimization: If the timer is already running and is | ||
312 | * set to expire at or before the autosuspend delay, | ||
313 | * avoid the overhead of resetting it. Just let it | ||
314 | * expire; pm_suspend_timer_fn() will take care of the | ||
315 | * rest. | ||
316 | */ | ||
317 | if (!(dev->power.timer_expires && time_before_eq( | ||
318 | dev->power.timer_expires, expires))) { | ||
319 | dev->power.timer_expires = expires; | ||
320 | mod_timer(&dev->power.suspend_timer, expires); | ||
321 | } | ||
322 | dev->power.timer_autosuspends = 1; | ||
323 | goto out; | ||
324 | } | ||
198 | } | 325 | } |
199 | 326 | ||
200 | /* Other scheduled or pending requests need to be canceled. */ | 327 | /* Other scheduled or pending requests need to be canceled. */ |
201 | pm_runtime_cancel_pending(dev); | 328 | pm_runtime_cancel_pending(dev); |
202 | 329 | ||
203 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
204 | retval = 1; | ||
205 | else if (dev->power.runtime_status == RPM_RESUMING | ||
206 | || dev->power.disable_depth > 0 | ||
207 | || atomic_read(&dev->power.usage_count) > 0) | ||
208 | retval = -EAGAIN; | ||
209 | else if (!pm_children_suspended(dev)) | ||
210 | retval = -EBUSY; | ||
211 | if (retval) | ||
212 | goto out; | ||
213 | |||
214 | if (dev->power.runtime_status == RPM_SUSPENDING) { | 330 | if (dev->power.runtime_status == RPM_SUSPENDING) { |
215 | DEFINE_WAIT(wait); | 331 | DEFINE_WAIT(wait); |
216 | 332 | ||
217 | if (from_wq) { | 333 | if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) { |
218 | retval = -EINPROGRESS; | 334 | retval = -EINPROGRESS; |
219 | goto out; | 335 | goto out; |
220 | } | 336 | } |
@@ -236,46 +352,42 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
236 | goto repeat; | 352 | goto repeat; |
237 | } | 353 | } |
238 | 354 | ||
239 | __update_runtime_status(dev, RPM_SUSPENDING); | ||
240 | dev->power.deferred_resume = false; | 355 | dev->power.deferred_resume = false; |
356 | if (dev->power.no_callbacks) | ||
357 | goto no_callback; /* Assume success. */ | ||
358 | |||
359 | /* Carry out an asynchronous or a synchronous suspend. */ | ||
360 | if (rpmflags & RPM_ASYNC) { | ||
361 | dev->power.request = (rpmflags & RPM_AUTO) ? | ||
362 | RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND; | ||
363 | if (!dev->power.request_pending) { | ||
364 | dev->power.request_pending = true; | ||
365 | queue_work(pm_wq, &dev->power.work); | ||
366 | } | ||
367 | goto out; | ||
368 | } | ||
241 | 369 | ||
242 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { | 370 | __update_runtime_status(dev, RPM_SUSPENDING); |
243 | spin_unlock_irq(&dev->power.lock); | ||
244 | |||
245 | retval = dev->bus->pm->runtime_suspend(dev); | ||
246 | |||
247 | spin_lock_irq(&dev->power.lock); | ||
248 | dev->power.runtime_error = retval; | ||
249 | } else if (dev->type && dev->type->pm | ||
250 | && dev->type->pm->runtime_suspend) { | ||
251 | spin_unlock_irq(&dev->power.lock); | ||
252 | |||
253 | retval = dev->type->pm->runtime_suspend(dev); | ||
254 | |||
255 | spin_lock_irq(&dev->power.lock); | ||
256 | dev->power.runtime_error = retval; | ||
257 | } else if (dev->class && dev->class->pm | ||
258 | && dev->class->pm->runtime_suspend) { | ||
259 | spin_unlock_irq(&dev->power.lock); | ||
260 | |||
261 | retval = dev->class->pm->runtime_suspend(dev); | ||
262 | 371 | ||
263 | spin_lock_irq(&dev->power.lock); | 372 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) |
264 | dev->power.runtime_error = retval; | 373 | callback = dev->bus->pm->runtime_suspend; |
265 | } else { | 374 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend) |
266 | retval = -ENOSYS; | 375 | callback = dev->type->pm->runtime_suspend; |
267 | } | 376 | else if (dev->class && dev->class->pm) |
377 | callback = dev->class->pm->runtime_suspend; | ||
378 | else | ||
379 | callback = NULL; | ||
268 | 380 | ||
381 | retval = rpm_callback(callback, dev); | ||
269 | if (retval) { | 382 | if (retval) { |
270 | __update_runtime_status(dev, RPM_ACTIVE); | 383 | __update_runtime_status(dev, RPM_ACTIVE); |
271 | if (retval == -EAGAIN || retval == -EBUSY) { | 384 | dev->power.deferred_resume = 0; |
272 | if (dev->power.timer_expires == 0) | 385 | if (retval == -EAGAIN || retval == -EBUSY) |
273 | notify = true; | ||
274 | dev->power.runtime_error = 0; | 386 | dev->power.runtime_error = 0; |
275 | } else { | 387 | else |
276 | pm_runtime_cancel_pending(dev); | 388 | pm_runtime_cancel_pending(dev); |
277 | } | ||
278 | } else { | 389 | } else { |
390 | no_callback: | ||
279 | __update_runtime_status(dev, RPM_SUSPENDED); | 391 | __update_runtime_status(dev, RPM_SUSPENDED); |
280 | pm_runtime_deactivate_timer(dev); | 392 | pm_runtime_deactivate_timer(dev); |
281 | 393 | ||
@@ -287,14 +399,11 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
287 | wake_up_all(&dev->power.wait_queue); | 399 | wake_up_all(&dev->power.wait_queue); |
288 | 400 | ||
289 | if (dev->power.deferred_resume) { | 401 | if (dev->power.deferred_resume) { |
290 | __pm_runtime_resume(dev, false); | 402 | rpm_resume(dev, 0); |
291 | retval = -EAGAIN; | 403 | retval = -EAGAIN; |
292 | goto out; | 404 | goto out; |
293 | } | 405 | } |
294 | 406 | ||
295 | if (notify) | ||
296 | __pm_runtime_idle(dev); | ||
297 | |||
298 | if (parent && !parent->power.ignore_children) { | 407 | if (parent && !parent->power.ignore_children) { |
299 | spin_unlock_irq(&dev->power.lock); | 408 | spin_unlock_irq(&dev->power.lock); |
300 | 409 | ||
@@ -304,72 +413,69 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
304 | } | 413 | } |
305 | 414 | ||
306 | out: | 415 | out: |
307 | dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval); | 416 | dev_dbg(dev, "%s returns %d\n", __func__, retval); |
308 | |||
309 | return retval; | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * pm_runtime_suspend - Carry out run-time suspend of given device. | ||
314 | * @dev: Device to suspend. | ||
315 | */ | ||
316 | int pm_runtime_suspend(struct device *dev) | ||
317 | { | ||
318 | int retval; | ||
319 | |||
320 | spin_lock_irq(&dev->power.lock); | ||
321 | retval = __pm_runtime_suspend(dev, false); | ||
322 | spin_unlock_irq(&dev->power.lock); | ||
323 | 417 | ||
324 | return retval; | 418 | return retval; |
325 | } | 419 | } |
326 | EXPORT_SYMBOL_GPL(pm_runtime_suspend); | ||
327 | 420 | ||
328 | /** | 421 | /** |
329 | * __pm_runtime_resume - Carry out run-time resume of given device. | 422 | * rpm_resume - Carry out run-time resume of given device. |
330 | * @dev: Device to resume. | 423 | * @dev: Device to resume. |
331 | * @from_wq: If set, the function has been called via pm_wq. | 424 | * @rpmflags: Flag bits. |
332 | * | 425 | * |
333 | * Check if the device can be woken up and run the ->runtime_resume() callback | 426 | * Check if the device's run-time PM status allows it to be resumed. Cancel |
334 | * provided by its bus type. If another resume has been started earlier, wait | 427 | * any scheduled or pending requests. If another resume has been started |
335 | * for it to finish. If there's a suspend running in parallel with this | 428 | * earlier, either return imediately or wait for it to finish, depending on the |
336 | * function, wait for it to finish and resume the device. Cancel any scheduled | 429 | * RPM_NOWAIT and RPM_ASYNC flags. Similarly, if there's a suspend running in |
337 | * or pending requests. | 430 | * parallel with this function, either tell the other process to resume after |
431 | * suspending (deferred_resume) or wait for it to finish. If the RPM_ASYNC | ||
432 | * flag is set then queue a resume request; otherwise run the | ||
433 | * ->runtime_resume() callback directly. Queue an idle notification for the | ||
434 | * device if the resume succeeded. | ||
338 | * | 435 | * |
339 | * This function must be called under dev->power.lock with interrupts disabled. | 436 | * This function must be called under dev->power.lock with interrupts disabled. |
340 | */ | 437 | */ |
341 | int __pm_runtime_resume(struct device *dev, bool from_wq) | 438 | static int rpm_resume(struct device *dev, int rpmflags) |
342 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | 439 | __releases(&dev->power.lock) __acquires(&dev->power.lock) |
343 | { | 440 | { |
441 | int (*callback)(struct device *); | ||
344 | struct device *parent = NULL; | 442 | struct device *parent = NULL; |
345 | int retval = 0; | 443 | int retval = 0; |
346 | 444 | ||
347 | dev_dbg(dev, "__pm_runtime_resume()%s!\n", | 445 | dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); |
348 | from_wq ? " from workqueue" : ""); | ||
349 | 446 | ||
350 | repeat: | 447 | repeat: |
351 | if (dev->power.runtime_error) { | 448 | if (dev->power.runtime_error) |
352 | retval = -EINVAL; | 449 | retval = -EINVAL; |
450 | else if (dev->power.disable_depth > 0) | ||
451 | retval = -EAGAIN; | ||
452 | if (retval) | ||
353 | goto out; | 453 | goto out; |
354 | } | ||
355 | 454 | ||
356 | pm_runtime_cancel_pending(dev); | 455 | /* |
456 | * Other scheduled or pending requests need to be canceled. Small | ||
457 | * optimization: If an autosuspend timer is running, leave it running | ||
458 | * rather than cancelling it now only to restart it again in the near | ||
459 | * future. | ||
460 | */ | ||
461 | dev->power.request = RPM_REQ_NONE; | ||
462 | if (!dev->power.timer_autosuspends) | ||
463 | pm_runtime_deactivate_timer(dev); | ||
357 | 464 | ||
358 | if (dev->power.runtime_status == RPM_ACTIVE) | 465 | if (dev->power.runtime_status == RPM_ACTIVE) { |
359 | retval = 1; | 466 | retval = 1; |
360 | else if (dev->power.disable_depth > 0) | ||
361 | retval = -EAGAIN; | ||
362 | if (retval) | ||
363 | goto out; | 467 | goto out; |
468 | } | ||
364 | 469 | ||
365 | if (dev->power.runtime_status == RPM_RESUMING | 470 | if (dev->power.runtime_status == RPM_RESUMING |
366 | || dev->power.runtime_status == RPM_SUSPENDING) { | 471 | || dev->power.runtime_status == RPM_SUSPENDING) { |
367 | DEFINE_WAIT(wait); | 472 | DEFINE_WAIT(wait); |
368 | 473 | ||
369 | if (from_wq) { | 474 | if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) { |
370 | if (dev->power.runtime_status == RPM_SUSPENDING) | 475 | if (dev->power.runtime_status == RPM_SUSPENDING) |
371 | dev->power.deferred_resume = true; | 476 | dev->power.deferred_resume = true; |
372 | retval = -EINPROGRESS; | 477 | else |
478 | retval = -EINPROGRESS; | ||
373 | goto out; | 479 | goto out; |
374 | } | 480 | } |
375 | 481 | ||
@@ -391,6 +497,34 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
391 | goto repeat; | 497 | goto repeat; |
392 | } | 498 | } |
393 | 499 | ||
500 | /* | ||
501 | * See if we can skip waking up the parent. This is safe only if | ||
502 | * power.no_callbacks is set, because otherwise we don't know whether | ||
503 | * the resume will actually succeed. | ||
504 | */ | ||
505 | if (dev->power.no_callbacks && !parent && dev->parent) { | ||
506 | spin_lock(&dev->parent->power.lock); | ||
507 | if (dev->parent->power.disable_depth > 0 | ||
508 | || dev->parent->power.ignore_children | ||
509 | || dev->parent->power.runtime_status == RPM_ACTIVE) { | ||
510 | atomic_inc(&dev->parent->power.child_count); | ||
511 | spin_unlock(&dev->parent->power.lock); | ||
512 | goto no_callback; /* Assume success. */ | ||
513 | } | ||
514 | spin_unlock(&dev->parent->power.lock); | ||
515 | } | ||
516 | |||
517 | /* Carry out an asynchronous or a synchronous resume. */ | ||
518 | if (rpmflags & RPM_ASYNC) { | ||
519 | dev->power.request = RPM_REQ_RESUME; | ||
520 | if (!dev->power.request_pending) { | ||
521 | dev->power.request_pending = true; | ||
522 | queue_work(pm_wq, &dev->power.work); | ||
523 | } | ||
524 | retval = 0; | ||
525 | goto out; | ||
526 | } | ||
527 | |||
394 | if (!parent && dev->parent) { | 528 | if (!parent && dev->parent) { |
395 | /* | 529 | /* |
396 | * Increment the parent's resume counter and resume it if | 530 | * Increment the parent's resume counter and resume it if |
@@ -408,7 +542,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
408 | */ | 542 | */ |
409 | if (!parent->power.disable_depth | 543 | if (!parent->power.disable_depth |
410 | && !parent->power.ignore_children) { | 544 | && !parent->power.ignore_children) { |
411 | __pm_runtime_resume(parent, false); | 545 | rpm_resume(parent, 0); |
412 | if (parent->power.runtime_status != RPM_ACTIVE) | 546 | if (parent->power.runtime_status != RPM_ACTIVE) |
413 | retval = -EBUSY; | 547 | retval = -EBUSY; |
414 | } | 548 | } |
@@ -420,39 +554,26 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
420 | goto repeat; | 554 | goto repeat; |
421 | } | 555 | } |
422 | 556 | ||
423 | __update_runtime_status(dev, RPM_RESUMING); | 557 | if (dev->power.no_callbacks) |
424 | 558 | goto no_callback; /* Assume success. */ | |
425 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) { | ||
426 | spin_unlock_irq(&dev->power.lock); | ||
427 | |||
428 | retval = dev->bus->pm->runtime_resume(dev); | ||
429 | |||
430 | spin_lock_irq(&dev->power.lock); | ||
431 | dev->power.runtime_error = retval; | ||
432 | } else if (dev->type && dev->type->pm | ||
433 | && dev->type->pm->runtime_resume) { | ||
434 | spin_unlock_irq(&dev->power.lock); | ||
435 | |||
436 | retval = dev->type->pm->runtime_resume(dev); | ||
437 | 559 | ||
438 | spin_lock_irq(&dev->power.lock); | 560 | __update_runtime_status(dev, RPM_RESUMING); |
439 | dev->power.runtime_error = retval; | ||
440 | } else if (dev->class && dev->class->pm | ||
441 | && dev->class->pm->runtime_resume) { | ||
442 | spin_unlock_irq(&dev->power.lock); | ||
443 | |||
444 | retval = dev->class->pm->runtime_resume(dev); | ||
445 | 561 | ||
446 | spin_lock_irq(&dev->power.lock); | 562 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) |
447 | dev->power.runtime_error = retval; | 563 | callback = dev->bus->pm->runtime_resume; |
448 | } else { | 564 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) |
449 | retval = -ENOSYS; | 565 | callback = dev->type->pm->runtime_resume; |
450 | } | 566 | else if (dev->class && dev->class->pm) |
567 | callback = dev->class->pm->runtime_resume; | ||
568 | else | ||
569 | callback = NULL; | ||
451 | 570 | ||
571 | retval = rpm_callback(callback, dev); | ||
452 | if (retval) { | 572 | if (retval) { |
453 | __update_runtime_status(dev, RPM_SUSPENDED); | 573 | __update_runtime_status(dev, RPM_SUSPENDED); |
454 | pm_runtime_cancel_pending(dev); | 574 | pm_runtime_cancel_pending(dev); |
455 | } else { | 575 | } else { |
576 | no_callback: | ||
456 | __update_runtime_status(dev, RPM_ACTIVE); | 577 | __update_runtime_status(dev, RPM_ACTIVE); |
457 | if (parent) | 578 | if (parent) |
458 | atomic_inc(&parent->power.child_count); | 579 | atomic_inc(&parent->power.child_count); |
@@ -460,7 +581,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
460 | wake_up_all(&dev->power.wait_queue); | 581 | wake_up_all(&dev->power.wait_queue); |
461 | 582 | ||
462 | if (!retval) | 583 | if (!retval) |
463 | __pm_request_idle(dev); | 584 | rpm_idle(dev, RPM_ASYNC); |
464 | 585 | ||
465 | out: | 586 | out: |
466 | if (parent) { | 587 | if (parent) { |
@@ -471,28 +592,12 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) | |||
471 | spin_lock_irq(&dev->power.lock); | 592 | spin_lock_irq(&dev->power.lock); |
472 | } | 593 | } |
473 | 594 | ||
474 | dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval); | 595 | dev_dbg(dev, "%s returns %d\n", __func__, retval); |
475 | 596 | ||
476 | return retval; | 597 | return retval; |
477 | } | 598 | } |
478 | 599 | ||
479 | /** | 600 | /** |
480 | * pm_runtime_resume - Carry out run-time resume of given device. | ||
481 | * @dev: Device to suspend. | ||
482 | */ | ||
483 | int pm_runtime_resume(struct device *dev) | ||
484 | { | ||
485 | int retval; | ||
486 | |||
487 | spin_lock_irq(&dev->power.lock); | ||
488 | retval = __pm_runtime_resume(dev, false); | ||
489 | spin_unlock_irq(&dev->power.lock); | ||
490 | |||
491 | return retval; | ||
492 | } | ||
493 | EXPORT_SYMBOL_GPL(pm_runtime_resume); | ||
494 | |||
495 | /** | ||
496 | * pm_runtime_work - Universal run-time PM work function. | 601 | * pm_runtime_work - Universal run-time PM work function. |
497 | * @work: Work structure used for scheduling the execution of this function. | 602 | * @work: Work structure used for scheduling the execution of this function. |
498 | * | 603 | * |
@@ -517,13 +622,16 @@ static void pm_runtime_work(struct work_struct *work) | |||
517 | case RPM_REQ_NONE: | 622 | case RPM_REQ_NONE: |
518 | break; | 623 | break; |
519 | case RPM_REQ_IDLE: | 624 | case RPM_REQ_IDLE: |
520 | __pm_runtime_idle(dev); | 625 | rpm_idle(dev, RPM_NOWAIT); |
521 | break; | 626 | break; |
522 | case RPM_REQ_SUSPEND: | 627 | case RPM_REQ_SUSPEND: |
523 | __pm_runtime_suspend(dev, true); | 628 | rpm_suspend(dev, RPM_NOWAIT); |
629 | break; | ||
630 | case RPM_REQ_AUTOSUSPEND: | ||
631 | rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO); | ||
524 | break; | 632 | break; |
525 | case RPM_REQ_RESUME: | 633 | case RPM_REQ_RESUME: |
526 | __pm_runtime_resume(dev, true); | 634 | rpm_resume(dev, RPM_NOWAIT); |
527 | break; | 635 | break; |
528 | } | 636 | } |
529 | 637 | ||
@@ -532,117 +640,10 @@ static void pm_runtime_work(struct work_struct *work) | |||
532 | } | 640 | } |
533 | 641 | ||
534 | /** | 642 | /** |
535 | * __pm_request_idle - Submit an idle notification request for given device. | ||
536 | * @dev: Device to handle. | ||
537 | * | ||
538 | * Check if the device's run-time PM status is correct for suspending the device | ||
539 | * and queue up a request to run __pm_runtime_idle() for it. | ||
540 | * | ||
541 | * This function must be called under dev->power.lock with interrupts disabled. | ||
542 | */ | ||
543 | static int __pm_request_idle(struct device *dev) | ||
544 | { | ||
545 | int retval = 0; | ||
546 | |||
547 | if (dev->power.runtime_error) | ||
548 | retval = -EINVAL; | ||
549 | else if (atomic_read(&dev->power.usage_count) > 0 | ||
550 | || dev->power.disable_depth > 0 | ||
551 | || dev->power.runtime_status == RPM_SUSPENDED | ||
552 | || dev->power.runtime_status == RPM_SUSPENDING) | ||
553 | retval = -EAGAIN; | ||
554 | else if (!pm_children_suspended(dev)) | ||
555 | retval = -EBUSY; | ||
556 | if (retval) | ||
557 | return retval; | ||
558 | |||
559 | if (dev->power.request_pending) { | ||
560 | /* Any requests other then RPM_REQ_IDLE take precedence. */ | ||
561 | if (dev->power.request == RPM_REQ_NONE) | ||
562 | dev->power.request = RPM_REQ_IDLE; | ||
563 | else if (dev->power.request != RPM_REQ_IDLE) | ||
564 | retval = -EAGAIN; | ||
565 | return retval; | ||
566 | } | ||
567 | |||
568 | dev->power.request = RPM_REQ_IDLE; | ||
569 | dev->power.request_pending = true; | ||
570 | queue_work(pm_wq, &dev->power.work); | ||
571 | |||
572 | return retval; | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * pm_request_idle - Submit an idle notification request for given device. | ||
577 | * @dev: Device to handle. | ||
578 | */ | ||
579 | int pm_request_idle(struct device *dev) | ||
580 | { | ||
581 | unsigned long flags; | ||
582 | int retval; | ||
583 | |||
584 | spin_lock_irqsave(&dev->power.lock, flags); | ||
585 | retval = __pm_request_idle(dev); | ||
586 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
587 | |||
588 | return retval; | ||
589 | } | ||
590 | EXPORT_SYMBOL_GPL(pm_request_idle); | ||
591 | |||
592 | /** | ||
593 | * __pm_request_suspend - Submit a suspend request for given device. | ||
594 | * @dev: Device to suspend. | ||
595 | * | ||
596 | * This function must be called under dev->power.lock with interrupts disabled. | ||
597 | */ | ||
598 | static int __pm_request_suspend(struct device *dev) | ||
599 | { | ||
600 | int retval = 0; | ||
601 | |||
602 | if (dev->power.runtime_error) | ||
603 | return -EINVAL; | ||
604 | |||
605 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
606 | retval = 1; | ||
607 | else if (atomic_read(&dev->power.usage_count) > 0 | ||
608 | || dev->power.disable_depth > 0) | ||
609 | retval = -EAGAIN; | ||
610 | else if (dev->power.runtime_status == RPM_SUSPENDING) | ||
611 | retval = -EINPROGRESS; | ||
612 | else if (!pm_children_suspended(dev)) | ||
613 | retval = -EBUSY; | ||
614 | if (retval < 0) | ||
615 | return retval; | ||
616 | |||
617 | pm_runtime_deactivate_timer(dev); | ||
618 | |||
619 | if (dev->power.request_pending) { | ||
620 | /* | ||
621 | * Pending resume requests take precedence over us, but we can | ||
622 | * overtake any other pending request. | ||
623 | */ | ||
624 | if (dev->power.request == RPM_REQ_RESUME) | ||
625 | retval = -EAGAIN; | ||
626 | else if (dev->power.request != RPM_REQ_SUSPEND) | ||
627 | dev->power.request = retval ? | ||
628 | RPM_REQ_NONE : RPM_REQ_SUSPEND; | ||
629 | return retval; | ||
630 | } else if (retval) { | ||
631 | return retval; | ||
632 | } | ||
633 | |||
634 | dev->power.request = RPM_REQ_SUSPEND; | ||
635 | dev->power.request_pending = true; | ||
636 | queue_work(pm_wq, &dev->power.work); | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * pm_suspend_timer_fn - Timer function for pm_schedule_suspend(). | 643 | * pm_suspend_timer_fn - Timer function for pm_schedule_suspend(). |
643 | * @data: Device pointer passed by pm_schedule_suspend(). | 644 | * @data: Device pointer passed by pm_schedule_suspend(). |
644 | * | 645 | * |
645 | * Check if the time is right and execute __pm_request_suspend() in that case. | 646 | * Check if the time is right and queue a suspend request. |
646 | */ | 647 | */ |
647 | static void pm_suspend_timer_fn(unsigned long data) | 648 | static void pm_suspend_timer_fn(unsigned long data) |
648 | { | 649 | { |
@@ -656,7 +657,8 @@ static void pm_suspend_timer_fn(unsigned long data) | |||
656 | /* If 'expire' is after 'jiffies' we've been called too early. */ | 657 | /* If 'expire' is after 'jiffies' we've been called too early. */ |
657 | if (expires > 0 && !time_after(expires, jiffies)) { | 658 | if (expires > 0 && !time_after(expires, jiffies)) { |
658 | dev->power.timer_expires = 0; | 659 | dev->power.timer_expires = 0; |
659 | __pm_request_suspend(dev); | 660 | rpm_suspend(dev, dev->power.timer_autosuspends ? |
661 | (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC); | ||
660 | } | 662 | } |
661 | 663 | ||
662 | spin_unlock_irqrestore(&dev->power.lock, flags); | 664 | spin_unlock_irqrestore(&dev->power.lock, flags); |
@@ -670,47 +672,25 @@ static void pm_suspend_timer_fn(unsigned long data) | |||
670 | int pm_schedule_suspend(struct device *dev, unsigned int delay) | 672 | int pm_schedule_suspend(struct device *dev, unsigned int delay) |
671 | { | 673 | { |
672 | unsigned long flags; | 674 | unsigned long flags; |
673 | int retval = 0; | 675 | int retval; |
674 | 676 | ||
675 | spin_lock_irqsave(&dev->power.lock, flags); | 677 | spin_lock_irqsave(&dev->power.lock, flags); |
676 | 678 | ||
677 | if (dev->power.runtime_error) { | ||
678 | retval = -EINVAL; | ||
679 | goto out; | ||
680 | } | ||
681 | |||
682 | if (!delay) { | 679 | if (!delay) { |
683 | retval = __pm_request_suspend(dev); | 680 | retval = rpm_suspend(dev, RPM_ASYNC); |
684 | goto out; | 681 | goto out; |
685 | } | 682 | } |
686 | 683 | ||
687 | pm_runtime_deactivate_timer(dev); | 684 | retval = rpm_check_suspend_allowed(dev); |
688 | |||
689 | if (dev->power.request_pending) { | ||
690 | /* | ||
691 | * Pending resume requests take precedence over us, but any | ||
692 | * other pending requests have to be canceled. | ||
693 | */ | ||
694 | if (dev->power.request == RPM_REQ_RESUME) { | ||
695 | retval = -EAGAIN; | ||
696 | goto out; | ||
697 | } | ||
698 | dev->power.request = RPM_REQ_NONE; | ||
699 | } | ||
700 | |||
701 | if (dev->power.runtime_status == RPM_SUSPENDED) | ||
702 | retval = 1; | ||
703 | else if (atomic_read(&dev->power.usage_count) > 0 | ||
704 | || dev->power.disable_depth > 0) | ||
705 | retval = -EAGAIN; | ||
706 | else if (!pm_children_suspended(dev)) | ||
707 | retval = -EBUSY; | ||
708 | if (retval) | 685 | if (retval) |
709 | goto out; | 686 | goto out; |
710 | 687 | ||
688 | /* Other scheduled or pending requests need to be canceled. */ | ||
689 | pm_runtime_cancel_pending(dev); | ||
690 | |||
711 | dev->power.timer_expires = jiffies + msecs_to_jiffies(delay); | 691 | dev->power.timer_expires = jiffies + msecs_to_jiffies(delay); |
712 | if (!dev->power.timer_expires) | 692 | dev->power.timer_expires += !dev->power.timer_expires; |
713 | dev->power.timer_expires = 1; | 693 | dev->power.timer_autosuspends = 0; |
714 | mod_timer(&dev->power.suspend_timer, dev->power.timer_expires); | 694 | mod_timer(&dev->power.suspend_timer, dev->power.timer_expires); |
715 | 695 | ||
716 | out: | 696 | out: |
@@ -721,103 +701,88 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay) | |||
721 | EXPORT_SYMBOL_GPL(pm_schedule_suspend); | 701 | EXPORT_SYMBOL_GPL(pm_schedule_suspend); |
722 | 702 | ||
723 | /** | 703 | /** |
724 | * pm_request_resume - Submit a resume request for given device. | 704 | * __pm_runtime_idle - Entry point for run-time idle operations. |
725 | * @dev: Device to resume. | 705 | * @dev: Device to send idle notification for. |
706 | * @rpmflags: Flag bits. | ||
726 | * | 707 | * |
727 | * This function must be called under dev->power.lock with interrupts disabled. | 708 | * If the RPM_GET_PUT flag is set, decrement the device's usage count and |
709 | * return immediately if it is larger than zero. Then carry out an idle | ||
710 | * notification, either synchronous or asynchronous. | ||
711 | * | ||
712 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. | ||
728 | */ | 713 | */ |
729 | static int __pm_request_resume(struct device *dev) | 714 | int __pm_runtime_idle(struct device *dev, int rpmflags) |
730 | { | 715 | { |
731 | int retval = 0; | 716 | unsigned long flags; |
732 | 717 | int retval; | |
733 | if (dev->power.runtime_error) | ||
734 | return -EINVAL; | ||
735 | |||
736 | if (dev->power.runtime_status == RPM_ACTIVE) | ||
737 | retval = 1; | ||
738 | else if (dev->power.runtime_status == RPM_RESUMING) | ||
739 | retval = -EINPROGRESS; | ||
740 | else if (dev->power.disable_depth > 0) | ||
741 | retval = -EAGAIN; | ||
742 | if (retval < 0) | ||
743 | return retval; | ||
744 | |||
745 | pm_runtime_deactivate_timer(dev); | ||
746 | 718 | ||
747 | if (dev->power.runtime_status == RPM_SUSPENDING) { | 719 | if (rpmflags & RPM_GET_PUT) { |
748 | dev->power.deferred_resume = true; | 720 | if (!atomic_dec_and_test(&dev->power.usage_count)) |
749 | return retval; | 721 | return 0; |
750 | } | 722 | } |
751 | if (dev->power.request_pending) { | ||
752 | /* If non-resume request is pending, we can overtake it. */ | ||
753 | dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME; | ||
754 | return retval; | ||
755 | } | ||
756 | if (retval) | ||
757 | return retval; | ||
758 | 723 | ||
759 | dev->power.request = RPM_REQ_RESUME; | 724 | spin_lock_irqsave(&dev->power.lock, flags); |
760 | dev->power.request_pending = true; | 725 | retval = rpm_idle(dev, rpmflags); |
761 | queue_work(pm_wq, &dev->power.work); | 726 | spin_unlock_irqrestore(&dev->power.lock, flags); |
762 | 727 | ||
763 | return retval; | 728 | return retval; |
764 | } | 729 | } |
730 | EXPORT_SYMBOL_GPL(__pm_runtime_idle); | ||
765 | 731 | ||
766 | /** | 732 | /** |
767 | * pm_request_resume - Submit a resume request for given device. | 733 | * __pm_runtime_suspend - Entry point for run-time put/suspend operations. |
768 | * @dev: Device to resume. | 734 | * @dev: Device to suspend. |
735 | * @rpmflags: Flag bits. | ||
736 | * | ||
737 | * If the RPM_GET_PUT flag is set, decrement the device's usage count and | ||
738 | * return immediately if it is larger than zero. Then carry out a suspend, | ||
739 | * either synchronous or asynchronous. | ||
740 | * | ||
741 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. | ||
769 | */ | 742 | */ |
770 | int pm_request_resume(struct device *dev) | 743 | int __pm_runtime_suspend(struct device *dev, int rpmflags) |
771 | { | 744 | { |
772 | unsigned long flags; | 745 | unsigned long flags; |
773 | int retval; | 746 | int retval; |
774 | 747 | ||
748 | if (rpmflags & RPM_GET_PUT) { | ||
749 | if (!atomic_dec_and_test(&dev->power.usage_count)) | ||
750 | return 0; | ||
751 | } | ||
752 | |||
775 | spin_lock_irqsave(&dev->power.lock, flags); | 753 | spin_lock_irqsave(&dev->power.lock, flags); |
776 | retval = __pm_request_resume(dev); | 754 | retval = rpm_suspend(dev, rpmflags); |
777 | spin_unlock_irqrestore(&dev->power.lock, flags); | 755 | spin_unlock_irqrestore(&dev->power.lock, flags); |
778 | 756 | ||
779 | return retval; | 757 | return retval; |
780 | } | 758 | } |
781 | EXPORT_SYMBOL_GPL(pm_request_resume); | 759 | EXPORT_SYMBOL_GPL(__pm_runtime_suspend); |
782 | 760 | ||
783 | /** | 761 | /** |
784 | * __pm_runtime_get - Reference count a device and wake it up, if necessary. | 762 | * __pm_runtime_resume - Entry point for run-time resume operations. |
785 | * @dev: Device to handle. | 763 | * @dev: Device to resume. |
786 | * @sync: If set and the device is suspended, resume it synchronously. | 764 | * @rpmflags: Flag bits. |
765 | * | ||
766 | * If the RPM_GET_PUT flag is set, increment the device's usage count. Then | ||
767 | * carry out a resume, either synchronous or asynchronous. | ||
787 | * | 768 | * |
788 | * Increment the usage count of the device and resume it or submit a resume | 769 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. |
789 | * request for it, depending on the value of @sync. | ||
790 | */ | 770 | */ |
791 | int __pm_runtime_get(struct device *dev, bool sync) | 771 | int __pm_runtime_resume(struct device *dev, int rpmflags) |
792 | { | 772 | { |
773 | unsigned long flags; | ||
793 | int retval; | 774 | int retval; |
794 | 775 | ||
795 | atomic_inc(&dev->power.usage_count); | 776 | if (rpmflags & RPM_GET_PUT) |
796 | retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev); | 777 | atomic_inc(&dev->power.usage_count); |
797 | 778 | ||
798 | return retval; | 779 | spin_lock_irqsave(&dev->power.lock, flags); |
799 | } | 780 | retval = rpm_resume(dev, rpmflags); |
800 | EXPORT_SYMBOL_GPL(__pm_runtime_get); | 781 | spin_unlock_irqrestore(&dev->power.lock, flags); |
801 | |||
802 | /** | ||
803 | * __pm_runtime_put - Decrement the device's usage counter and notify its bus. | ||
804 | * @dev: Device to handle. | ||
805 | * @sync: If the device's bus type is to be notified, do that synchronously. | ||
806 | * | ||
807 | * Decrement the usage count of the device and if it reaches zero, carry out a | ||
808 | * synchronous idle notification or submit an idle notification request for it, | ||
809 | * depending on the value of @sync. | ||
810 | */ | ||
811 | int __pm_runtime_put(struct device *dev, bool sync) | ||
812 | { | ||
813 | int retval = 0; | ||
814 | |||
815 | if (atomic_dec_and_test(&dev->power.usage_count)) | ||
816 | retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev); | ||
817 | 782 | ||
818 | return retval; | 783 | return retval; |
819 | } | 784 | } |
820 | EXPORT_SYMBOL_GPL(__pm_runtime_put); | 785 | EXPORT_SYMBOL_GPL(__pm_runtime_resume); |
821 | 786 | ||
822 | /** | 787 | /** |
823 | * __pm_runtime_set_status - Set run-time PM status of a device. | 788 | * __pm_runtime_set_status - Set run-time PM status of a device. |
@@ -968,7 +933,7 @@ int pm_runtime_barrier(struct device *dev) | |||
968 | 933 | ||
969 | if (dev->power.request_pending | 934 | if (dev->power.request_pending |
970 | && dev->power.request == RPM_REQ_RESUME) { | 935 | && dev->power.request == RPM_REQ_RESUME) { |
971 | __pm_runtime_resume(dev, false); | 936 | rpm_resume(dev, 0); |
972 | retval = 1; | 937 | retval = 1; |
973 | } | 938 | } |
974 | 939 | ||
@@ -1017,7 +982,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume) | |||
1017 | */ | 982 | */ |
1018 | pm_runtime_get_noresume(dev); | 983 | pm_runtime_get_noresume(dev); |
1019 | 984 | ||
1020 | __pm_runtime_resume(dev, false); | 985 | rpm_resume(dev, 0); |
1021 | 986 | ||
1022 | pm_runtime_put_noidle(dev); | 987 | pm_runtime_put_noidle(dev); |
1023 | } | 988 | } |
@@ -1065,7 +1030,7 @@ void pm_runtime_forbid(struct device *dev) | |||
1065 | 1030 | ||
1066 | dev->power.runtime_auto = false; | 1031 | dev->power.runtime_auto = false; |
1067 | atomic_inc(&dev->power.usage_count); | 1032 | atomic_inc(&dev->power.usage_count); |
1068 | __pm_runtime_resume(dev, false); | 1033 | rpm_resume(dev, 0); |
1069 | 1034 | ||
1070 | out: | 1035 | out: |
1071 | spin_unlock_irq(&dev->power.lock); | 1036 | spin_unlock_irq(&dev->power.lock); |
@@ -1086,7 +1051,7 @@ void pm_runtime_allow(struct device *dev) | |||
1086 | 1051 | ||
1087 | dev->power.runtime_auto = true; | 1052 | dev->power.runtime_auto = true; |
1088 | if (atomic_dec_and_test(&dev->power.usage_count)) | 1053 | if (atomic_dec_and_test(&dev->power.usage_count)) |
1089 | __pm_runtime_idle(dev); | 1054 | rpm_idle(dev, RPM_AUTO); |
1090 | 1055 | ||
1091 | out: | 1056 | out: |
1092 | spin_unlock_irq(&dev->power.lock); | 1057 | spin_unlock_irq(&dev->power.lock); |
@@ -1094,13 +1059,110 @@ void pm_runtime_allow(struct device *dev) | |||
1094 | EXPORT_SYMBOL_GPL(pm_runtime_allow); | 1059 | EXPORT_SYMBOL_GPL(pm_runtime_allow); |
1095 | 1060 | ||
1096 | /** | 1061 | /** |
1062 | * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device. | ||
1063 | * @dev: Device to handle. | ||
1064 | * | ||
1065 | * Set the power.no_callbacks flag, which tells the PM core that this | ||
1066 | * device is power-managed through its parent and has no run-time PM | ||
1067 | * callbacks of its own. The run-time sysfs attributes will be removed. | ||
1068 | * | ||
1069 | */ | ||
1070 | void pm_runtime_no_callbacks(struct device *dev) | ||
1071 | { | ||
1072 | spin_lock_irq(&dev->power.lock); | ||
1073 | dev->power.no_callbacks = 1; | ||
1074 | spin_unlock_irq(&dev->power.lock); | ||
1075 | if (device_is_registered(dev)) | ||
1076 | rpm_sysfs_remove(dev); | ||
1077 | } | ||
1078 | EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks); | ||
1079 | |||
1080 | /** | ||
1081 | * update_autosuspend - Handle a change to a device's autosuspend settings. | ||
1082 | * @dev: Device to handle. | ||
1083 | * @old_delay: The former autosuspend_delay value. | ||
1084 | * @old_use: The former use_autosuspend value. | ||
1085 | * | ||
1086 | * Prevent runtime suspend if the new delay is negative and use_autosuspend is | ||
1087 | * set; otherwise allow it. Send an idle notification if suspends are allowed. | ||
1088 | * | ||
1089 | * This function must be called under dev->power.lock with interrupts disabled. | ||
1090 | */ | ||
1091 | static void update_autosuspend(struct device *dev, int old_delay, int old_use) | ||
1092 | { | ||
1093 | int delay = dev->power.autosuspend_delay; | ||
1094 | |||
1095 | /* Should runtime suspend be prevented now? */ | ||
1096 | if (dev->power.use_autosuspend && delay < 0) { | ||
1097 | |||
1098 | /* If it used to be allowed then prevent it. */ | ||
1099 | if (!old_use || old_delay >= 0) { | ||
1100 | atomic_inc(&dev->power.usage_count); | ||
1101 | rpm_resume(dev, 0); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | /* Runtime suspend should be allowed now. */ | ||
1106 | else { | ||
1107 | |||
1108 | /* If it used to be prevented then allow it. */ | ||
1109 | if (old_use && old_delay < 0) | ||
1110 | atomic_dec(&dev->power.usage_count); | ||
1111 | |||
1112 | /* Maybe we can autosuspend now. */ | ||
1113 | rpm_idle(dev, RPM_AUTO); | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | /** | ||
1118 | * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value. | ||
1119 | * @dev: Device to handle. | ||
1120 | * @delay: Value of the new delay in milliseconds. | ||
1121 | * | ||
1122 | * Set the device's power.autosuspend_delay value. If it changes to negative | ||
1123 | * and the power.use_autosuspend flag is set, prevent run-time suspends. If it | ||
1124 | * changes the other way, allow run-time suspends. | ||
1125 | */ | ||
1126 | void pm_runtime_set_autosuspend_delay(struct device *dev, int delay) | ||
1127 | { | ||
1128 | int old_delay, old_use; | ||
1129 | |||
1130 | spin_lock_irq(&dev->power.lock); | ||
1131 | old_delay = dev->power.autosuspend_delay; | ||
1132 | old_use = dev->power.use_autosuspend; | ||
1133 | dev->power.autosuspend_delay = delay; | ||
1134 | update_autosuspend(dev, old_delay, old_use); | ||
1135 | spin_unlock_irq(&dev->power.lock); | ||
1136 | } | ||
1137 | EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay); | ||
1138 | |||
1139 | /** | ||
1140 | * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag. | ||
1141 | * @dev: Device to handle. | ||
1142 | * @use: New value for use_autosuspend. | ||
1143 | * | ||
1144 | * Set the device's power.use_autosuspend flag, and allow or prevent run-time | ||
1145 | * suspends as needed. | ||
1146 | */ | ||
1147 | void __pm_runtime_use_autosuspend(struct device *dev, bool use) | ||
1148 | { | ||
1149 | int old_delay, old_use; | ||
1150 | |||
1151 | spin_lock_irq(&dev->power.lock); | ||
1152 | old_delay = dev->power.autosuspend_delay; | ||
1153 | old_use = dev->power.use_autosuspend; | ||
1154 | dev->power.use_autosuspend = use; | ||
1155 | update_autosuspend(dev, old_delay, old_use); | ||
1156 | spin_unlock_irq(&dev->power.lock); | ||
1157 | } | ||
1158 | EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend); | ||
1159 | |||
1160 | /** | ||
1097 | * pm_runtime_init - Initialize run-time PM fields in given device object. | 1161 | * pm_runtime_init - Initialize run-time PM fields in given device object. |
1098 | * @dev: Device object to initialize. | 1162 | * @dev: Device object to initialize. |
1099 | */ | 1163 | */ |
1100 | void pm_runtime_init(struct device *dev) | 1164 | void pm_runtime_init(struct device *dev) |
1101 | { | 1165 | { |
1102 | spin_lock_init(&dev->power.lock); | ||
1103 | |||
1104 | dev->power.runtime_status = RPM_SUSPENDED; | 1166 | dev->power.runtime_status = RPM_SUSPENDED; |
1105 | dev->power.idle_notification = false; | 1167 | dev->power.idle_notification = false; |
1106 | 1168 | ||
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index e56b4388fe61..0b1e46bf3e56 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -75,12 +75,27 @@ | |||
75 | * attribute is set to "enabled" by bus type code or device drivers and in | 75 | * attribute is set to "enabled" by bus type code or device drivers and in |
76 | * that cases it should be safe to leave the default value. | 76 | * that cases it should be safe to leave the default value. |
77 | * | 77 | * |
78 | * autosuspend_delay_ms - Report/change a device's autosuspend_delay value | ||
79 | * | ||
80 | * Some drivers don't want to carry out a runtime suspend as soon as a | ||
81 | * device becomes idle; they want it always to remain idle for some period | ||
82 | * of time before suspending it. This period is the autosuspend_delay | ||
83 | * value (expressed in milliseconds) and it can be controlled by the user. | ||
84 | * If the value is negative then the device will never be runtime | ||
85 | * suspended. | ||
86 | * | ||
87 | * NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay | ||
88 | * value are used only if the driver calls pm_runtime_use_autosuspend(). | ||
89 | * | ||
78 | * wakeup_count - Report the number of wakeup events related to the device | 90 | * wakeup_count - Report the number of wakeup events related to the device |
79 | */ | 91 | */ |
80 | 92 | ||
81 | static const char enabled[] = "enabled"; | 93 | static const char enabled[] = "enabled"; |
82 | static const char disabled[] = "disabled"; | 94 | static const char disabled[] = "disabled"; |
83 | 95 | ||
96 | const char power_group_name[] = "power"; | ||
97 | EXPORT_SYMBOL_GPL(power_group_name); | ||
98 | |||
84 | #ifdef CONFIG_PM_RUNTIME | 99 | #ifdef CONFIG_PM_RUNTIME |
85 | static const char ctrl_auto[] = "auto"; | 100 | static const char ctrl_auto[] = "auto"; |
86 | static const char ctrl_on[] = "on"; | 101 | static const char ctrl_on[] = "on"; |
@@ -170,6 +185,33 @@ static ssize_t rtpm_status_show(struct device *dev, | |||
170 | } | 185 | } |
171 | 186 | ||
172 | static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL); | 187 | static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL); |
188 | |||
189 | static ssize_t autosuspend_delay_ms_show(struct device *dev, | ||
190 | struct device_attribute *attr, char *buf) | ||
191 | { | ||
192 | if (!dev->power.use_autosuspend) | ||
193 | return -EIO; | ||
194 | return sprintf(buf, "%d\n", dev->power.autosuspend_delay); | ||
195 | } | ||
196 | |||
197 | static ssize_t autosuspend_delay_ms_store(struct device *dev, | ||
198 | struct device_attribute *attr, const char *buf, size_t n) | ||
199 | { | ||
200 | long delay; | ||
201 | |||
202 | if (!dev->power.use_autosuspend) | ||
203 | return -EIO; | ||
204 | |||
205 | if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay) | ||
206 | return -EINVAL; | ||
207 | |||
208 | pm_runtime_set_autosuspend_delay(dev, delay); | ||
209 | return n; | ||
210 | } | ||
211 | |||
212 | static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show, | ||
213 | autosuspend_delay_ms_store); | ||
214 | |||
173 | #endif | 215 | #endif |
174 | 216 | ||
175 | static ssize_t | 217 | static ssize_t |
@@ -210,11 +252,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); | |||
210 | static ssize_t wakeup_count_show(struct device *dev, | 252 | static ssize_t wakeup_count_show(struct device *dev, |
211 | struct device_attribute *attr, char *buf) | 253 | struct device_attribute *attr, char *buf) |
212 | { | 254 | { |
213 | return sprintf(buf, "%lu\n", dev->power.wakeup_count); | 255 | unsigned long count = 0; |
256 | bool enabled = false; | ||
257 | |||
258 | spin_lock_irq(&dev->power.lock); | ||
259 | if (dev->power.wakeup) { | ||
260 | count = dev->power.wakeup->event_count; | ||
261 | enabled = true; | ||
262 | } | ||
263 | spin_unlock_irq(&dev->power.lock); | ||
264 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
214 | } | 265 | } |
215 | 266 | ||
216 | static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); | 267 | static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); |
217 | #endif | 268 | |
269 | static ssize_t wakeup_active_count_show(struct device *dev, | ||
270 | struct device_attribute *attr, char *buf) | ||
271 | { | ||
272 | unsigned long count = 0; | ||
273 | bool enabled = false; | ||
274 | |||
275 | spin_lock_irq(&dev->power.lock); | ||
276 | if (dev->power.wakeup) { | ||
277 | count = dev->power.wakeup->active_count; | ||
278 | enabled = true; | ||
279 | } | ||
280 | spin_unlock_irq(&dev->power.lock); | ||
281 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
282 | } | ||
283 | |||
284 | static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL); | ||
285 | |||
286 | static ssize_t wakeup_hit_count_show(struct device *dev, | ||
287 | struct device_attribute *attr, char *buf) | ||
288 | { | ||
289 | unsigned long count = 0; | ||
290 | bool enabled = false; | ||
291 | |||
292 | spin_lock_irq(&dev->power.lock); | ||
293 | if (dev->power.wakeup) { | ||
294 | count = dev->power.wakeup->hit_count; | ||
295 | enabled = true; | ||
296 | } | ||
297 | spin_unlock_irq(&dev->power.lock); | ||
298 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
299 | } | ||
300 | |||
301 | static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL); | ||
302 | |||
303 | static ssize_t wakeup_active_show(struct device *dev, | ||
304 | struct device_attribute *attr, char *buf) | ||
305 | { | ||
306 | unsigned int active = 0; | ||
307 | bool enabled = false; | ||
308 | |||
309 | spin_lock_irq(&dev->power.lock); | ||
310 | if (dev->power.wakeup) { | ||
311 | active = dev->power.wakeup->active; | ||
312 | enabled = true; | ||
313 | } | ||
314 | spin_unlock_irq(&dev->power.lock); | ||
315 | return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n"); | ||
316 | } | ||
317 | |||
318 | static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL); | ||
319 | |||
320 | static ssize_t wakeup_total_time_show(struct device *dev, | ||
321 | struct device_attribute *attr, char *buf) | ||
322 | { | ||
323 | s64 msec = 0; | ||
324 | bool enabled = false; | ||
325 | |||
326 | spin_lock_irq(&dev->power.lock); | ||
327 | if (dev->power.wakeup) { | ||
328 | msec = ktime_to_ms(dev->power.wakeup->total_time); | ||
329 | enabled = true; | ||
330 | } | ||
331 | spin_unlock_irq(&dev->power.lock); | ||
332 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
333 | } | ||
334 | |||
335 | static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL); | ||
336 | |||
337 | static ssize_t wakeup_max_time_show(struct device *dev, | ||
338 | struct device_attribute *attr, char *buf) | ||
339 | { | ||
340 | s64 msec = 0; | ||
341 | bool enabled = false; | ||
342 | |||
343 | spin_lock_irq(&dev->power.lock); | ||
344 | if (dev->power.wakeup) { | ||
345 | msec = ktime_to_ms(dev->power.wakeup->max_time); | ||
346 | enabled = true; | ||
347 | } | ||
348 | spin_unlock_irq(&dev->power.lock); | ||
349 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
350 | } | ||
351 | |||
352 | static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL); | ||
353 | |||
354 | static ssize_t wakeup_last_time_show(struct device *dev, | ||
355 | struct device_attribute *attr, char *buf) | ||
356 | { | ||
357 | s64 msec = 0; | ||
358 | bool enabled = false; | ||
359 | |||
360 | spin_lock_irq(&dev->power.lock); | ||
361 | if (dev->power.wakeup) { | ||
362 | msec = ktime_to_ms(dev->power.wakeup->last_time); | ||
363 | enabled = true; | ||
364 | } | ||
365 | spin_unlock_irq(&dev->power.lock); | ||
366 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
367 | } | ||
368 | |||
369 | static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL); | ||
370 | #endif /* CONFIG_PM_SLEEP */ | ||
218 | 371 | ||
219 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 372 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
220 | #ifdef CONFIG_PM_RUNTIME | 373 | #ifdef CONFIG_PM_RUNTIME |
@@ -279,19 +432,20 @@ static DEVICE_ATTR(async, 0644, async_show, async_store); | |||
279 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ | 432 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ |
280 | 433 | ||
281 | static struct attribute * power_attrs[] = { | 434 | static struct attribute * power_attrs[] = { |
282 | #ifdef CONFIG_PM_RUNTIME | ||
283 | &dev_attr_control.attr, | ||
284 | &dev_attr_runtime_status.attr, | ||
285 | &dev_attr_runtime_suspended_time.attr, | ||
286 | &dev_attr_runtime_active_time.attr, | ||
287 | #endif | ||
288 | &dev_attr_wakeup.attr, | 435 | &dev_attr_wakeup.attr, |
289 | #ifdef CONFIG_PM_SLEEP | 436 | #ifdef CONFIG_PM_SLEEP |
290 | &dev_attr_wakeup_count.attr, | 437 | &dev_attr_wakeup_count.attr, |
438 | &dev_attr_wakeup_active_count.attr, | ||
439 | &dev_attr_wakeup_hit_count.attr, | ||
440 | &dev_attr_wakeup_active.attr, | ||
441 | &dev_attr_wakeup_total_time_ms.attr, | ||
442 | &dev_attr_wakeup_max_time_ms.attr, | ||
443 | &dev_attr_wakeup_last_time_ms.attr, | ||
291 | #endif | 444 | #endif |
292 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 445 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
293 | &dev_attr_async.attr, | 446 | &dev_attr_async.attr, |
294 | #ifdef CONFIG_PM_RUNTIME | 447 | #ifdef CONFIG_PM_RUNTIME |
448 | &dev_attr_runtime_status.attr, | ||
295 | &dev_attr_runtime_usage.attr, | 449 | &dev_attr_runtime_usage.attr, |
296 | &dev_attr_runtime_active_kids.attr, | 450 | &dev_attr_runtime_active_kids.attr, |
297 | &dev_attr_runtime_enabled.attr, | 451 | &dev_attr_runtime_enabled.attr, |
@@ -300,10 +454,53 @@ static struct attribute * power_attrs[] = { | |||
300 | NULL, | 454 | NULL, |
301 | }; | 455 | }; |
302 | static struct attribute_group pm_attr_group = { | 456 | static struct attribute_group pm_attr_group = { |
303 | .name = "power", | 457 | .name = power_group_name, |
304 | .attrs = power_attrs, | 458 | .attrs = power_attrs, |
305 | }; | 459 | }; |
306 | 460 | ||
461 | #ifdef CONFIG_PM_RUNTIME | ||
462 | |||
463 | static struct attribute *runtime_attrs[] = { | ||
464 | #ifndef CONFIG_PM_ADVANCED_DEBUG | ||
465 | &dev_attr_runtime_status.attr, | ||
466 | #endif | ||
467 | &dev_attr_control.attr, | ||
468 | &dev_attr_runtime_suspended_time.attr, | ||
469 | &dev_attr_runtime_active_time.attr, | ||
470 | &dev_attr_autosuspend_delay_ms.attr, | ||
471 | NULL, | ||
472 | }; | ||
473 | static struct attribute_group pm_runtime_attr_group = { | ||
474 | .name = power_group_name, | ||
475 | .attrs = runtime_attrs, | ||
476 | }; | ||
477 | |||
478 | int dpm_sysfs_add(struct device *dev) | ||
479 | { | ||
480 | int rc; | ||
481 | |||
482 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); | ||
483 | if (rc == 0 && !dev->power.no_callbacks) { | ||
484 | rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); | ||
485 | if (rc) | ||
486 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
487 | } | ||
488 | return rc; | ||
489 | } | ||
490 | |||
491 | void rpm_sysfs_remove(struct device *dev) | ||
492 | { | ||
493 | sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); | ||
494 | } | ||
495 | |||
496 | void dpm_sysfs_remove(struct device *dev) | ||
497 | { | ||
498 | rpm_sysfs_remove(dev); | ||
499 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
500 | } | ||
501 | |||
502 | #else /* CONFIG_PM_RUNTIME */ | ||
503 | |||
307 | int dpm_sysfs_add(struct device * dev) | 504 | int dpm_sysfs_add(struct device * dev) |
308 | { | 505 | { |
309 | return sysfs_create_group(&dev->kobj, &pm_attr_group); | 506 | return sysfs_create_group(&dev->kobj, &pm_attr_group); |
@@ -313,3 +510,5 @@ void dpm_sysfs_remove(struct device * dev) | |||
313 | { | 510 | { |
314 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 511 | sysfs_remove_group(&dev->kobj, &pm_attr_group); |
315 | } | 512 | } |
513 | |||
514 | #endif | ||
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index 0a1a2c4dbc6e..9f4258df4cfd 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
@@ -188,8 +188,10 @@ static int show_file_hash(unsigned int value) | |||
188 | static int show_dev_hash(unsigned int value) | 188 | static int show_dev_hash(unsigned int value) |
189 | { | 189 | { |
190 | int match = 0; | 190 | int match = 0; |
191 | struct list_head *entry = dpm_list.prev; | 191 | struct list_head *entry; |
192 | 192 | ||
193 | device_pm_lock(); | ||
194 | entry = dpm_list.prev; | ||
193 | while (entry != &dpm_list) { | 195 | while (entry != &dpm_list) { |
194 | struct device * dev = to_device(entry); | 196 | struct device * dev = to_device(entry); |
195 | unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH); | 197 | unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH); |
@@ -199,11 +201,43 @@ static int show_dev_hash(unsigned int value) | |||
199 | } | 201 | } |
200 | entry = entry->prev; | 202 | entry = entry->prev; |
201 | } | 203 | } |
204 | device_pm_unlock(); | ||
202 | return match; | 205 | return match; |
203 | } | 206 | } |
204 | 207 | ||
205 | static unsigned int hash_value_early_read; | 208 | static unsigned int hash_value_early_read; |
206 | 209 | ||
210 | int show_trace_dev_match(char *buf, size_t size) | ||
211 | { | ||
212 | unsigned int value = hash_value_early_read / (USERHASH * FILEHASH); | ||
213 | int ret = 0; | ||
214 | struct list_head *entry; | ||
215 | |||
216 | /* | ||
217 | * It's possible that multiple devices will match the hash and we can't | ||
218 | * tell which is the culprit, so it's best to output them all. | ||
219 | */ | ||
220 | device_pm_lock(); | ||
221 | entry = dpm_list.prev; | ||
222 | while (size && entry != &dpm_list) { | ||
223 | struct device *dev = to_device(entry); | ||
224 | unsigned int hash = hash_string(DEVSEED, dev_name(dev), | ||
225 | DEVHASH); | ||
226 | if (hash == value) { | ||
227 | int len = snprintf(buf, size, "%s\n", | ||
228 | dev_driver_string(dev)); | ||
229 | if (len > size) | ||
230 | len = size; | ||
231 | buf += len; | ||
232 | ret += len; | ||
233 | size -= len; | ||
234 | } | ||
235 | entry = entry->prev; | ||
236 | } | ||
237 | device_pm_unlock(); | ||
238 | return ret; | ||
239 | } | ||
240 | |||
207 | static int early_resume_init(void) | 241 | static int early_resume_init(void) |
208 | { | 242 | { |
209 | hash_value_early_read = read_magic_time(); | 243 | hash_value_early_read = read_magic_time(); |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index eb594facfc3f..71c5528e1c35 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -11,7 +11,12 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/capability.h> | 12 | #include <linux/capability.h> |
13 | #include <linux/suspend.h> | 13 | #include <linux/suspend.h> |
14 | #include <linux/pm.h> | 14 | #include <linux/seq_file.h> |
15 | #include <linux/debugfs.h> | ||
16 | |||
17 | #include "power.h" | ||
18 | |||
19 | #define TIMEOUT 100 | ||
15 | 20 | ||
16 | /* | 21 | /* |
17 | * If set, the suspend/hibernate code will abort transitions to a sleep state | 22 | * If set, the suspend/hibernate code will abort transitions to a sleep state |
@@ -20,18 +25,244 @@ | |||
20 | bool events_check_enabled; | 25 | bool events_check_enabled; |
21 | 26 | ||
22 | /* The counter of registered wakeup events. */ | 27 | /* The counter of registered wakeup events. */ |
23 | static unsigned long event_count; | 28 | static atomic_t event_count = ATOMIC_INIT(0); |
24 | /* A preserved old value of event_count. */ | 29 | /* A preserved old value of event_count. */ |
25 | static unsigned long saved_event_count; | 30 | static unsigned int saved_count; |
26 | /* The counter of wakeup events being processed. */ | 31 | /* The counter of wakeup events being processed. */ |
27 | static unsigned long events_in_progress; | 32 | static atomic_t events_in_progress = ATOMIC_INIT(0); |
28 | 33 | ||
29 | static DEFINE_SPINLOCK(events_lock); | 34 | static DEFINE_SPINLOCK(events_lock); |
30 | 35 | ||
31 | static void pm_wakeup_timer_fn(unsigned long data); | 36 | static void pm_wakeup_timer_fn(unsigned long data); |
32 | 37 | ||
33 | static DEFINE_TIMER(events_timer, pm_wakeup_timer_fn, 0, 0); | 38 | static LIST_HEAD(wakeup_sources); |
34 | static unsigned long events_timer_expires; | 39 | |
40 | /** | ||
41 | * wakeup_source_create - Create a struct wakeup_source object. | ||
42 | * @name: Name of the new wakeup source. | ||
43 | */ | ||
44 | struct wakeup_source *wakeup_source_create(const char *name) | ||
45 | { | ||
46 | struct wakeup_source *ws; | ||
47 | |||
48 | ws = kzalloc(sizeof(*ws), GFP_KERNEL); | ||
49 | if (!ws) | ||
50 | return NULL; | ||
51 | |||
52 | spin_lock_init(&ws->lock); | ||
53 | if (name) | ||
54 | ws->name = kstrdup(name, GFP_KERNEL); | ||
55 | |||
56 | return ws; | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(wakeup_source_create); | ||
59 | |||
60 | /** | ||
61 | * wakeup_source_destroy - Destroy a struct wakeup_source object. | ||
62 | * @ws: Wakeup source to destroy. | ||
63 | */ | ||
64 | void wakeup_source_destroy(struct wakeup_source *ws) | ||
65 | { | ||
66 | if (!ws) | ||
67 | return; | ||
68 | |||
69 | spin_lock_irq(&ws->lock); | ||
70 | while (ws->active) { | ||
71 | spin_unlock_irq(&ws->lock); | ||
72 | |||
73 | schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); | ||
74 | |||
75 | spin_lock_irq(&ws->lock); | ||
76 | } | ||
77 | spin_unlock_irq(&ws->lock); | ||
78 | |||
79 | kfree(ws->name); | ||
80 | kfree(ws); | ||
81 | } | ||
82 | EXPORT_SYMBOL_GPL(wakeup_source_destroy); | ||
83 | |||
84 | /** | ||
85 | * wakeup_source_add - Add given object to the list of wakeup sources. | ||
86 | * @ws: Wakeup source object to add to the list. | ||
87 | */ | ||
88 | void wakeup_source_add(struct wakeup_source *ws) | ||
89 | { | ||
90 | if (WARN_ON(!ws)) | ||
91 | return; | ||
92 | |||
93 | setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws); | ||
94 | ws->active = false; | ||
95 | |||
96 | spin_lock_irq(&events_lock); | ||
97 | list_add_rcu(&ws->entry, &wakeup_sources); | ||
98 | spin_unlock_irq(&events_lock); | ||
99 | synchronize_rcu(); | ||
100 | } | ||
101 | EXPORT_SYMBOL_GPL(wakeup_source_add); | ||
102 | |||
103 | /** | ||
104 | * wakeup_source_remove - Remove given object from the wakeup sources list. | ||
105 | * @ws: Wakeup source object to remove from the list. | ||
106 | */ | ||
107 | void wakeup_source_remove(struct wakeup_source *ws) | ||
108 | { | ||
109 | if (WARN_ON(!ws)) | ||
110 | return; | ||
111 | |||
112 | spin_lock_irq(&events_lock); | ||
113 | list_del_rcu(&ws->entry); | ||
114 | spin_unlock_irq(&events_lock); | ||
115 | synchronize_rcu(); | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(wakeup_source_remove); | ||
118 | |||
119 | /** | ||
120 | * wakeup_source_register - Create wakeup source and add it to the list. | ||
121 | * @name: Name of the wakeup source to register. | ||
122 | */ | ||
123 | struct wakeup_source *wakeup_source_register(const char *name) | ||
124 | { | ||
125 | struct wakeup_source *ws; | ||
126 | |||
127 | ws = wakeup_source_create(name); | ||
128 | if (ws) | ||
129 | wakeup_source_add(ws); | ||
130 | |||
131 | return ws; | ||
132 | } | ||
133 | EXPORT_SYMBOL_GPL(wakeup_source_register); | ||
134 | |||
135 | /** | ||
136 | * wakeup_source_unregister - Remove wakeup source from the list and remove it. | ||
137 | * @ws: Wakeup source object to unregister. | ||
138 | */ | ||
139 | void wakeup_source_unregister(struct wakeup_source *ws) | ||
140 | { | ||
141 | wakeup_source_remove(ws); | ||
142 | wakeup_source_destroy(ws); | ||
143 | } | ||
144 | EXPORT_SYMBOL_GPL(wakeup_source_unregister); | ||
145 | |||
146 | /** | ||
147 | * device_wakeup_attach - Attach a wakeup source object to a device object. | ||
148 | * @dev: Device to handle. | ||
149 | * @ws: Wakeup source object to attach to @dev. | ||
150 | * | ||
151 | * This causes @dev to be treated as a wakeup device. | ||
152 | */ | ||
153 | static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws) | ||
154 | { | ||
155 | spin_lock_irq(&dev->power.lock); | ||
156 | if (dev->power.wakeup) { | ||
157 | spin_unlock_irq(&dev->power.lock); | ||
158 | return -EEXIST; | ||
159 | } | ||
160 | dev->power.wakeup = ws; | ||
161 | spin_unlock_irq(&dev->power.lock); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * device_wakeup_enable - Enable given device to be a wakeup source. | ||
167 | * @dev: Device to handle. | ||
168 | * | ||
169 | * Create a wakeup source object, register it and attach it to @dev. | ||
170 | */ | ||
171 | int device_wakeup_enable(struct device *dev) | ||
172 | { | ||
173 | struct wakeup_source *ws; | ||
174 | int ret; | ||
175 | |||
176 | if (!dev || !dev->power.can_wakeup) | ||
177 | return -EINVAL; | ||
178 | |||
179 | ws = wakeup_source_register(dev_name(dev)); | ||
180 | if (!ws) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | ret = device_wakeup_attach(dev, ws); | ||
184 | if (ret) | ||
185 | wakeup_source_unregister(ws); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(device_wakeup_enable); | ||
190 | |||
191 | /** | ||
192 | * device_wakeup_detach - Detach a device's wakeup source object from it. | ||
193 | * @dev: Device to detach the wakeup source object from. | ||
194 | * | ||
195 | * After it returns, @dev will not be treated as a wakeup device any more. | ||
196 | */ | ||
197 | static struct wakeup_source *device_wakeup_detach(struct device *dev) | ||
198 | { | ||
199 | struct wakeup_source *ws; | ||
200 | |||
201 | spin_lock_irq(&dev->power.lock); | ||
202 | ws = dev->power.wakeup; | ||
203 | dev->power.wakeup = NULL; | ||
204 | spin_unlock_irq(&dev->power.lock); | ||
205 | return ws; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * device_wakeup_disable - Do not regard a device as a wakeup source any more. | ||
210 | * @dev: Device to handle. | ||
211 | * | ||
212 | * Detach the @dev's wakeup source object from it, unregister this wakeup source | ||
213 | * object and destroy it. | ||
214 | */ | ||
215 | int device_wakeup_disable(struct device *dev) | ||
216 | { | ||
217 | struct wakeup_source *ws; | ||
218 | |||
219 | if (!dev || !dev->power.can_wakeup) | ||
220 | return -EINVAL; | ||
221 | |||
222 | ws = device_wakeup_detach(dev); | ||
223 | if (ws) | ||
224 | wakeup_source_unregister(ws); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(device_wakeup_disable); | ||
229 | |||
230 | /** | ||
231 | * device_init_wakeup - Device wakeup initialization. | ||
232 | * @dev: Device to handle. | ||
233 | * @enable: Whether or not to enable @dev as a wakeup device. | ||
234 | * | ||
235 | * By default, most devices should leave wakeup disabled. The exceptions are | ||
236 | * devices that everyone expects to be wakeup sources: keyboards, power buttons, | ||
237 | * possibly network interfaces, etc. | ||
238 | */ | ||
239 | int device_init_wakeup(struct device *dev, bool enable) | ||
240 | { | ||
241 | int ret = 0; | ||
242 | |||
243 | if (enable) { | ||
244 | device_set_wakeup_capable(dev, true); | ||
245 | ret = device_wakeup_enable(dev); | ||
246 | } else { | ||
247 | device_set_wakeup_capable(dev, false); | ||
248 | } | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | EXPORT_SYMBOL_GPL(device_init_wakeup); | ||
253 | |||
254 | /** | ||
255 | * device_set_wakeup_enable - Enable or disable a device to wake up the system. | ||
256 | * @dev: Device to handle. | ||
257 | */ | ||
258 | int device_set_wakeup_enable(struct device *dev, bool enable) | ||
259 | { | ||
260 | if (!dev || !dev->power.can_wakeup) | ||
261 | return -EINVAL; | ||
262 | |||
263 | return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev); | ||
264 | } | ||
265 | EXPORT_SYMBOL_GPL(device_set_wakeup_enable); | ||
35 | 266 | ||
36 | /* | 267 | /* |
37 | * The functions below use the observation that each wakeup event starts a | 268 | * The functions below use the observation that each wakeup event starts a |
@@ -55,118 +286,259 @@ static unsigned long events_timer_expires; | |||
55 | * knowledge, however, may not be available to it, so it can simply specify time | 286 | * knowledge, however, may not be available to it, so it can simply specify time |
56 | * to wait before the system can be suspended and pass it as the second | 287 | * to wait before the system can be suspended and pass it as the second |
57 | * argument of pm_wakeup_event(). | 288 | * argument of pm_wakeup_event(). |
289 | * | ||
290 | * It is valid to call pm_relax() after pm_wakeup_event(), in which case the | ||
291 | * "no suspend" period will be ended either by the pm_relax(), or by the timer | ||
292 | * function executed when the timer expires, whichever comes first. | ||
58 | */ | 293 | */ |
59 | 294 | ||
60 | /** | 295 | /** |
296 | * wakup_source_activate - Mark given wakeup source as active. | ||
297 | * @ws: Wakeup source to handle. | ||
298 | * | ||
299 | * Update the @ws' statistics and, if @ws has just been activated, notify the PM | ||
300 | * core of the event by incrementing the counter of of wakeup events being | ||
301 | * processed. | ||
302 | */ | ||
303 | static void wakeup_source_activate(struct wakeup_source *ws) | ||
304 | { | ||
305 | ws->active = true; | ||
306 | ws->active_count++; | ||
307 | ws->timer_expires = jiffies; | ||
308 | ws->last_time = ktime_get(); | ||
309 | |||
310 | atomic_inc(&events_in_progress); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * __pm_stay_awake - Notify the PM core of a wakeup event. | ||
315 | * @ws: Wakeup source object associated with the source of the event. | ||
316 | * | ||
317 | * It is safe to call this function from interrupt context. | ||
318 | */ | ||
319 | void __pm_stay_awake(struct wakeup_source *ws) | ||
320 | { | ||
321 | unsigned long flags; | ||
322 | |||
323 | if (!ws) | ||
324 | return; | ||
325 | |||
326 | spin_lock_irqsave(&ws->lock, flags); | ||
327 | ws->event_count++; | ||
328 | if (!ws->active) | ||
329 | wakeup_source_activate(ws); | ||
330 | spin_unlock_irqrestore(&ws->lock, flags); | ||
331 | } | ||
332 | EXPORT_SYMBOL_GPL(__pm_stay_awake); | ||
333 | |||
334 | /** | ||
61 | * pm_stay_awake - Notify the PM core that a wakeup event is being processed. | 335 | * pm_stay_awake - Notify the PM core that a wakeup event is being processed. |
62 | * @dev: Device the wakeup event is related to. | 336 | * @dev: Device the wakeup event is related to. |
63 | * | 337 | * |
64 | * Notify the PM core of a wakeup event (signaled by @dev) by incrementing the | 338 | * Notify the PM core of a wakeup event (signaled by @dev) by calling |
65 | * counter of wakeup events being processed. If @dev is not NULL, the counter | 339 | * __pm_stay_awake for the @dev's wakeup source object. |
66 | * of wakeup events related to @dev is incremented too. | ||
67 | * | 340 | * |
68 | * Call this function after detecting of a wakeup event if pm_relax() is going | 341 | * Call this function after detecting of a wakeup event if pm_relax() is going |
69 | * to be called directly after processing the event (and possibly passing it to | 342 | * to be called directly after processing the event (and possibly passing it to |
70 | * user space for further processing). | 343 | * user space for further processing). |
71 | * | ||
72 | * It is safe to call this function from interrupt context. | ||
73 | */ | 344 | */ |
74 | void pm_stay_awake(struct device *dev) | 345 | void pm_stay_awake(struct device *dev) |
75 | { | 346 | { |
76 | unsigned long flags; | 347 | unsigned long flags; |
77 | 348 | ||
78 | spin_lock_irqsave(&events_lock, flags); | 349 | if (!dev) |
79 | if (dev) | 350 | return; |
80 | dev->power.wakeup_count++; | ||
81 | 351 | ||
82 | events_in_progress++; | 352 | spin_lock_irqsave(&dev->power.lock, flags); |
83 | spin_unlock_irqrestore(&events_lock, flags); | 353 | __pm_stay_awake(dev->power.wakeup); |
354 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
84 | } | 355 | } |
356 | EXPORT_SYMBOL_GPL(pm_stay_awake); | ||
85 | 357 | ||
86 | /** | 358 | /** |
87 | * pm_relax - Notify the PM core that processing of a wakeup event has ended. | 359 | * wakup_source_deactivate - Mark given wakeup source as inactive. |
360 | * @ws: Wakeup source to handle. | ||
88 | * | 361 | * |
89 | * Notify the PM core that a wakeup event has been processed by decrementing | 362 | * Update the @ws' statistics and notify the PM core that the wakeup source has |
90 | * the counter of wakeup events being processed and incrementing the counter | 363 | * become inactive by decrementing the counter of wakeup events being processed |
91 | * of registered wakeup events. | 364 | * and incrementing the counter of registered wakeup events. |
365 | */ | ||
366 | static void wakeup_source_deactivate(struct wakeup_source *ws) | ||
367 | { | ||
368 | ktime_t duration; | ||
369 | ktime_t now; | ||
370 | |||
371 | ws->relax_count++; | ||
372 | /* | ||
373 | * __pm_relax() may be called directly or from a timer function. | ||
374 | * If it is called directly right after the timer function has been | ||
375 | * started, but before the timer function calls __pm_relax(), it is | ||
376 | * possible that __pm_stay_awake() will be called in the meantime and | ||
377 | * will set ws->active. Then, ws->active may be cleared immediately | ||
378 | * by the __pm_relax() called from the timer function, but in such a | ||
379 | * case ws->relax_count will be different from ws->active_count. | ||
380 | */ | ||
381 | if (ws->relax_count != ws->active_count) { | ||
382 | ws->relax_count--; | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | ws->active = false; | ||
387 | |||
388 | now = ktime_get(); | ||
389 | duration = ktime_sub(now, ws->last_time); | ||
390 | ws->total_time = ktime_add(ws->total_time, duration); | ||
391 | if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) | ||
392 | ws->max_time = duration; | ||
393 | |||
394 | del_timer(&ws->timer); | ||
395 | |||
396 | /* | ||
397 | * event_count has to be incremented before events_in_progress is | ||
398 | * modified, so that the callers of pm_check_wakeup_events() and | ||
399 | * pm_save_wakeup_count() don't see the old value of event_count and | ||
400 | * events_in_progress equal to zero at the same time. | ||
401 | */ | ||
402 | atomic_inc(&event_count); | ||
403 | smp_mb__before_atomic_dec(); | ||
404 | atomic_dec(&events_in_progress); | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * __pm_relax - Notify the PM core that processing of a wakeup event has ended. | ||
409 | * @ws: Wakeup source object associated with the source of the event. | ||
92 | * | 410 | * |
93 | * Call this function for wakeup events whose processing started with calling | 411 | * Call this function for wakeup events whose processing started with calling |
94 | * pm_stay_awake(). | 412 | * __pm_stay_awake(). |
95 | * | 413 | * |
96 | * It is safe to call it from interrupt context. | 414 | * It is safe to call it from interrupt context. |
97 | */ | 415 | */ |
98 | void pm_relax(void) | 416 | void __pm_relax(struct wakeup_source *ws) |
99 | { | 417 | { |
100 | unsigned long flags; | 418 | unsigned long flags; |
101 | 419 | ||
102 | spin_lock_irqsave(&events_lock, flags); | 420 | if (!ws) |
103 | if (events_in_progress) { | 421 | return; |
104 | events_in_progress--; | 422 | |
105 | event_count++; | 423 | spin_lock_irqsave(&ws->lock, flags); |
106 | } | 424 | if (ws->active) |
107 | spin_unlock_irqrestore(&events_lock, flags); | 425 | wakeup_source_deactivate(ws); |
426 | spin_unlock_irqrestore(&ws->lock, flags); | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(__pm_relax); | ||
429 | |||
430 | /** | ||
431 | * pm_relax - Notify the PM core that processing of a wakeup event has ended. | ||
432 | * @dev: Device that signaled the event. | ||
433 | * | ||
434 | * Execute __pm_relax() for the @dev's wakeup source object. | ||
435 | */ | ||
436 | void pm_relax(struct device *dev) | ||
437 | { | ||
438 | unsigned long flags; | ||
439 | |||
440 | if (!dev) | ||
441 | return; | ||
442 | |||
443 | spin_lock_irqsave(&dev->power.lock, flags); | ||
444 | __pm_relax(dev->power.wakeup); | ||
445 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
108 | } | 446 | } |
447 | EXPORT_SYMBOL_GPL(pm_relax); | ||
109 | 448 | ||
110 | /** | 449 | /** |
111 | * pm_wakeup_timer_fn - Delayed finalization of a wakeup event. | 450 | * pm_wakeup_timer_fn - Delayed finalization of a wakeup event. |
451 | * @data: Address of the wakeup source object associated with the event source. | ||
112 | * | 452 | * |
113 | * Decrease the counter of wakeup events being processed after it was increased | 453 | * Call __pm_relax() for the wakeup source whose address is stored in @data. |
114 | * by pm_wakeup_event(). | ||
115 | */ | 454 | */ |
116 | static void pm_wakeup_timer_fn(unsigned long data) | 455 | static void pm_wakeup_timer_fn(unsigned long data) |
117 | { | 456 | { |
457 | __pm_relax((struct wakeup_source *)data); | ||
458 | } | ||
459 | |||
460 | /** | ||
461 | * __pm_wakeup_event - Notify the PM core of a wakeup event. | ||
462 | * @ws: Wakeup source object associated with the event source. | ||
463 | * @msec: Anticipated event processing time (in milliseconds). | ||
464 | * | ||
465 | * Notify the PM core of a wakeup event whose source is @ws that will take | ||
466 | * approximately @msec milliseconds to be processed by the kernel. If @ws is | ||
467 | * not active, activate it. If @msec is nonzero, set up the @ws' timer to | ||
468 | * execute pm_wakeup_timer_fn() in future. | ||
469 | * | ||
470 | * It is safe to call this function from interrupt context. | ||
471 | */ | ||
472 | void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) | ||
473 | { | ||
118 | unsigned long flags; | 474 | unsigned long flags; |
475 | unsigned long expires; | ||
119 | 476 | ||
120 | spin_lock_irqsave(&events_lock, flags); | 477 | if (!ws) |
121 | if (events_timer_expires | 478 | return; |
122 | && time_before_eq(events_timer_expires, jiffies)) { | 479 | |
123 | events_in_progress--; | 480 | spin_lock_irqsave(&ws->lock, flags); |
124 | events_timer_expires = 0; | 481 | |
482 | ws->event_count++; | ||
483 | if (!ws->active) | ||
484 | wakeup_source_activate(ws); | ||
485 | |||
486 | if (!msec) { | ||
487 | wakeup_source_deactivate(ws); | ||
488 | goto unlock; | ||
125 | } | 489 | } |
126 | spin_unlock_irqrestore(&events_lock, flags); | 490 | |
491 | expires = jiffies + msecs_to_jiffies(msec); | ||
492 | if (!expires) | ||
493 | expires = 1; | ||
494 | |||
495 | if (time_after(expires, ws->timer_expires)) { | ||
496 | mod_timer(&ws->timer, expires); | ||
497 | ws->timer_expires = expires; | ||
498 | } | ||
499 | |||
500 | unlock: | ||
501 | spin_unlock_irqrestore(&ws->lock, flags); | ||
127 | } | 502 | } |
503 | EXPORT_SYMBOL_GPL(__pm_wakeup_event); | ||
504 | |||
128 | 505 | ||
129 | /** | 506 | /** |
130 | * pm_wakeup_event - Notify the PM core of a wakeup event. | 507 | * pm_wakeup_event - Notify the PM core of a wakeup event. |
131 | * @dev: Device the wakeup event is related to. | 508 | * @dev: Device the wakeup event is related to. |
132 | * @msec: Anticipated event processing time (in milliseconds). | 509 | * @msec: Anticipated event processing time (in milliseconds). |
133 | * | 510 | * |
134 | * Notify the PM core of a wakeup event (signaled by @dev) that will take | 511 | * Call __pm_wakeup_event() for the @dev's wakeup source object. |
135 | * approximately @msec milliseconds to be processed by the kernel. Increment | ||
136 | * the counter of registered wakeup events and (if @msec is nonzero) set up | ||
137 | * the wakeup events timer to execute pm_wakeup_timer_fn() in future (if the | ||
138 | * timer has not been set up already, increment the counter of wakeup events | ||
139 | * being processed). If @dev is not NULL, the counter of wakeup events related | ||
140 | * to @dev is incremented too. | ||
141 | * | ||
142 | * It is safe to call this function from interrupt context. | ||
143 | */ | 512 | */ |
144 | void pm_wakeup_event(struct device *dev, unsigned int msec) | 513 | void pm_wakeup_event(struct device *dev, unsigned int msec) |
145 | { | 514 | { |
146 | unsigned long flags; | 515 | unsigned long flags; |
147 | 516 | ||
148 | spin_lock_irqsave(&events_lock, flags); | 517 | if (!dev) |
149 | event_count++; | 518 | return; |
150 | if (dev) | ||
151 | dev->power.wakeup_count++; | ||
152 | |||
153 | if (msec) { | ||
154 | unsigned long expires; | ||
155 | 519 | ||
156 | expires = jiffies + msecs_to_jiffies(msec); | 520 | spin_lock_irqsave(&dev->power.lock, flags); |
157 | if (!expires) | 521 | __pm_wakeup_event(dev->power.wakeup, msec); |
158 | expires = 1; | 522 | spin_unlock_irqrestore(&dev->power.lock, flags); |
523 | } | ||
524 | EXPORT_SYMBOL_GPL(pm_wakeup_event); | ||
159 | 525 | ||
160 | if (!events_timer_expires | 526 | /** |
161 | || time_after(expires, events_timer_expires)) { | 527 | * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources. |
162 | if (!events_timer_expires) | 528 | */ |
163 | events_in_progress++; | 529 | static void pm_wakeup_update_hit_counts(void) |
530 | { | ||
531 | unsigned long flags; | ||
532 | struct wakeup_source *ws; | ||
164 | 533 | ||
165 | mod_timer(&events_timer, expires); | 534 | rcu_read_lock(); |
166 | events_timer_expires = expires; | 535 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) { |
167 | } | 536 | spin_lock_irqsave(&ws->lock, flags); |
537 | if (ws->active) | ||
538 | ws->hit_count++; | ||
539 | spin_unlock_irqrestore(&ws->lock, flags); | ||
168 | } | 540 | } |
169 | spin_unlock_irqrestore(&events_lock, flags); | 541 | rcu_read_unlock(); |
170 | } | 542 | } |
171 | 543 | ||
172 | /** | 544 | /** |
@@ -184,10 +556,13 @@ bool pm_check_wakeup_events(void) | |||
184 | 556 | ||
185 | spin_lock_irqsave(&events_lock, flags); | 557 | spin_lock_irqsave(&events_lock, flags); |
186 | if (events_check_enabled) { | 558 | if (events_check_enabled) { |
187 | ret = (event_count == saved_event_count) && !events_in_progress; | 559 | ret = ((unsigned int)atomic_read(&event_count) == saved_count) |
560 | && !atomic_read(&events_in_progress); | ||
188 | events_check_enabled = ret; | 561 | events_check_enabled = ret; |
189 | } | 562 | } |
190 | spin_unlock_irqrestore(&events_lock, flags); | 563 | spin_unlock_irqrestore(&events_lock, flags); |
564 | if (!ret) | ||
565 | pm_wakeup_update_hit_counts(); | ||
191 | return ret; | 566 | return ret; |
192 | } | 567 | } |
193 | 568 | ||
@@ -202,24 +577,20 @@ bool pm_check_wakeup_events(void) | |||
202 | * drop down to zero has been interrupted by a signal (and the current number | 577 | * drop down to zero has been interrupted by a signal (and the current number |
203 | * of wakeup events being processed is still nonzero). Otherwise return true. | 578 | * of wakeup events being processed is still nonzero). Otherwise return true. |
204 | */ | 579 | */ |
205 | bool pm_get_wakeup_count(unsigned long *count) | 580 | bool pm_get_wakeup_count(unsigned int *count) |
206 | { | 581 | { |
207 | bool ret; | 582 | bool ret; |
208 | 583 | ||
209 | spin_lock_irq(&events_lock); | ||
210 | if (capable(CAP_SYS_ADMIN)) | 584 | if (capable(CAP_SYS_ADMIN)) |
211 | events_check_enabled = false; | 585 | events_check_enabled = false; |
212 | 586 | ||
213 | while (events_in_progress && !signal_pending(current)) { | 587 | while (atomic_read(&events_in_progress) && !signal_pending(current)) { |
214 | spin_unlock_irq(&events_lock); | 588 | pm_wakeup_update_hit_counts(); |
215 | 589 | schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); | |
216 | schedule_timeout_interruptible(msecs_to_jiffies(100)); | ||
217 | |||
218 | spin_lock_irq(&events_lock); | ||
219 | } | 590 | } |
220 | *count = event_count; | 591 | |
221 | ret = !events_in_progress; | 592 | ret = !atomic_read(&events_in_progress); |
222 | spin_unlock_irq(&events_lock); | 593 | *count = atomic_read(&event_count); |
223 | return ret; | 594 | return ret; |
224 | } | 595 | } |
225 | 596 | ||
@@ -232,16 +603,102 @@ bool pm_get_wakeup_count(unsigned long *count) | |||
232 | * old number of registered wakeup events to be used by pm_check_wakeup_events() | 603 | * old number of registered wakeup events to be used by pm_check_wakeup_events() |
233 | * and return true. Otherwise return false. | 604 | * and return true. Otherwise return false. |
234 | */ | 605 | */ |
235 | bool pm_save_wakeup_count(unsigned long count) | 606 | bool pm_save_wakeup_count(unsigned int count) |
236 | { | 607 | { |
237 | bool ret = false; | 608 | bool ret = false; |
238 | 609 | ||
239 | spin_lock_irq(&events_lock); | 610 | spin_lock_irq(&events_lock); |
240 | if (count == event_count && !events_in_progress) { | 611 | if (count == (unsigned int)atomic_read(&event_count) |
241 | saved_event_count = count; | 612 | && !atomic_read(&events_in_progress)) { |
613 | saved_count = count; | ||
242 | events_check_enabled = true; | 614 | events_check_enabled = true; |
243 | ret = true; | 615 | ret = true; |
244 | } | 616 | } |
245 | spin_unlock_irq(&events_lock); | 617 | spin_unlock_irq(&events_lock); |
618 | if (!ret) | ||
619 | pm_wakeup_update_hit_counts(); | ||
620 | return ret; | ||
621 | } | ||
622 | |||
623 | static struct dentry *wakeup_sources_stats_dentry; | ||
624 | |||
625 | /** | ||
626 | * print_wakeup_source_stats - Print wakeup source statistics information. | ||
627 | * @m: seq_file to print the statistics into. | ||
628 | * @ws: Wakeup source object to print the statistics for. | ||
629 | */ | ||
630 | static int print_wakeup_source_stats(struct seq_file *m, | ||
631 | struct wakeup_source *ws) | ||
632 | { | ||
633 | unsigned long flags; | ||
634 | ktime_t total_time; | ||
635 | ktime_t max_time; | ||
636 | unsigned long active_count; | ||
637 | ktime_t active_time; | ||
638 | int ret; | ||
639 | |||
640 | spin_lock_irqsave(&ws->lock, flags); | ||
641 | |||
642 | total_time = ws->total_time; | ||
643 | max_time = ws->max_time; | ||
644 | active_count = ws->active_count; | ||
645 | if (ws->active) { | ||
646 | active_time = ktime_sub(ktime_get(), ws->last_time); | ||
647 | total_time = ktime_add(total_time, active_time); | ||
648 | if (active_time.tv64 > max_time.tv64) | ||
649 | max_time = active_time; | ||
650 | } else { | ||
651 | active_time = ktime_set(0, 0); | ||
652 | } | ||
653 | |||
654 | ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t" | ||
655 | "%lld\t\t%lld\t\t%lld\t\t%lld\n", | ||
656 | ws->name, active_count, ws->event_count, ws->hit_count, | ||
657 | ktime_to_ms(active_time), ktime_to_ms(total_time), | ||
658 | ktime_to_ms(max_time), ktime_to_ms(ws->last_time)); | ||
659 | |||
660 | spin_unlock_irqrestore(&ws->lock, flags); | ||
661 | |||
246 | return ret; | 662 | return ret; |
247 | } | 663 | } |
664 | |||
665 | /** | ||
666 | * wakeup_sources_stats_show - Print wakeup sources statistics information. | ||
667 | * @m: seq_file to print the statistics into. | ||
668 | */ | ||
669 | static int wakeup_sources_stats_show(struct seq_file *m, void *unused) | ||
670 | { | ||
671 | struct wakeup_source *ws; | ||
672 | |||
673 | seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t" | ||
674 | "active_since\ttotal_time\tmax_time\tlast_change\n"); | ||
675 | |||
676 | rcu_read_lock(); | ||
677 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) | ||
678 | print_wakeup_source_stats(m, ws); | ||
679 | rcu_read_unlock(); | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | static int wakeup_sources_stats_open(struct inode *inode, struct file *file) | ||
685 | { | ||
686 | return single_open(file, wakeup_sources_stats_show, NULL); | ||
687 | } | ||
688 | |||
689 | static const struct file_operations wakeup_sources_stats_fops = { | ||
690 | .owner = THIS_MODULE, | ||
691 | .open = wakeup_sources_stats_open, | ||
692 | .read = seq_read, | ||
693 | .llseek = seq_lseek, | ||
694 | .release = single_release, | ||
695 | }; | ||
696 | |||
697 | static int __init wakeup_sources_debugfs_init(void) | ||
698 | { | ||
699 | wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources", | ||
700 | S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops); | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | postcore_initcall(wakeup_sources_debugfs_init); | ||
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 9fc630ce1ddb..f6f37a05a0c3 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -45,7 +45,8 @@ static ssize_t show_##name(struct sys_device *dev, \ | |||
45 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | 45 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ |
46 | } | 46 | } |
47 | 47 | ||
48 | #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) | 48 | #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ |
49 | defined(topology_book_cpumask) | ||
49 | static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) | 50 | static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) |
50 | { | 51 | { |
51 | ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf; | 52 | ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf; |
@@ -114,6 +115,14 @@ define_siblings_show_func(core_cpumask); | |||
114 | define_one_ro_named(core_siblings, show_core_cpumask); | 115 | define_one_ro_named(core_siblings, show_core_cpumask); |
115 | define_one_ro_named(core_siblings_list, show_core_cpumask_list); | 116 | define_one_ro_named(core_siblings_list, show_core_cpumask_list); |
116 | 117 | ||
118 | #ifdef CONFIG_SCHED_BOOK | ||
119 | define_id_show_func(book_id); | ||
120 | define_one_ro(book_id); | ||
121 | define_siblings_show_func(book_cpumask); | ||
122 | define_one_ro_named(book_siblings, show_book_cpumask); | ||
123 | define_one_ro_named(book_siblings_list, show_book_cpumask_list); | ||
124 | #endif | ||
125 | |||
117 | static struct attribute *default_attrs[] = { | 126 | static struct attribute *default_attrs[] = { |
118 | &attr_physical_package_id.attr, | 127 | &attr_physical_package_id.attr, |
119 | &attr_core_id.attr, | 128 | &attr_core_id.attr, |
@@ -121,6 +130,11 @@ static struct attribute *default_attrs[] = { | |||
121 | &attr_thread_siblings_list.attr, | 130 | &attr_thread_siblings_list.attr, |
122 | &attr_core_siblings.attr, | 131 | &attr_core_siblings.attr, |
123 | &attr_core_siblings_list.attr, | 132 | &attr_core_siblings_list.attr, |
133 | #ifdef CONFIG_SCHED_BOOK | ||
134 | &attr_book_id.attr, | ||
135 | &attr_book_siblings.attr, | ||
136 | &attr_book_siblings_list.attr, | ||
137 | #endif | ||
124 | NULL | 138 | NULL |
125 | }; | 139 | }; |
126 | 140 | ||
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index de277689da61..4b9359a6f6ca 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -488,4 +488,21 @@ config BLK_DEV_HD | |||
488 | 488 | ||
489 | If unsure, say N. | 489 | If unsure, say N. |
490 | 490 | ||
491 | config BLK_DEV_RBD | ||
492 | tristate "Rados block device (RBD)" | ||
493 | depends on INET && EXPERIMENTAL && BLOCK | ||
494 | select CEPH_LIB | ||
495 | select LIBCRC32C | ||
496 | select CRYPTO_AES | ||
497 | select CRYPTO | ||
498 | default n | ||
499 | help | ||
500 | Say Y here if you want include the Rados block device, which stripes | ||
501 | a block device over objects stored in the Ceph distributed object | ||
502 | store. | ||
503 | |||
504 | More information at http://ceph.newdream.net/. | ||
505 | |||
506 | If unsure, say N. | ||
507 | |||
491 | endif # BLK_DEV | 508 | endif # BLK_DEV |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index aff5ac925c34..d7f463d6312d 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
@@ -37,5 +37,6 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o | |||
37 | 37 | ||
38 | obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o | 38 | obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o |
39 | obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ | 39 | obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ |
40 | obj-$(CONFIG_BLK_DEV_RBD) += rbd.o | ||
40 | 41 | ||
41 | swim_mod-objs := swim.o swim_asm.o | 42 | swim_mod-objs := swim.o swim_asm.o |
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index e9da874d0419..03688c2da319 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c | |||
@@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, | |||
113 | memcpy(buf, dev->bounce_buf+offset, size); | 113 | memcpy(buf, dev->bounce_buf+offset, size); |
114 | offset += size; | 114 | offset += size; |
115 | flush_kernel_dcache_page(bvec->bv_page); | 115 | flush_kernel_dcache_page(bvec->bv_page); |
116 | bvec_kunmap_irq(bvec, &flags); | 116 | bvec_kunmap_irq(buf, &flags); |
117 | i++; | 117 | i++; |
118 | } | 118 | } |
119 | } | 119 | } |
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c new file mode 100644 index 000000000000..6ec9d53806c5 --- /dev/null +++ b/drivers/block/rbd.c | |||
@@ -0,0 +1,1841 @@ | |||
1 | /* | ||
2 | rbd.c -- Export ceph rados objects as a Linux block device | ||
3 | |||
4 | |||
5 | based on drivers/block/osdblk.c: | ||
6 | |||
7 | Copyright 2009 Red Hat, Inc. | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; see the file COPYING. If not, write to | ||
20 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | |||
23 | |||
24 | Instructions for use | ||
25 | -------------------- | ||
26 | |||
27 | 1) Map a Linux block device to an existing rbd image. | ||
28 | |||
29 | Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name] | ||
30 | |||
31 | $ echo "192.168.0.1 name=admin rbd foo" > /sys/class/rbd/add | ||
32 | |||
33 | The snapshot name can be "-" or omitted to map the image read/write. | ||
34 | |||
35 | 2) List all active blkdev<->object mappings. | ||
36 | |||
37 | In this example, we have performed step #1 twice, creating two blkdevs, | ||
38 | mapped to two separate rados objects in the rados rbd pool | ||
39 | |||
40 | $ cat /sys/class/rbd/list | ||
41 | #id major client_name pool name snap KB | ||
42 | 0 254 client4143 rbd foo - 1024000 | ||
43 | |||
44 | The columns, in order, are: | ||
45 | - blkdev unique id | ||
46 | - blkdev assigned major | ||
47 | - rados client id | ||
48 | - rados pool name | ||
49 | - rados block device name | ||
50 | - mapped snapshot ("-" if none) | ||
51 | - device size in KB | ||
52 | |||
53 | |||
54 | 3) Create a snapshot. | ||
55 | |||
56 | Usage: <blkdev id> <snapname> | ||
57 | |||
58 | $ echo "0 mysnap" > /sys/class/rbd/snap_create | ||
59 | |||
60 | |||
61 | 4) Listing a snapshot. | ||
62 | |||
63 | $ cat /sys/class/rbd/snaps_list | ||
64 | #id snap KB | ||
65 | 0 - 1024000 (*) | ||
66 | 0 foo 1024000 | ||
67 | |||
68 | The columns, in order, are: | ||
69 | - blkdev unique id | ||
70 | - snapshot name, '-' means none (active read/write version) | ||
71 | - size of device at time of snapshot | ||
72 | - the (*) indicates this is the active version | ||
73 | |||
74 | 5) Rollback to snapshot. | ||
75 | |||
76 | Usage: <blkdev id> <snapname> | ||
77 | |||
78 | $ echo "0 mysnap" > /sys/class/rbd/snap_rollback | ||
79 | |||
80 | |||
81 | 6) Mapping an image using snapshot. | ||
82 | |||
83 | A snapshot mapping is read-only. This is being done by passing | ||
84 | snap=<snapname> to the options when adding a device. | ||
85 | |||
86 | $ echo "192.168.0.1 name=admin,snap=mysnap rbd foo" > /sys/class/rbd/add | ||
87 | |||
88 | |||
89 | 7) Remove an active blkdev<->rbd image mapping. | ||
90 | |||
91 | In this example, we remove the mapping with blkdev unique id 1. | ||
92 | |||
93 | $ echo 1 > /sys/class/rbd/remove | ||
94 | |||
95 | |||
96 | NOTE: The actual creation and deletion of rados objects is outside the scope | ||
97 | of this driver. | ||
98 | |||
99 | */ | ||
100 | |||
101 | #include <linux/ceph/libceph.h> | ||
102 | #include <linux/ceph/osd_client.h> | ||
103 | #include <linux/ceph/mon_client.h> | ||
104 | #include <linux/ceph/decode.h> | ||
105 | |||
106 | #include <linux/kernel.h> | ||
107 | #include <linux/device.h> | ||
108 | #include <linux/module.h> | ||
109 | #include <linux/fs.h> | ||
110 | #include <linux/blkdev.h> | ||
111 | |||
112 | #include "rbd_types.h" | ||
113 | |||
114 | #define DRV_NAME "rbd" | ||
115 | #define DRV_NAME_LONG "rbd (rados block device)" | ||
116 | |||
117 | #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ | ||
118 | |||
119 | #define RBD_MAX_MD_NAME_LEN (96 + sizeof(RBD_SUFFIX)) | ||
120 | #define RBD_MAX_POOL_NAME_LEN 64 | ||
121 | #define RBD_MAX_SNAP_NAME_LEN 32 | ||
122 | #define RBD_MAX_OPT_LEN 1024 | ||
123 | |||
124 | #define RBD_SNAP_HEAD_NAME "-" | ||
125 | |||
126 | #define DEV_NAME_LEN 32 | ||
127 | |||
128 | /* | ||
129 | * block device image metadata (in-memory version) | ||
130 | */ | ||
131 | struct rbd_image_header { | ||
132 | u64 image_size; | ||
133 | char block_name[32]; | ||
134 | __u8 obj_order; | ||
135 | __u8 crypt_type; | ||
136 | __u8 comp_type; | ||
137 | struct rw_semaphore snap_rwsem; | ||
138 | struct ceph_snap_context *snapc; | ||
139 | size_t snap_names_len; | ||
140 | u64 snap_seq; | ||
141 | u32 total_snaps; | ||
142 | |||
143 | char *snap_names; | ||
144 | u64 *snap_sizes; | ||
145 | }; | ||
146 | |||
147 | /* | ||
148 | * an instance of the client. multiple devices may share a client. | ||
149 | */ | ||
150 | struct rbd_client { | ||
151 | struct ceph_client *client; | ||
152 | struct kref kref; | ||
153 | struct list_head node; | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * a single io request | ||
158 | */ | ||
159 | struct rbd_request { | ||
160 | struct request *rq; /* blk layer request */ | ||
161 | struct bio *bio; /* cloned bio */ | ||
162 | struct page **pages; /* list of used pages */ | ||
163 | u64 len; | ||
164 | }; | ||
165 | |||
166 | /* | ||
167 | * a single device | ||
168 | */ | ||
169 | struct rbd_device { | ||
170 | int id; /* blkdev unique id */ | ||
171 | |||
172 | int major; /* blkdev assigned major */ | ||
173 | struct gendisk *disk; /* blkdev's gendisk and rq */ | ||
174 | struct request_queue *q; | ||
175 | |||
176 | struct ceph_client *client; | ||
177 | struct rbd_client *rbd_client; | ||
178 | |||
179 | char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */ | ||
180 | |||
181 | spinlock_t lock; /* queue lock */ | ||
182 | |||
183 | struct rbd_image_header header; | ||
184 | char obj[RBD_MAX_OBJ_NAME_LEN]; /* rbd image name */ | ||
185 | int obj_len; | ||
186 | char obj_md_name[RBD_MAX_MD_NAME_LEN]; /* hdr nm. */ | ||
187 | char pool_name[RBD_MAX_POOL_NAME_LEN]; | ||
188 | int poolid; | ||
189 | |||
190 | char snap_name[RBD_MAX_SNAP_NAME_LEN]; | ||
191 | u32 cur_snap; /* index+1 of current snapshot within snap context | ||
192 | 0 - for the head */ | ||
193 | int read_only; | ||
194 | |||
195 | struct list_head node; | ||
196 | }; | ||
197 | |||
198 | static spinlock_t node_lock; /* protects client get/put */ | ||
199 | |||
200 | static struct class *class_rbd; /* /sys/class/rbd */ | ||
201 | static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ | ||
202 | static LIST_HEAD(rbd_dev_list); /* devices */ | ||
203 | static LIST_HEAD(rbd_client_list); /* clients */ | ||
204 | |||
205 | |||
206 | static int rbd_open(struct block_device *bdev, fmode_t mode) | ||
207 | { | ||
208 | struct gendisk *disk = bdev->bd_disk; | ||
209 | struct rbd_device *rbd_dev = disk->private_data; | ||
210 | |||
211 | set_device_ro(bdev, rbd_dev->read_only); | ||
212 | |||
213 | if ((mode & FMODE_WRITE) && rbd_dev->read_only) | ||
214 | return -EROFS; | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static const struct block_device_operations rbd_bd_ops = { | ||
220 | .owner = THIS_MODULE, | ||
221 | .open = rbd_open, | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * Initialize an rbd client instance. | ||
226 | * We own *opt. | ||
227 | */ | ||
228 | static struct rbd_client *rbd_client_create(struct ceph_options *opt) | ||
229 | { | ||
230 | struct rbd_client *rbdc; | ||
231 | int ret = -ENOMEM; | ||
232 | |||
233 | dout("rbd_client_create\n"); | ||
234 | rbdc = kmalloc(sizeof(struct rbd_client), GFP_KERNEL); | ||
235 | if (!rbdc) | ||
236 | goto out_opt; | ||
237 | |||
238 | kref_init(&rbdc->kref); | ||
239 | INIT_LIST_HEAD(&rbdc->node); | ||
240 | |||
241 | rbdc->client = ceph_create_client(opt, rbdc); | ||
242 | if (IS_ERR(rbdc->client)) | ||
243 | goto out_rbdc; | ||
244 | opt = NULL; /* Now rbdc->client is responsible for opt */ | ||
245 | |||
246 | ret = ceph_open_session(rbdc->client); | ||
247 | if (ret < 0) | ||
248 | goto out_err; | ||
249 | |||
250 | spin_lock(&node_lock); | ||
251 | list_add_tail(&rbdc->node, &rbd_client_list); | ||
252 | spin_unlock(&node_lock); | ||
253 | |||
254 | dout("rbd_client_create created %p\n", rbdc); | ||
255 | return rbdc; | ||
256 | |||
257 | out_err: | ||
258 | ceph_destroy_client(rbdc->client); | ||
259 | out_rbdc: | ||
260 | kfree(rbdc); | ||
261 | out_opt: | ||
262 | if (opt) | ||
263 | ceph_destroy_options(opt); | ||
264 | return ERR_PTR(ret); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Find a ceph client with specific addr and configuration. | ||
269 | */ | ||
270 | static struct rbd_client *__rbd_client_find(struct ceph_options *opt) | ||
271 | { | ||
272 | struct rbd_client *client_node; | ||
273 | |||
274 | if (opt->flags & CEPH_OPT_NOSHARE) | ||
275 | return NULL; | ||
276 | |||
277 | list_for_each_entry(client_node, &rbd_client_list, node) | ||
278 | if (ceph_compare_options(opt, client_node->client) == 0) | ||
279 | return client_node; | ||
280 | return NULL; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * Get a ceph client with specific addr and configuration, if one does | ||
285 | * not exist create it. | ||
286 | */ | ||
287 | static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr, | ||
288 | char *options) | ||
289 | { | ||
290 | struct rbd_client *rbdc; | ||
291 | struct ceph_options *opt; | ||
292 | int ret; | ||
293 | |||
294 | ret = ceph_parse_options(&opt, options, mon_addr, | ||
295 | mon_addr + strlen(mon_addr), NULL, NULL); | ||
296 | if (ret < 0) | ||
297 | return ret; | ||
298 | |||
299 | spin_lock(&node_lock); | ||
300 | rbdc = __rbd_client_find(opt); | ||
301 | if (rbdc) { | ||
302 | ceph_destroy_options(opt); | ||
303 | |||
304 | /* using an existing client */ | ||
305 | kref_get(&rbdc->kref); | ||
306 | rbd_dev->rbd_client = rbdc; | ||
307 | rbd_dev->client = rbdc->client; | ||
308 | spin_unlock(&node_lock); | ||
309 | return 0; | ||
310 | } | ||
311 | spin_unlock(&node_lock); | ||
312 | |||
313 | rbdc = rbd_client_create(opt); | ||
314 | if (IS_ERR(rbdc)) | ||
315 | return PTR_ERR(rbdc); | ||
316 | |||
317 | rbd_dev->rbd_client = rbdc; | ||
318 | rbd_dev->client = rbdc->client; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Destroy ceph client | ||
324 | */ | ||
325 | static void rbd_client_release(struct kref *kref) | ||
326 | { | ||
327 | struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); | ||
328 | |||
329 | dout("rbd_release_client %p\n", rbdc); | ||
330 | spin_lock(&node_lock); | ||
331 | list_del(&rbdc->node); | ||
332 | spin_unlock(&node_lock); | ||
333 | |||
334 | ceph_destroy_client(rbdc->client); | ||
335 | kfree(rbdc); | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * Drop reference to ceph client node. If it's not referenced anymore, release | ||
340 | * it. | ||
341 | */ | ||
342 | static void rbd_put_client(struct rbd_device *rbd_dev) | ||
343 | { | ||
344 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); | ||
345 | rbd_dev->rbd_client = NULL; | ||
346 | rbd_dev->client = NULL; | ||
347 | } | ||
348 | |||
349 | |||
350 | /* | ||
351 | * Create a new header structure, translate header format from the on-disk | ||
352 | * header. | ||
353 | */ | ||
354 | static int rbd_header_from_disk(struct rbd_image_header *header, | ||
355 | struct rbd_image_header_ondisk *ondisk, | ||
356 | int allocated_snaps, | ||
357 | gfp_t gfp_flags) | ||
358 | { | ||
359 | int i; | ||
360 | u32 snap_count = le32_to_cpu(ondisk->snap_count); | ||
361 | int ret = -ENOMEM; | ||
362 | |||
363 | init_rwsem(&header->snap_rwsem); | ||
364 | |||
365 | header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); | ||
366 | header->snapc = kmalloc(sizeof(struct ceph_snap_context) + | ||
367 | snap_count * | ||
368 | sizeof(struct rbd_image_snap_ondisk), | ||
369 | gfp_flags); | ||
370 | if (!header->snapc) | ||
371 | return -ENOMEM; | ||
372 | if (snap_count) { | ||
373 | header->snap_names = kmalloc(header->snap_names_len, | ||
374 | GFP_KERNEL); | ||
375 | if (!header->snap_names) | ||
376 | goto err_snapc; | ||
377 | header->snap_sizes = kmalloc(snap_count * sizeof(u64), | ||
378 | GFP_KERNEL); | ||
379 | if (!header->snap_sizes) | ||
380 | goto err_names; | ||
381 | } else { | ||
382 | header->snap_names = NULL; | ||
383 | header->snap_sizes = NULL; | ||
384 | } | ||
385 | memcpy(header->block_name, ondisk->block_name, | ||
386 | sizeof(ondisk->block_name)); | ||
387 | |||
388 | header->image_size = le64_to_cpu(ondisk->image_size); | ||
389 | header->obj_order = ondisk->options.order; | ||
390 | header->crypt_type = ondisk->options.crypt_type; | ||
391 | header->comp_type = ondisk->options.comp_type; | ||
392 | |||
393 | atomic_set(&header->snapc->nref, 1); | ||
394 | header->snap_seq = le64_to_cpu(ondisk->snap_seq); | ||
395 | header->snapc->num_snaps = snap_count; | ||
396 | header->total_snaps = snap_count; | ||
397 | |||
398 | if (snap_count && | ||
399 | allocated_snaps == snap_count) { | ||
400 | for (i = 0; i < snap_count; i++) { | ||
401 | header->snapc->snaps[i] = | ||
402 | le64_to_cpu(ondisk->snaps[i].id); | ||
403 | header->snap_sizes[i] = | ||
404 | le64_to_cpu(ondisk->snaps[i].image_size); | ||
405 | } | ||
406 | |||
407 | /* copy snapshot names */ | ||
408 | memcpy(header->snap_names, &ondisk->snaps[i], | ||
409 | header->snap_names_len); | ||
410 | } | ||
411 | |||
412 | return 0; | ||
413 | |||
414 | err_names: | ||
415 | kfree(header->snap_names); | ||
416 | err_snapc: | ||
417 | kfree(header->snapc); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | static int snap_index(struct rbd_image_header *header, int snap_num) | ||
422 | { | ||
423 | return header->total_snaps - snap_num; | ||
424 | } | ||
425 | |||
426 | static u64 cur_snap_id(struct rbd_device *rbd_dev) | ||
427 | { | ||
428 | struct rbd_image_header *header = &rbd_dev->header; | ||
429 | |||
430 | if (!rbd_dev->cur_snap) | ||
431 | return 0; | ||
432 | |||
433 | return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)]; | ||
434 | } | ||
435 | |||
436 | static int snap_by_name(struct rbd_image_header *header, const char *snap_name, | ||
437 | u64 *seq, u64 *size) | ||
438 | { | ||
439 | int i; | ||
440 | char *p = header->snap_names; | ||
441 | |||
442 | for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) { | ||
443 | if (strcmp(snap_name, p) == 0) | ||
444 | break; | ||
445 | } | ||
446 | if (i == header->total_snaps) | ||
447 | return -ENOENT; | ||
448 | if (seq) | ||
449 | *seq = header->snapc->snaps[i]; | ||
450 | |||
451 | if (size) | ||
452 | *size = header->snap_sizes[i]; | ||
453 | |||
454 | return i; | ||
455 | } | ||
456 | |||
457 | static int rbd_header_set_snap(struct rbd_device *dev, | ||
458 | const char *snap_name, | ||
459 | u64 *size) | ||
460 | { | ||
461 | struct rbd_image_header *header = &dev->header; | ||
462 | struct ceph_snap_context *snapc = header->snapc; | ||
463 | int ret = -ENOENT; | ||
464 | |||
465 | down_write(&header->snap_rwsem); | ||
466 | |||
467 | if (!snap_name || | ||
468 | !*snap_name || | ||
469 | strcmp(snap_name, "-") == 0 || | ||
470 | strcmp(snap_name, RBD_SNAP_HEAD_NAME) == 0) { | ||
471 | if (header->total_snaps) | ||
472 | snapc->seq = header->snap_seq; | ||
473 | else | ||
474 | snapc->seq = 0; | ||
475 | dev->cur_snap = 0; | ||
476 | dev->read_only = 0; | ||
477 | if (size) | ||
478 | *size = header->image_size; | ||
479 | } else { | ||
480 | ret = snap_by_name(header, snap_name, &snapc->seq, size); | ||
481 | if (ret < 0) | ||
482 | goto done; | ||
483 | |||
484 | dev->cur_snap = header->total_snaps - ret; | ||
485 | dev->read_only = 1; | ||
486 | } | ||
487 | |||
488 | ret = 0; | ||
489 | done: | ||
490 | up_write(&header->snap_rwsem); | ||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | static void rbd_header_free(struct rbd_image_header *header) | ||
495 | { | ||
496 | kfree(header->snapc); | ||
497 | kfree(header->snap_names); | ||
498 | kfree(header->snap_sizes); | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * get the actual striped segment name, offset and length | ||
503 | */ | ||
504 | static u64 rbd_get_segment(struct rbd_image_header *header, | ||
505 | const char *block_name, | ||
506 | u64 ofs, u64 len, | ||
507 | char *seg_name, u64 *segofs) | ||
508 | { | ||
509 | u64 seg = ofs >> header->obj_order; | ||
510 | |||
511 | if (seg_name) | ||
512 | snprintf(seg_name, RBD_MAX_SEG_NAME_LEN, | ||
513 | "%s.%012llx", block_name, seg); | ||
514 | |||
515 | ofs = ofs & ((1 << header->obj_order) - 1); | ||
516 | len = min_t(u64, len, (1 << header->obj_order) - ofs); | ||
517 | |||
518 | if (segofs) | ||
519 | *segofs = ofs; | ||
520 | |||
521 | return len; | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * bio helpers | ||
526 | */ | ||
527 | |||
528 | static void bio_chain_put(struct bio *chain) | ||
529 | { | ||
530 | struct bio *tmp; | ||
531 | |||
532 | while (chain) { | ||
533 | tmp = chain; | ||
534 | chain = chain->bi_next; | ||
535 | bio_put(tmp); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | /* | ||
540 | * zeros a bio chain, starting at specific offset | ||
541 | */ | ||
542 | static void zero_bio_chain(struct bio *chain, int start_ofs) | ||
543 | { | ||
544 | struct bio_vec *bv; | ||
545 | unsigned long flags; | ||
546 | void *buf; | ||
547 | int i; | ||
548 | int pos = 0; | ||
549 | |||
550 | while (chain) { | ||
551 | bio_for_each_segment(bv, chain, i) { | ||
552 | if (pos + bv->bv_len > start_ofs) { | ||
553 | int remainder = max(start_ofs - pos, 0); | ||
554 | buf = bvec_kmap_irq(bv, &flags); | ||
555 | memset(buf + remainder, 0, | ||
556 | bv->bv_len - remainder); | ||
557 | bvec_kunmap_irq(buf, &flags); | ||
558 | } | ||
559 | pos += bv->bv_len; | ||
560 | } | ||
561 | |||
562 | chain = chain->bi_next; | ||
563 | } | ||
564 | } | ||
565 | |||
566 | /* | ||
567 | * bio_chain_clone - clone a chain of bios up to a certain length. | ||
568 | * might return a bio_pair that will need to be released. | ||
569 | */ | ||
570 | static struct bio *bio_chain_clone(struct bio **old, struct bio **next, | ||
571 | struct bio_pair **bp, | ||
572 | int len, gfp_t gfpmask) | ||
573 | { | ||
574 | struct bio *tmp, *old_chain = *old, *new_chain = NULL, *tail = NULL; | ||
575 | int total = 0; | ||
576 | |||
577 | if (*bp) { | ||
578 | bio_pair_release(*bp); | ||
579 | *bp = NULL; | ||
580 | } | ||
581 | |||
582 | while (old_chain && (total < len)) { | ||
583 | tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); | ||
584 | if (!tmp) | ||
585 | goto err_out; | ||
586 | |||
587 | if (total + old_chain->bi_size > len) { | ||
588 | struct bio_pair *bp; | ||
589 | |||
590 | /* | ||
591 | * this split can only happen with a single paged bio, | ||
592 | * split_bio will BUG_ON if this is not the case | ||
593 | */ | ||
594 | dout("bio_chain_clone split! total=%d remaining=%d" | ||
595 | "bi_size=%d\n", | ||
596 | (int)total, (int)len-total, | ||
597 | (int)old_chain->bi_size); | ||
598 | |||
599 | /* split the bio. We'll release it either in the next | ||
600 | call, or it will have to be released outside */ | ||
601 | bp = bio_split(old_chain, (len - total) / 512ULL); | ||
602 | if (!bp) | ||
603 | goto err_out; | ||
604 | |||
605 | __bio_clone(tmp, &bp->bio1); | ||
606 | |||
607 | *next = &bp->bio2; | ||
608 | } else { | ||
609 | __bio_clone(tmp, old_chain); | ||
610 | *next = old_chain->bi_next; | ||
611 | } | ||
612 | |||
613 | tmp->bi_bdev = NULL; | ||
614 | gfpmask &= ~__GFP_WAIT; | ||
615 | tmp->bi_next = NULL; | ||
616 | |||
617 | if (!new_chain) { | ||
618 | new_chain = tail = tmp; | ||
619 | } else { | ||
620 | tail->bi_next = tmp; | ||
621 | tail = tmp; | ||
622 | } | ||
623 | old_chain = old_chain->bi_next; | ||
624 | |||
625 | total += tmp->bi_size; | ||
626 | } | ||
627 | |||
628 | BUG_ON(total < len); | ||
629 | |||
630 | if (tail) | ||
631 | tail->bi_next = NULL; | ||
632 | |||
633 | *old = old_chain; | ||
634 | |||
635 | return new_chain; | ||
636 | |||
637 | err_out: | ||
638 | dout("bio_chain_clone with err\n"); | ||
639 | bio_chain_put(new_chain); | ||
640 | return NULL; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * helpers for osd request op vectors. | ||
645 | */ | ||
646 | static int rbd_create_rw_ops(struct ceph_osd_req_op **ops, | ||
647 | int num_ops, | ||
648 | int opcode, | ||
649 | u32 payload_len) | ||
650 | { | ||
651 | *ops = kzalloc(sizeof(struct ceph_osd_req_op) * (num_ops + 1), | ||
652 | GFP_NOIO); | ||
653 | if (!*ops) | ||
654 | return -ENOMEM; | ||
655 | (*ops)[0].op = opcode; | ||
656 | /* | ||
657 | * op extent offset and length will be set later on | ||
658 | * in calc_raw_layout() | ||
659 | */ | ||
660 | (*ops)[0].payload_len = payload_len; | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static void rbd_destroy_ops(struct ceph_osd_req_op *ops) | ||
665 | { | ||
666 | kfree(ops); | ||
667 | } | ||
668 | |||
669 | /* | ||
670 | * Send ceph osd request | ||
671 | */ | ||
672 | static int rbd_do_request(struct request *rq, | ||
673 | struct rbd_device *dev, | ||
674 | struct ceph_snap_context *snapc, | ||
675 | u64 snapid, | ||
676 | const char *obj, u64 ofs, u64 len, | ||
677 | struct bio *bio, | ||
678 | struct page **pages, | ||
679 | int num_pages, | ||
680 | int flags, | ||
681 | struct ceph_osd_req_op *ops, | ||
682 | int num_reply, | ||
683 | void (*rbd_cb)(struct ceph_osd_request *req, | ||
684 | struct ceph_msg *msg)) | ||
685 | { | ||
686 | struct ceph_osd_request *req; | ||
687 | struct ceph_file_layout *layout; | ||
688 | int ret; | ||
689 | u64 bno; | ||
690 | struct timespec mtime = CURRENT_TIME; | ||
691 | struct rbd_request *req_data; | ||
692 | struct ceph_osd_request_head *reqhead; | ||
693 | struct rbd_image_header *header = &dev->header; | ||
694 | |||
695 | ret = -ENOMEM; | ||
696 | req_data = kzalloc(sizeof(*req_data), GFP_NOIO); | ||
697 | if (!req_data) | ||
698 | goto done; | ||
699 | |||
700 | dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs); | ||
701 | |||
702 | down_read(&header->snap_rwsem); | ||
703 | |||
704 | req = ceph_osdc_alloc_request(&dev->client->osdc, flags, | ||
705 | snapc, | ||
706 | ops, | ||
707 | false, | ||
708 | GFP_NOIO, pages, bio); | ||
709 | if (IS_ERR(req)) { | ||
710 | up_read(&header->snap_rwsem); | ||
711 | ret = PTR_ERR(req); | ||
712 | goto done_pages; | ||
713 | } | ||
714 | |||
715 | req->r_callback = rbd_cb; | ||
716 | |||
717 | req_data->rq = rq; | ||
718 | req_data->bio = bio; | ||
719 | req_data->pages = pages; | ||
720 | req_data->len = len; | ||
721 | |||
722 | req->r_priv = req_data; | ||
723 | |||
724 | reqhead = req->r_request->front.iov_base; | ||
725 | reqhead->snapid = cpu_to_le64(CEPH_NOSNAP); | ||
726 | |||
727 | strncpy(req->r_oid, obj, sizeof(req->r_oid)); | ||
728 | req->r_oid_len = strlen(req->r_oid); | ||
729 | |||
730 | layout = &req->r_file_layout; | ||
731 | memset(layout, 0, sizeof(*layout)); | ||
732 | layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | ||
733 | layout->fl_stripe_count = cpu_to_le32(1); | ||
734 | layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | ||
735 | layout->fl_pg_preferred = cpu_to_le32(-1); | ||
736 | layout->fl_pg_pool = cpu_to_le32(dev->poolid); | ||
737 | ceph_calc_raw_layout(&dev->client->osdc, layout, snapid, | ||
738 | ofs, &len, &bno, req, ops); | ||
739 | |||
740 | ceph_osdc_build_request(req, ofs, &len, | ||
741 | ops, | ||
742 | snapc, | ||
743 | &mtime, | ||
744 | req->r_oid, req->r_oid_len); | ||
745 | up_read(&header->snap_rwsem); | ||
746 | |||
747 | ret = ceph_osdc_start_request(&dev->client->osdc, req, false); | ||
748 | if (ret < 0) | ||
749 | goto done_err; | ||
750 | |||
751 | if (!rbd_cb) { | ||
752 | ret = ceph_osdc_wait_request(&dev->client->osdc, req); | ||
753 | ceph_osdc_put_request(req); | ||
754 | } | ||
755 | return ret; | ||
756 | |||
757 | done_err: | ||
758 | bio_chain_put(req_data->bio); | ||
759 | ceph_osdc_put_request(req); | ||
760 | done_pages: | ||
761 | kfree(req_data); | ||
762 | done: | ||
763 | if (rq) | ||
764 | blk_end_request(rq, ret, len); | ||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * Ceph osd op callback | ||
770 | */ | ||
771 | static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg) | ||
772 | { | ||
773 | struct rbd_request *req_data = req->r_priv; | ||
774 | struct ceph_osd_reply_head *replyhead; | ||
775 | struct ceph_osd_op *op; | ||
776 | __s32 rc; | ||
777 | u64 bytes; | ||
778 | int read_op; | ||
779 | |||
780 | /* parse reply */ | ||
781 | replyhead = msg->front.iov_base; | ||
782 | WARN_ON(le32_to_cpu(replyhead->num_ops) == 0); | ||
783 | op = (void *)(replyhead + 1); | ||
784 | rc = le32_to_cpu(replyhead->result); | ||
785 | bytes = le64_to_cpu(op->extent.length); | ||
786 | read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ); | ||
787 | |||
788 | dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc); | ||
789 | |||
790 | if (rc == -ENOENT && read_op) { | ||
791 | zero_bio_chain(req_data->bio, 0); | ||
792 | rc = 0; | ||
793 | } else if (rc == 0 && read_op && bytes < req_data->len) { | ||
794 | zero_bio_chain(req_data->bio, bytes); | ||
795 | bytes = req_data->len; | ||
796 | } | ||
797 | |||
798 | blk_end_request(req_data->rq, rc, bytes); | ||
799 | |||
800 | if (req_data->bio) | ||
801 | bio_chain_put(req_data->bio); | ||
802 | |||
803 | ceph_osdc_put_request(req); | ||
804 | kfree(req_data); | ||
805 | } | ||
806 | |||
807 | /* | ||
808 | * Do a synchronous ceph osd operation | ||
809 | */ | ||
810 | static int rbd_req_sync_op(struct rbd_device *dev, | ||
811 | struct ceph_snap_context *snapc, | ||
812 | u64 snapid, | ||
813 | int opcode, | ||
814 | int flags, | ||
815 | struct ceph_osd_req_op *orig_ops, | ||
816 | int num_reply, | ||
817 | const char *obj, | ||
818 | u64 ofs, u64 len, | ||
819 | char *buf) | ||
820 | { | ||
821 | int ret; | ||
822 | struct page **pages; | ||
823 | int num_pages; | ||
824 | struct ceph_osd_req_op *ops = orig_ops; | ||
825 | u32 payload_len; | ||
826 | |||
827 | num_pages = calc_pages_for(ofs , len); | ||
828 | pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL); | ||
829 | if (IS_ERR(pages)) | ||
830 | return PTR_ERR(pages); | ||
831 | |||
832 | if (!orig_ops) { | ||
833 | payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0); | ||
834 | ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len); | ||
835 | if (ret < 0) | ||
836 | goto done; | ||
837 | |||
838 | if ((flags & CEPH_OSD_FLAG_WRITE) && buf) { | ||
839 | ret = ceph_copy_to_page_vector(pages, buf, ofs, len); | ||
840 | if (ret < 0) | ||
841 | goto done_ops; | ||
842 | } | ||
843 | } | ||
844 | |||
845 | ret = rbd_do_request(NULL, dev, snapc, snapid, | ||
846 | obj, ofs, len, NULL, | ||
847 | pages, num_pages, | ||
848 | flags, | ||
849 | ops, | ||
850 | 2, | ||
851 | NULL); | ||
852 | if (ret < 0) | ||
853 | goto done_ops; | ||
854 | |||
855 | if ((flags & CEPH_OSD_FLAG_READ) && buf) | ||
856 | ret = ceph_copy_from_page_vector(pages, buf, ofs, ret); | ||
857 | |||
858 | done_ops: | ||
859 | if (!orig_ops) | ||
860 | rbd_destroy_ops(ops); | ||
861 | done: | ||
862 | ceph_release_page_vector(pages, num_pages); | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Do an asynchronous ceph osd operation | ||
868 | */ | ||
869 | static int rbd_do_op(struct request *rq, | ||
870 | struct rbd_device *rbd_dev , | ||
871 | struct ceph_snap_context *snapc, | ||
872 | u64 snapid, | ||
873 | int opcode, int flags, int num_reply, | ||
874 | u64 ofs, u64 len, | ||
875 | struct bio *bio) | ||
876 | { | ||
877 | char *seg_name; | ||
878 | u64 seg_ofs; | ||
879 | u64 seg_len; | ||
880 | int ret; | ||
881 | struct ceph_osd_req_op *ops; | ||
882 | u32 payload_len; | ||
883 | |||
884 | seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); | ||
885 | if (!seg_name) | ||
886 | return -ENOMEM; | ||
887 | |||
888 | seg_len = rbd_get_segment(&rbd_dev->header, | ||
889 | rbd_dev->header.block_name, | ||
890 | ofs, len, | ||
891 | seg_name, &seg_ofs); | ||
892 | |||
893 | payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0); | ||
894 | |||
895 | ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len); | ||
896 | if (ret < 0) | ||
897 | goto done; | ||
898 | |||
899 | /* we've taken care of segment sizes earlier when we | ||
900 | cloned the bios. We should never have a segment | ||
901 | truncated at this point */ | ||
902 | BUG_ON(seg_len < len); | ||
903 | |||
904 | ret = rbd_do_request(rq, rbd_dev, snapc, snapid, | ||
905 | seg_name, seg_ofs, seg_len, | ||
906 | bio, | ||
907 | NULL, 0, | ||
908 | flags, | ||
909 | ops, | ||
910 | num_reply, | ||
911 | rbd_req_cb); | ||
912 | done: | ||
913 | kfree(seg_name); | ||
914 | return ret; | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * Request async osd write | ||
919 | */ | ||
920 | static int rbd_req_write(struct request *rq, | ||
921 | struct rbd_device *rbd_dev, | ||
922 | struct ceph_snap_context *snapc, | ||
923 | u64 ofs, u64 len, | ||
924 | struct bio *bio) | ||
925 | { | ||
926 | return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, | ||
927 | CEPH_OSD_OP_WRITE, | ||
928 | CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, | ||
929 | 2, | ||
930 | ofs, len, bio); | ||
931 | } | ||
932 | |||
933 | /* | ||
934 | * Request async osd read | ||
935 | */ | ||
936 | static int rbd_req_read(struct request *rq, | ||
937 | struct rbd_device *rbd_dev, | ||
938 | u64 snapid, | ||
939 | u64 ofs, u64 len, | ||
940 | struct bio *bio) | ||
941 | { | ||
942 | return rbd_do_op(rq, rbd_dev, NULL, | ||
943 | (snapid ? snapid : CEPH_NOSNAP), | ||
944 | CEPH_OSD_OP_READ, | ||
945 | CEPH_OSD_FLAG_READ, | ||
946 | 2, | ||
947 | ofs, len, bio); | ||
948 | } | ||
949 | |||
950 | /* | ||
951 | * Request sync osd read | ||
952 | */ | ||
953 | static int rbd_req_sync_read(struct rbd_device *dev, | ||
954 | struct ceph_snap_context *snapc, | ||
955 | u64 snapid, | ||
956 | const char *obj, | ||
957 | u64 ofs, u64 len, | ||
958 | char *buf) | ||
959 | { | ||
960 | return rbd_req_sync_op(dev, NULL, | ||
961 | (snapid ? snapid : CEPH_NOSNAP), | ||
962 | CEPH_OSD_OP_READ, | ||
963 | CEPH_OSD_FLAG_READ, | ||
964 | NULL, | ||
965 | 1, obj, ofs, len, buf); | ||
966 | } | ||
967 | |||
968 | /* | ||
969 | * Request sync osd read | ||
970 | */ | ||
971 | static int rbd_req_sync_rollback_obj(struct rbd_device *dev, | ||
972 | u64 snapid, | ||
973 | const char *obj) | ||
974 | { | ||
975 | struct ceph_osd_req_op *ops; | ||
976 | int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0); | ||
977 | if (ret < 0) | ||
978 | return ret; | ||
979 | |||
980 | ops[0].snap.snapid = snapid; | ||
981 | |||
982 | ret = rbd_req_sync_op(dev, NULL, | ||
983 | CEPH_NOSNAP, | ||
984 | 0, | ||
985 | CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, | ||
986 | ops, | ||
987 | 1, obj, 0, 0, NULL); | ||
988 | |||
989 | rbd_destroy_ops(ops); | ||
990 | |||
991 | if (ret < 0) | ||
992 | return ret; | ||
993 | |||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | /* | ||
998 | * Request sync osd read | ||
999 | */ | ||
1000 | static int rbd_req_sync_exec(struct rbd_device *dev, | ||
1001 | const char *obj, | ||
1002 | const char *cls, | ||
1003 | const char *method, | ||
1004 | const char *data, | ||
1005 | int len) | ||
1006 | { | ||
1007 | struct ceph_osd_req_op *ops; | ||
1008 | int cls_len = strlen(cls); | ||
1009 | int method_len = strlen(method); | ||
1010 | int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_CALL, | ||
1011 | cls_len + method_len + len); | ||
1012 | if (ret < 0) | ||
1013 | return ret; | ||
1014 | |||
1015 | ops[0].cls.class_name = cls; | ||
1016 | ops[0].cls.class_len = (__u8)cls_len; | ||
1017 | ops[0].cls.method_name = method; | ||
1018 | ops[0].cls.method_len = (__u8)method_len; | ||
1019 | ops[0].cls.argc = 0; | ||
1020 | ops[0].cls.indata = data; | ||
1021 | ops[0].cls.indata_len = len; | ||
1022 | |||
1023 | ret = rbd_req_sync_op(dev, NULL, | ||
1024 | CEPH_NOSNAP, | ||
1025 | 0, | ||
1026 | CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, | ||
1027 | ops, | ||
1028 | 1, obj, 0, 0, NULL); | ||
1029 | |||
1030 | rbd_destroy_ops(ops); | ||
1031 | |||
1032 | dout("cls_exec returned %d\n", ret); | ||
1033 | return ret; | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
1037 | * block device queue callback | ||
1038 | */ | ||
1039 | static void rbd_rq_fn(struct request_queue *q) | ||
1040 | { | ||
1041 | struct rbd_device *rbd_dev = q->queuedata; | ||
1042 | struct request *rq; | ||
1043 | struct bio_pair *bp = NULL; | ||
1044 | |||
1045 | rq = blk_fetch_request(q); | ||
1046 | |||
1047 | while (1) { | ||
1048 | struct bio *bio; | ||
1049 | struct bio *rq_bio, *next_bio = NULL; | ||
1050 | bool do_write; | ||
1051 | int size, op_size = 0; | ||
1052 | u64 ofs; | ||
1053 | |||
1054 | /* peek at request from block layer */ | ||
1055 | if (!rq) | ||
1056 | break; | ||
1057 | |||
1058 | dout("fetched request\n"); | ||
1059 | |||
1060 | /* filter out block requests we don't understand */ | ||
1061 | if ((rq->cmd_type != REQ_TYPE_FS)) { | ||
1062 | __blk_end_request_all(rq, 0); | ||
1063 | goto next; | ||
1064 | } | ||
1065 | |||
1066 | /* deduce our operation (read, write) */ | ||
1067 | do_write = (rq_data_dir(rq) == WRITE); | ||
1068 | |||
1069 | size = blk_rq_bytes(rq); | ||
1070 | ofs = blk_rq_pos(rq) * 512ULL; | ||
1071 | rq_bio = rq->bio; | ||
1072 | if (do_write && rbd_dev->read_only) { | ||
1073 | __blk_end_request_all(rq, -EROFS); | ||
1074 | goto next; | ||
1075 | } | ||
1076 | |||
1077 | spin_unlock_irq(q->queue_lock); | ||
1078 | |||
1079 | dout("%s 0x%x bytes at 0x%llx\n", | ||
1080 | do_write ? "write" : "read", | ||
1081 | size, blk_rq_pos(rq) * 512ULL); | ||
1082 | |||
1083 | do { | ||
1084 | /* a bio clone to be passed down to OSD req */ | ||
1085 | dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); | ||
1086 | op_size = rbd_get_segment(&rbd_dev->header, | ||
1087 | rbd_dev->header.block_name, | ||
1088 | ofs, size, | ||
1089 | NULL, NULL); | ||
1090 | bio = bio_chain_clone(&rq_bio, &next_bio, &bp, | ||
1091 | op_size, GFP_ATOMIC); | ||
1092 | if (!bio) { | ||
1093 | spin_lock_irq(q->queue_lock); | ||
1094 | __blk_end_request_all(rq, -ENOMEM); | ||
1095 | goto next; | ||
1096 | } | ||
1097 | |||
1098 | /* init OSD command: write or read */ | ||
1099 | if (do_write) | ||
1100 | rbd_req_write(rq, rbd_dev, | ||
1101 | rbd_dev->header.snapc, | ||
1102 | ofs, | ||
1103 | op_size, bio); | ||
1104 | else | ||
1105 | rbd_req_read(rq, rbd_dev, | ||
1106 | cur_snap_id(rbd_dev), | ||
1107 | ofs, | ||
1108 | op_size, bio); | ||
1109 | |||
1110 | size -= op_size; | ||
1111 | ofs += op_size; | ||
1112 | |||
1113 | rq_bio = next_bio; | ||
1114 | } while (size > 0); | ||
1115 | |||
1116 | if (bp) | ||
1117 | bio_pair_release(bp); | ||
1118 | |||
1119 | spin_lock_irq(q->queue_lock); | ||
1120 | next: | ||
1121 | rq = blk_fetch_request(q); | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | /* | ||
1126 | * a queue callback. Makes sure that we don't create a bio that spans across | ||
1127 | * multiple osd objects. One exception would be with a single page bios, | ||
1128 | * which we handle later at bio_chain_clone | ||
1129 | */ | ||
1130 | static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd, | ||
1131 | struct bio_vec *bvec) | ||
1132 | { | ||
1133 | struct rbd_device *rbd_dev = q->queuedata; | ||
1134 | unsigned int chunk_sectors = 1 << (rbd_dev->header.obj_order - 9); | ||
1135 | sector_t sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev); | ||
1136 | unsigned int bio_sectors = bmd->bi_size >> 9; | ||
1137 | int max; | ||
1138 | |||
1139 | max = (chunk_sectors - ((sector & (chunk_sectors - 1)) | ||
1140 | + bio_sectors)) << 9; | ||
1141 | if (max < 0) | ||
1142 | max = 0; /* bio_add cannot handle a negative return */ | ||
1143 | if (max <= bvec->bv_len && bio_sectors == 0) | ||
1144 | return bvec->bv_len; | ||
1145 | return max; | ||
1146 | } | ||
1147 | |||
1148 | static void rbd_free_disk(struct rbd_device *rbd_dev) | ||
1149 | { | ||
1150 | struct gendisk *disk = rbd_dev->disk; | ||
1151 | |||
1152 | if (!disk) | ||
1153 | return; | ||
1154 | |||
1155 | rbd_header_free(&rbd_dev->header); | ||
1156 | |||
1157 | if (disk->flags & GENHD_FL_UP) | ||
1158 | del_gendisk(disk); | ||
1159 | if (disk->queue) | ||
1160 | blk_cleanup_queue(disk->queue); | ||
1161 | put_disk(disk); | ||
1162 | } | ||
1163 | |||
1164 | /* | ||
1165 | * reload the ondisk the header | ||
1166 | */ | ||
1167 | static int rbd_read_header(struct rbd_device *rbd_dev, | ||
1168 | struct rbd_image_header *header) | ||
1169 | { | ||
1170 | ssize_t rc; | ||
1171 | struct rbd_image_header_ondisk *dh; | ||
1172 | int snap_count = 0; | ||
1173 | u64 snap_names_len = 0; | ||
1174 | |||
1175 | while (1) { | ||
1176 | int len = sizeof(*dh) + | ||
1177 | snap_count * sizeof(struct rbd_image_snap_ondisk) + | ||
1178 | snap_names_len; | ||
1179 | |||
1180 | rc = -ENOMEM; | ||
1181 | dh = kmalloc(len, GFP_KERNEL); | ||
1182 | if (!dh) | ||
1183 | return -ENOMEM; | ||
1184 | |||
1185 | rc = rbd_req_sync_read(rbd_dev, | ||
1186 | NULL, CEPH_NOSNAP, | ||
1187 | rbd_dev->obj_md_name, | ||
1188 | 0, len, | ||
1189 | (char *)dh); | ||
1190 | if (rc < 0) | ||
1191 | goto out_dh; | ||
1192 | |||
1193 | rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL); | ||
1194 | if (rc < 0) | ||
1195 | goto out_dh; | ||
1196 | |||
1197 | if (snap_count != header->total_snaps) { | ||
1198 | snap_count = header->total_snaps; | ||
1199 | snap_names_len = header->snap_names_len; | ||
1200 | rbd_header_free(header); | ||
1201 | kfree(dh); | ||
1202 | continue; | ||
1203 | } | ||
1204 | break; | ||
1205 | } | ||
1206 | |||
1207 | out_dh: | ||
1208 | kfree(dh); | ||
1209 | return rc; | ||
1210 | } | ||
1211 | |||
1212 | /* | ||
1213 | * create a snapshot | ||
1214 | */ | ||
1215 | static int rbd_header_add_snap(struct rbd_device *dev, | ||
1216 | const char *snap_name, | ||
1217 | gfp_t gfp_flags) | ||
1218 | { | ||
1219 | int name_len = strlen(snap_name); | ||
1220 | u64 new_snapid; | ||
1221 | int ret; | ||
1222 | void *data, *data_start, *data_end; | ||
1223 | |||
1224 | /* we should create a snapshot only if we're pointing at the head */ | ||
1225 | if (dev->cur_snap) | ||
1226 | return -EINVAL; | ||
1227 | |||
1228 | ret = ceph_monc_create_snapid(&dev->client->monc, dev->poolid, | ||
1229 | &new_snapid); | ||
1230 | dout("created snapid=%lld\n", new_snapid); | ||
1231 | if (ret < 0) | ||
1232 | return ret; | ||
1233 | |||
1234 | data = kmalloc(name_len + 16, gfp_flags); | ||
1235 | if (!data) | ||
1236 | return -ENOMEM; | ||
1237 | |||
1238 | data_start = data; | ||
1239 | data_end = data + name_len + 16; | ||
1240 | |||
1241 | ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad); | ||
1242 | ceph_encode_64_safe(&data, data_end, new_snapid, bad); | ||
1243 | |||
1244 | ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add", | ||
1245 | data_start, data - data_start); | ||
1246 | |||
1247 | kfree(data_start); | ||
1248 | |||
1249 | if (ret < 0) | ||
1250 | return ret; | ||
1251 | |||
1252 | dev->header.snapc->seq = new_snapid; | ||
1253 | |||
1254 | return 0; | ||
1255 | bad: | ||
1256 | return -ERANGE; | ||
1257 | } | ||
1258 | |||
1259 | /* | ||
1260 | * only read the first part of the ondisk header, without the snaps info | ||
1261 | */ | ||
1262 | static int rbd_update_snaps(struct rbd_device *rbd_dev) | ||
1263 | { | ||
1264 | int ret; | ||
1265 | struct rbd_image_header h; | ||
1266 | u64 snap_seq; | ||
1267 | |||
1268 | ret = rbd_read_header(rbd_dev, &h); | ||
1269 | if (ret < 0) | ||
1270 | return ret; | ||
1271 | |||
1272 | down_write(&rbd_dev->header.snap_rwsem); | ||
1273 | |||
1274 | snap_seq = rbd_dev->header.snapc->seq; | ||
1275 | |||
1276 | kfree(rbd_dev->header.snapc); | ||
1277 | kfree(rbd_dev->header.snap_names); | ||
1278 | kfree(rbd_dev->header.snap_sizes); | ||
1279 | |||
1280 | rbd_dev->header.total_snaps = h.total_snaps; | ||
1281 | rbd_dev->header.snapc = h.snapc; | ||
1282 | rbd_dev->header.snap_names = h.snap_names; | ||
1283 | rbd_dev->header.snap_sizes = h.snap_sizes; | ||
1284 | rbd_dev->header.snapc->seq = snap_seq; | ||
1285 | |||
1286 | up_write(&rbd_dev->header.snap_rwsem); | ||
1287 | |||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static int rbd_init_disk(struct rbd_device *rbd_dev) | ||
1292 | { | ||
1293 | struct gendisk *disk; | ||
1294 | struct request_queue *q; | ||
1295 | int rc; | ||
1296 | u64 total_size = 0; | ||
1297 | |||
1298 | /* contact OSD, request size info about the object being mapped */ | ||
1299 | rc = rbd_read_header(rbd_dev, &rbd_dev->header); | ||
1300 | if (rc) | ||
1301 | return rc; | ||
1302 | |||
1303 | rc = rbd_header_set_snap(rbd_dev, rbd_dev->snap_name, &total_size); | ||
1304 | if (rc) | ||
1305 | return rc; | ||
1306 | |||
1307 | /* create gendisk info */ | ||
1308 | rc = -ENOMEM; | ||
1309 | disk = alloc_disk(RBD_MINORS_PER_MAJOR); | ||
1310 | if (!disk) | ||
1311 | goto out; | ||
1312 | |||
1313 | sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id); | ||
1314 | disk->major = rbd_dev->major; | ||
1315 | disk->first_minor = 0; | ||
1316 | disk->fops = &rbd_bd_ops; | ||
1317 | disk->private_data = rbd_dev; | ||
1318 | |||
1319 | /* init rq */ | ||
1320 | rc = -ENOMEM; | ||
1321 | q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock); | ||
1322 | if (!q) | ||
1323 | goto out_disk; | ||
1324 | blk_queue_merge_bvec(q, rbd_merge_bvec); | ||
1325 | disk->queue = q; | ||
1326 | |||
1327 | q->queuedata = rbd_dev; | ||
1328 | |||
1329 | rbd_dev->disk = disk; | ||
1330 | rbd_dev->q = q; | ||
1331 | |||
1332 | /* finally, announce the disk to the world */ | ||
1333 | set_capacity(disk, total_size / 512ULL); | ||
1334 | add_disk(disk); | ||
1335 | |||
1336 | pr_info("%s: added with size 0x%llx\n", | ||
1337 | disk->disk_name, (unsigned long long)total_size); | ||
1338 | return 0; | ||
1339 | |||
1340 | out_disk: | ||
1341 | put_disk(disk); | ||
1342 | out: | ||
1343 | return rc; | ||
1344 | } | ||
1345 | |||
1346 | /******************************************************************** | ||
1347 | * /sys/class/rbd/ | ||
1348 | * add map rados objects to blkdev | ||
1349 | * remove unmap rados objects | ||
1350 | * list show mappings | ||
1351 | *******************************************************************/ | ||
1352 | |||
1353 | static void class_rbd_release(struct class *cls) | ||
1354 | { | ||
1355 | kfree(cls); | ||
1356 | } | ||
1357 | |||
1358 | static ssize_t class_rbd_list(struct class *c, | ||
1359 | struct class_attribute *attr, | ||
1360 | char *data) | ||
1361 | { | ||
1362 | int n = 0; | ||
1363 | struct list_head *tmp; | ||
1364 | int max = PAGE_SIZE; | ||
1365 | |||
1366 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1367 | |||
1368 | n += snprintf(data, max, | ||
1369 | "#id\tmajor\tclient_name\tpool\tname\tsnap\tKB\n"); | ||
1370 | |||
1371 | list_for_each(tmp, &rbd_dev_list) { | ||
1372 | struct rbd_device *rbd_dev; | ||
1373 | |||
1374 | rbd_dev = list_entry(tmp, struct rbd_device, node); | ||
1375 | n += snprintf(data+n, max-n, | ||
1376 | "%d\t%d\tclient%lld\t%s\t%s\t%s\t%lld\n", | ||
1377 | rbd_dev->id, | ||
1378 | rbd_dev->major, | ||
1379 | ceph_client_id(rbd_dev->client), | ||
1380 | rbd_dev->pool_name, | ||
1381 | rbd_dev->obj, rbd_dev->snap_name, | ||
1382 | rbd_dev->header.image_size >> 10); | ||
1383 | if (n == max) | ||
1384 | break; | ||
1385 | } | ||
1386 | |||
1387 | mutex_unlock(&ctl_mutex); | ||
1388 | return n; | ||
1389 | } | ||
1390 | |||
1391 | static ssize_t class_rbd_add(struct class *c, | ||
1392 | struct class_attribute *attr, | ||
1393 | const char *buf, size_t count) | ||
1394 | { | ||
1395 | struct ceph_osd_client *osdc; | ||
1396 | struct rbd_device *rbd_dev; | ||
1397 | ssize_t rc = -ENOMEM; | ||
1398 | int irc, new_id = 0; | ||
1399 | struct list_head *tmp; | ||
1400 | char *mon_dev_name; | ||
1401 | char *options; | ||
1402 | |||
1403 | if (!try_module_get(THIS_MODULE)) | ||
1404 | return -ENODEV; | ||
1405 | |||
1406 | mon_dev_name = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL); | ||
1407 | if (!mon_dev_name) | ||
1408 | goto err_out_mod; | ||
1409 | |||
1410 | options = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL); | ||
1411 | if (!options) | ||
1412 | goto err_mon_dev; | ||
1413 | |||
1414 | /* new rbd_device object */ | ||
1415 | rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL); | ||
1416 | if (!rbd_dev) | ||
1417 | goto err_out_opt; | ||
1418 | |||
1419 | /* static rbd_device initialization */ | ||
1420 | spin_lock_init(&rbd_dev->lock); | ||
1421 | INIT_LIST_HEAD(&rbd_dev->node); | ||
1422 | |||
1423 | /* generate unique id: find highest unique id, add one */ | ||
1424 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1425 | |||
1426 | list_for_each(tmp, &rbd_dev_list) { | ||
1427 | struct rbd_device *rbd_dev; | ||
1428 | |||
1429 | rbd_dev = list_entry(tmp, struct rbd_device, node); | ||
1430 | if (rbd_dev->id >= new_id) | ||
1431 | new_id = rbd_dev->id + 1; | ||
1432 | } | ||
1433 | |||
1434 | rbd_dev->id = new_id; | ||
1435 | |||
1436 | /* add to global list */ | ||
1437 | list_add_tail(&rbd_dev->node, &rbd_dev_list); | ||
1438 | |||
1439 | /* parse add command */ | ||
1440 | if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s " | ||
1441 | "%" __stringify(RBD_MAX_OPT_LEN) "s " | ||
1442 | "%" __stringify(RBD_MAX_POOL_NAME_LEN) "s " | ||
1443 | "%" __stringify(RBD_MAX_OBJ_NAME_LEN) "s" | ||
1444 | "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s", | ||
1445 | mon_dev_name, options, rbd_dev->pool_name, | ||
1446 | rbd_dev->obj, rbd_dev->snap_name) < 4) { | ||
1447 | rc = -EINVAL; | ||
1448 | goto err_out_slot; | ||
1449 | } | ||
1450 | |||
1451 | if (rbd_dev->snap_name[0] == 0) | ||
1452 | rbd_dev->snap_name[0] = '-'; | ||
1453 | |||
1454 | rbd_dev->obj_len = strlen(rbd_dev->obj); | ||
1455 | snprintf(rbd_dev->obj_md_name, sizeof(rbd_dev->obj_md_name), "%s%s", | ||
1456 | rbd_dev->obj, RBD_SUFFIX); | ||
1457 | |||
1458 | /* initialize rest of new object */ | ||
1459 | snprintf(rbd_dev->name, DEV_NAME_LEN, DRV_NAME "%d", rbd_dev->id); | ||
1460 | rc = rbd_get_client(rbd_dev, mon_dev_name, options); | ||
1461 | if (rc < 0) | ||
1462 | goto err_out_slot; | ||
1463 | |||
1464 | mutex_unlock(&ctl_mutex); | ||
1465 | |||
1466 | /* pick the pool */ | ||
1467 | osdc = &rbd_dev->client->osdc; | ||
1468 | rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name); | ||
1469 | if (rc < 0) | ||
1470 | goto err_out_client; | ||
1471 | rbd_dev->poolid = rc; | ||
1472 | |||
1473 | /* register our block device */ | ||
1474 | irc = register_blkdev(0, rbd_dev->name); | ||
1475 | if (irc < 0) { | ||
1476 | rc = irc; | ||
1477 | goto err_out_client; | ||
1478 | } | ||
1479 | rbd_dev->major = irc; | ||
1480 | |||
1481 | /* set up and announce blkdev mapping */ | ||
1482 | rc = rbd_init_disk(rbd_dev); | ||
1483 | if (rc) | ||
1484 | goto err_out_blkdev; | ||
1485 | |||
1486 | return count; | ||
1487 | |||
1488 | err_out_blkdev: | ||
1489 | unregister_blkdev(rbd_dev->major, rbd_dev->name); | ||
1490 | err_out_client: | ||
1491 | rbd_put_client(rbd_dev); | ||
1492 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1493 | err_out_slot: | ||
1494 | list_del_init(&rbd_dev->node); | ||
1495 | mutex_unlock(&ctl_mutex); | ||
1496 | |||
1497 | kfree(rbd_dev); | ||
1498 | err_out_opt: | ||
1499 | kfree(options); | ||
1500 | err_mon_dev: | ||
1501 | kfree(mon_dev_name); | ||
1502 | err_out_mod: | ||
1503 | dout("Error adding device %s\n", buf); | ||
1504 | module_put(THIS_MODULE); | ||
1505 | return rc; | ||
1506 | } | ||
1507 | |||
1508 | static struct rbd_device *__rbd_get_dev(unsigned long id) | ||
1509 | { | ||
1510 | struct list_head *tmp; | ||
1511 | struct rbd_device *rbd_dev; | ||
1512 | |||
1513 | list_for_each(tmp, &rbd_dev_list) { | ||
1514 | rbd_dev = list_entry(tmp, struct rbd_device, node); | ||
1515 | if (rbd_dev->id == id) | ||
1516 | return rbd_dev; | ||
1517 | } | ||
1518 | return NULL; | ||
1519 | } | ||
1520 | |||
1521 | static ssize_t class_rbd_remove(struct class *c, | ||
1522 | struct class_attribute *attr, | ||
1523 | const char *buf, | ||
1524 | size_t count) | ||
1525 | { | ||
1526 | struct rbd_device *rbd_dev = NULL; | ||
1527 | int target_id, rc; | ||
1528 | unsigned long ul; | ||
1529 | |||
1530 | rc = strict_strtoul(buf, 10, &ul); | ||
1531 | if (rc) | ||
1532 | return rc; | ||
1533 | |||
1534 | /* convert to int; abort if we lost anything in the conversion */ | ||
1535 | target_id = (int) ul; | ||
1536 | if (target_id != ul) | ||
1537 | return -EINVAL; | ||
1538 | |||
1539 | /* remove object from list immediately */ | ||
1540 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1541 | |||
1542 | rbd_dev = __rbd_get_dev(target_id); | ||
1543 | if (rbd_dev) | ||
1544 | list_del_init(&rbd_dev->node); | ||
1545 | |||
1546 | mutex_unlock(&ctl_mutex); | ||
1547 | |||
1548 | if (!rbd_dev) | ||
1549 | return -ENOENT; | ||
1550 | |||
1551 | rbd_put_client(rbd_dev); | ||
1552 | |||
1553 | /* clean up and free blkdev */ | ||
1554 | rbd_free_disk(rbd_dev); | ||
1555 | unregister_blkdev(rbd_dev->major, rbd_dev->name); | ||
1556 | kfree(rbd_dev); | ||
1557 | |||
1558 | /* release module ref */ | ||
1559 | module_put(THIS_MODULE); | ||
1560 | |||
1561 | return count; | ||
1562 | } | ||
1563 | |||
1564 | static ssize_t class_rbd_snaps_list(struct class *c, | ||
1565 | struct class_attribute *attr, | ||
1566 | char *data) | ||
1567 | { | ||
1568 | struct rbd_device *rbd_dev = NULL; | ||
1569 | struct list_head *tmp; | ||
1570 | struct rbd_image_header *header; | ||
1571 | int i, n = 0, max = PAGE_SIZE; | ||
1572 | int ret; | ||
1573 | |||
1574 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1575 | |||
1576 | n += snprintf(data, max, "#id\tsnap\tKB\n"); | ||
1577 | |||
1578 | list_for_each(tmp, &rbd_dev_list) { | ||
1579 | char *names, *p; | ||
1580 | struct ceph_snap_context *snapc; | ||
1581 | |||
1582 | rbd_dev = list_entry(tmp, struct rbd_device, node); | ||
1583 | header = &rbd_dev->header; | ||
1584 | |||
1585 | down_read(&header->snap_rwsem); | ||
1586 | |||
1587 | names = header->snap_names; | ||
1588 | snapc = header->snapc; | ||
1589 | |||
1590 | n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n", | ||
1591 | rbd_dev->id, RBD_SNAP_HEAD_NAME, | ||
1592 | header->image_size >> 10, | ||
1593 | (!rbd_dev->cur_snap ? " (*)" : "")); | ||
1594 | if (n == max) | ||
1595 | break; | ||
1596 | |||
1597 | p = names; | ||
1598 | for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) { | ||
1599 | n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n", | ||
1600 | rbd_dev->id, p, header->snap_sizes[i] >> 10, | ||
1601 | (rbd_dev->cur_snap && | ||
1602 | (snap_index(header, i) == rbd_dev->cur_snap) ? | ||
1603 | " (*)" : "")); | ||
1604 | if (n == max) | ||
1605 | break; | ||
1606 | } | ||
1607 | |||
1608 | up_read(&header->snap_rwsem); | ||
1609 | } | ||
1610 | |||
1611 | |||
1612 | ret = n; | ||
1613 | mutex_unlock(&ctl_mutex); | ||
1614 | return ret; | ||
1615 | } | ||
1616 | |||
1617 | static ssize_t class_rbd_snaps_refresh(struct class *c, | ||
1618 | struct class_attribute *attr, | ||
1619 | const char *buf, | ||
1620 | size_t count) | ||
1621 | { | ||
1622 | struct rbd_device *rbd_dev = NULL; | ||
1623 | int target_id, rc; | ||
1624 | unsigned long ul; | ||
1625 | int ret = count; | ||
1626 | |||
1627 | rc = strict_strtoul(buf, 10, &ul); | ||
1628 | if (rc) | ||
1629 | return rc; | ||
1630 | |||
1631 | /* convert to int; abort if we lost anything in the conversion */ | ||
1632 | target_id = (int) ul; | ||
1633 | if (target_id != ul) | ||
1634 | return -EINVAL; | ||
1635 | |||
1636 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1637 | |||
1638 | rbd_dev = __rbd_get_dev(target_id); | ||
1639 | if (!rbd_dev) { | ||
1640 | ret = -ENOENT; | ||
1641 | goto done; | ||
1642 | } | ||
1643 | |||
1644 | rc = rbd_update_snaps(rbd_dev); | ||
1645 | if (rc < 0) | ||
1646 | ret = rc; | ||
1647 | |||
1648 | done: | ||
1649 | mutex_unlock(&ctl_mutex); | ||
1650 | return ret; | ||
1651 | } | ||
1652 | |||
1653 | static ssize_t class_rbd_snap_create(struct class *c, | ||
1654 | struct class_attribute *attr, | ||
1655 | const char *buf, | ||
1656 | size_t count) | ||
1657 | { | ||
1658 | struct rbd_device *rbd_dev = NULL; | ||
1659 | int target_id, ret; | ||
1660 | char *name; | ||
1661 | |||
1662 | name = kmalloc(RBD_MAX_SNAP_NAME_LEN + 1, GFP_KERNEL); | ||
1663 | if (!name) | ||
1664 | return -ENOMEM; | ||
1665 | |||
1666 | /* parse snaps add command */ | ||
1667 | if (sscanf(buf, "%d " | ||
1668 | "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s", | ||
1669 | &target_id, | ||
1670 | name) != 2) { | ||
1671 | ret = -EINVAL; | ||
1672 | goto done; | ||
1673 | } | ||
1674 | |||
1675 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1676 | |||
1677 | rbd_dev = __rbd_get_dev(target_id); | ||
1678 | if (!rbd_dev) { | ||
1679 | ret = -ENOENT; | ||
1680 | goto done_unlock; | ||
1681 | } | ||
1682 | |||
1683 | ret = rbd_header_add_snap(rbd_dev, | ||
1684 | name, GFP_KERNEL); | ||
1685 | if (ret < 0) | ||
1686 | goto done_unlock; | ||
1687 | |||
1688 | ret = rbd_update_snaps(rbd_dev); | ||
1689 | if (ret < 0) | ||
1690 | goto done_unlock; | ||
1691 | |||
1692 | ret = count; | ||
1693 | done_unlock: | ||
1694 | mutex_unlock(&ctl_mutex); | ||
1695 | done: | ||
1696 | kfree(name); | ||
1697 | return ret; | ||
1698 | } | ||
1699 | |||
1700 | static ssize_t class_rbd_rollback(struct class *c, | ||
1701 | struct class_attribute *attr, | ||
1702 | const char *buf, | ||
1703 | size_t count) | ||
1704 | { | ||
1705 | struct rbd_device *rbd_dev = NULL; | ||
1706 | int target_id, ret; | ||
1707 | u64 snapid; | ||
1708 | char snap_name[RBD_MAX_SNAP_NAME_LEN]; | ||
1709 | u64 cur_ofs; | ||
1710 | char *seg_name; | ||
1711 | |||
1712 | /* parse snaps add command */ | ||
1713 | if (sscanf(buf, "%d " | ||
1714 | "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s", | ||
1715 | &target_id, | ||
1716 | snap_name) != 2) { | ||
1717 | return -EINVAL; | ||
1718 | } | ||
1719 | |||
1720 | ret = -ENOMEM; | ||
1721 | seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); | ||
1722 | if (!seg_name) | ||
1723 | return ret; | ||
1724 | |||
1725 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1726 | |||
1727 | rbd_dev = __rbd_get_dev(target_id); | ||
1728 | if (!rbd_dev) { | ||
1729 | ret = -ENOENT; | ||
1730 | goto done_unlock; | ||
1731 | } | ||
1732 | |||
1733 | ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL); | ||
1734 | if (ret < 0) | ||
1735 | goto done_unlock; | ||
1736 | |||
1737 | dout("snapid=%lld\n", snapid); | ||
1738 | |||
1739 | cur_ofs = 0; | ||
1740 | while (cur_ofs < rbd_dev->header.image_size) { | ||
1741 | cur_ofs += rbd_get_segment(&rbd_dev->header, | ||
1742 | rbd_dev->obj, | ||
1743 | cur_ofs, (u64)-1, | ||
1744 | seg_name, NULL); | ||
1745 | dout("seg_name=%s\n", seg_name); | ||
1746 | |||
1747 | ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name); | ||
1748 | if (ret < 0) | ||
1749 | pr_warning("could not roll back obj %s err=%d\n", | ||
1750 | seg_name, ret); | ||
1751 | } | ||
1752 | |||
1753 | ret = rbd_update_snaps(rbd_dev); | ||
1754 | if (ret < 0) | ||
1755 | goto done_unlock; | ||
1756 | |||
1757 | ret = count; | ||
1758 | |||
1759 | done_unlock: | ||
1760 | mutex_unlock(&ctl_mutex); | ||
1761 | kfree(seg_name); | ||
1762 | |||
1763 | return ret; | ||
1764 | } | ||
1765 | |||
1766 | static struct class_attribute class_rbd_attrs[] = { | ||
1767 | __ATTR(add, 0200, NULL, class_rbd_add), | ||
1768 | __ATTR(remove, 0200, NULL, class_rbd_remove), | ||
1769 | __ATTR(list, 0444, class_rbd_list, NULL), | ||
1770 | __ATTR(snaps_refresh, 0200, NULL, class_rbd_snaps_refresh), | ||
1771 | __ATTR(snap_create, 0200, NULL, class_rbd_snap_create), | ||
1772 | __ATTR(snaps_list, 0444, class_rbd_snaps_list, NULL), | ||
1773 | __ATTR(snap_rollback, 0200, NULL, class_rbd_rollback), | ||
1774 | __ATTR_NULL | ||
1775 | }; | ||
1776 | |||
1777 | /* | ||
1778 | * create control files in sysfs | ||
1779 | * /sys/class/rbd/... | ||
1780 | */ | ||
1781 | static int rbd_sysfs_init(void) | ||
1782 | { | ||
1783 | int ret = -ENOMEM; | ||
1784 | |||
1785 | class_rbd = kzalloc(sizeof(*class_rbd), GFP_KERNEL); | ||
1786 | if (!class_rbd) | ||
1787 | goto out; | ||
1788 | |||
1789 | class_rbd->name = DRV_NAME; | ||
1790 | class_rbd->owner = THIS_MODULE; | ||
1791 | class_rbd->class_release = class_rbd_release; | ||
1792 | class_rbd->class_attrs = class_rbd_attrs; | ||
1793 | |||
1794 | ret = class_register(class_rbd); | ||
1795 | if (ret) | ||
1796 | goto out_class; | ||
1797 | return 0; | ||
1798 | |||
1799 | out_class: | ||
1800 | kfree(class_rbd); | ||
1801 | class_rbd = NULL; | ||
1802 | pr_err(DRV_NAME ": failed to create class rbd\n"); | ||
1803 | out: | ||
1804 | return ret; | ||
1805 | } | ||
1806 | |||
1807 | static void rbd_sysfs_cleanup(void) | ||
1808 | { | ||
1809 | if (class_rbd) | ||
1810 | class_destroy(class_rbd); | ||
1811 | class_rbd = NULL; | ||
1812 | } | ||
1813 | |||
1814 | int __init rbd_init(void) | ||
1815 | { | ||
1816 | int rc; | ||
1817 | |||
1818 | rc = rbd_sysfs_init(); | ||
1819 | if (rc) | ||
1820 | return rc; | ||
1821 | spin_lock_init(&node_lock); | ||
1822 | pr_info("loaded " DRV_NAME_LONG "\n"); | ||
1823 | return 0; | ||
1824 | } | ||
1825 | |||
1826 | void __exit rbd_exit(void) | ||
1827 | { | ||
1828 | rbd_sysfs_cleanup(); | ||
1829 | } | ||
1830 | |||
1831 | module_init(rbd_init); | ||
1832 | module_exit(rbd_exit); | ||
1833 | |||
1834 | MODULE_AUTHOR("Sage Weil <sage@newdream.net>"); | ||
1835 | MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>"); | ||
1836 | MODULE_DESCRIPTION("rados block device"); | ||
1837 | |||
1838 | /* following authorship retained from original osdblk.c */ | ||
1839 | MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>"); | ||
1840 | |||
1841 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/block/rbd_types.h b/drivers/block/rbd_types.h new file mode 100644 index 000000000000..fc6c678aa2cb --- /dev/null +++ b/drivers/block/rbd_types.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Ceph - scalable distributed file system | ||
3 | * | ||
4 | * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net> | ||
5 | * | ||
6 | * This is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License version 2.1, as published by the Free Software | ||
9 | * Foundation. See file COPYING. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #ifndef CEPH_RBD_TYPES_H | ||
14 | #define CEPH_RBD_TYPES_H | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | |||
18 | /* | ||
19 | * rbd image 'foo' consists of objects | ||
20 | * foo.rbd - image metadata | ||
21 | * foo.00000000 | ||
22 | * foo.00000001 | ||
23 | * ... - data | ||
24 | */ | ||
25 | |||
26 | #define RBD_SUFFIX ".rbd" | ||
27 | #define RBD_DIRECTORY "rbd_directory" | ||
28 | #define RBD_INFO "rbd_info" | ||
29 | |||
30 | #define RBD_DEFAULT_OBJ_ORDER 22 /* 4MB */ | ||
31 | #define RBD_MIN_OBJ_ORDER 16 | ||
32 | #define RBD_MAX_OBJ_ORDER 30 | ||
33 | |||
34 | #define RBD_MAX_OBJ_NAME_LEN 96 | ||
35 | #define RBD_MAX_SEG_NAME_LEN 128 | ||
36 | |||
37 | #define RBD_COMP_NONE 0 | ||
38 | #define RBD_CRYPT_NONE 0 | ||
39 | |||
40 | #define RBD_HEADER_TEXT "<<< Rados Block Device Image >>>\n" | ||
41 | #define RBD_HEADER_SIGNATURE "RBD" | ||
42 | #define RBD_HEADER_VERSION "001.005" | ||
43 | |||
44 | struct rbd_info { | ||
45 | __le64 max_id; | ||
46 | } __attribute__ ((packed)); | ||
47 | |||
48 | struct rbd_image_snap_ondisk { | ||
49 | __le64 id; | ||
50 | __le64 image_size; | ||
51 | } __attribute__((packed)); | ||
52 | |||
53 | struct rbd_image_header_ondisk { | ||
54 | char text[40]; | ||
55 | char block_name[24]; | ||
56 | char signature[4]; | ||
57 | char version[8]; | ||
58 | struct { | ||
59 | __u8 order; | ||
60 | __u8 crypt_type; | ||
61 | __u8 comp_type; | ||
62 | __u8 unused; | ||
63 | } __attribute__((packed)) options; | ||
64 | __le64 image_size; | ||
65 | __le64 snap_seq; | ||
66 | __le32 snap_count; | ||
67 | __le32 reserved; | ||
68 | __le64 snap_names_len; | ||
69 | struct rbd_image_snap_ondisk snaps[0]; | ||
70 | } __attribute__((packed)); | ||
71 | |||
72 | |||
73 | #endif | ||
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2aafafca2b13..8320490226b7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -2,7 +2,6 @@ | |||
2 | #include <linux/spinlock.h> | 2 | #include <linux/spinlock.h> |
3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
4 | #include <linux/blkdev.h> | 4 | #include <linux/blkdev.h> |
5 | #include <linux/smp_lock.h> | ||
6 | #include <linux/hdreg.h> | 5 | #include <linux/hdreg.h> |
7 | #include <linux/virtio.h> | 6 | #include <linux/virtio.h> |
8 | #include <linux/virtio_blk.h> | 7 | #include <linux/virtio_blk.h> |
@@ -202,6 +201,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) | |||
202 | struct virtio_blk *vblk = disk->private_data; | 201 | struct virtio_blk *vblk = disk->private_data; |
203 | struct request *req; | 202 | struct request *req; |
204 | struct bio *bio; | 203 | struct bio *bio; |
204 | int err; | ||
205 | 205 | ||
206 | bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, | 206 | bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, |
207 | GFP_KERNEL); | 207 | GFP_KERNEL); |
@@ -215,11 +215,14 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) | |||
215 | } | 215 | } |
216 | 216 | ||
217 | req->cmd_type = REQ_TYPE_SPECIAL; | 217 | req->cmd_type = REQ_TYPE_SPECIAL; |
218 | return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); | 218 | err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); |
219 | blk_put_request(req); | ||
220 | |||
221 | return err; | ||
219 | } | 222 | } |
220 | 223 | ||
221 | static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, | 224 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
222 | unsigned cmd, unsigned long data) | 225 | unsigned int cmd, unsigned long data) |
223 | { | 226 | { |
224 | struct gendisk *disk = bdev->bd_disk; | 227 | struct gendisk *disk = bdev->bd_disk; |
225 | struct virtio_blk *vblk = disk->private_data; | 228 | struct virtio_blk *vblk = disk->private_data; |
@@ -234,18 +237,6 @@ static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, | |||
234 | (void __user *)data); | 237 | (void __user *)data); |
235 | } | 238 | } |
236 | 239 | ||
237 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | ||
238 | unsigned int cmd, unsigned long param) | ||
239 | { | ||
240 | int ret; | ||
241 | |||
242 | lock_kernel(); | ||
243 | ret = virtblk_locked_ioctl(bdev, mode, cmd, param); | ||
244 | unlock_kernel(); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | /* We provide getgeo only to please some old bootloader/partitioning tools */ | 240 | /* We provide getgeo only to please some old bootloader/partitioning tools */ |
250 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) | 241 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) |
251 | { | 242 | { |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index d52e90a5a617..4104b7feae67 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
40 | #include <linux/io.h> | 40 | #include <linux/io.h> |
41 | 41 | ||
42 | #include <pcmcia/cs.h> | ||
43 | #include <pcmcia/cistpl.h> | 42 | #include <pcmcia/cistpl.h> |
44 | #include <pcmcia/ciscode.h> | 43 | #include <pcmcia/ciscode.h> |
45 | #include <pcmcia/ds.h> | 44 | #include <pcmcia/ds.h> |
@@ -865,8 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link) | |||
865 | info->p_dev = link; | 864 | info->p_dev = link; |
866 | link->priv = info; | 865 | link->priv = info; |
867 | 866 | ||
868 | link->conf.Attributes = CONF_ENABLE_IRQ; | 867 | link->config_flags |= CONF_ENABLE_IRQ; |
869 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
870 | 868 | ||
871 | return bluecard_config(link); | 869 | return bluecard_config(link); |
872 | } | 870 | } |
@@ -886,7 +884,7 @@ static int bluecard_config(struct pcmcia_device *link) | |||
886 | bluecard_info_t *info = link->priv; | 884 | bluecard_info_t *info = link->priv; |
887 | int i, n; | 885 | int i, n; |
888 | 886 | ||
889 | link->conf.ConfigIndex = 0x20; | 887 | link->config_index = 0x20; |
890 | 888 | ||
891 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 889 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
892 | link->resource[0]->end = 64; | 890 | link->resource[0]->end = 64; |
@@ -906,7 +904,7 @@ static int bluecard_config(struct pcmcia_device *link) | |||
906 | if (i != 0) | 904 | if (i != 0) |
907 | goto failed; | 905 | goto failed; |
908 | 906 | ||
909 | i = pcmcia_request_configuration(link, &link->conf); | 907 | i = pcmcia_enable_device(link); |
910 | if (i != 0) | 908 | if (i != 0) |
911 | goto failed; | 909 | goto failed; |
912 | 910 | ||
@@ -942,9 +940,7 @@ MODULE_DEVICE_TABLE(pcmcia, bluecard_ids); | |||
942 | 940 | ||
943 | static struct pcmcia_driver bluecard_driver = { | 941 | static struct pcmcia_driver bluecard_driver = { |
944 | .owner = THIS_MODULE, | 942 | .owner = THIS_MODULE, |
945 | .drv = { | 943 | .name = "bluecard_cs", |
946 | .name = "bluecard_cs", | ||
947 | }, | ||
948 | .probe = bluecard_probe, | 944 | .probe = bluecard_probe, |
949 | .remove = bluecard_detach, | 945 | .remove = bluecard_detach, |
950 | .id_table = bluecard_ids, | 946 | .id_table = bluecard_ids, |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 7ab8f29d5e0d..0c8a65587491 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/device.h> | 45 | #include <linux/device.h> |
46 | #include <linux/firmware.h> | 46 | #include <linux/firmware.h> |
47 | 47 | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | 48 | #include <pcmcia/cistpl.h> |
50 | #include <pcmcia/ciscode.h> | 49 | #include <pcmcia/ciscode.h> |
51 | #include <pcmcia/ds.h> | 50 | #include <pcmcia/ds.h> |
@@ -657,11 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link) | |||
657 | info->p_dev = link; | 656 | info->p_dev = link; |
658 | link->priv = info; | 657 | link->priv = info; |
659 | 658 | ||
660 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 659 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | |
661 | link->resource[0]->end = 8; | 660 | CONF_AUTO_SET_IO; |
662 | |||
663 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
664 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
665 | 661 | ||
666 | return bt3c_config(link); | 662 | return bt3c_config(link); |
667 | } | 663 | } |
@@ -675,43 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link) | |||
675 | kfree(info); | 671 | kfree(info); |
676 | } | 672 | } |
677 | 673 | ||
678 | static int bt3c_check_config(struct pcmcia_device *p_dev, | 674 | static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data) |
679 | cistpl_cftable_entry_t *cf, | ||
680 | cistpl_cftable_entry_t *dflt, | ||
681 | unsigned int vcc, | ||
682 | void *priv_data) | ||
683 | { | 675 | { |
684 | unsigned long try = (unsigned long) priv_data; | 676 | int *try = priv_data; |
685 | 677 | ||
686 | p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | 678 | if (try == 0) |
679 | p_dev->io_lines = 16; | ||
687 | 680 | ||
688 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 681 | if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0)) |
689 | p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 682 | return -EINVAL; |
690 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && | 683 | |
691 | (cf->io.win[0].base != 0)) { | 684 | p_dev->resource[0]->end = 8; |
692 | p_dev->resource[0]->start = cf->io.win[0].base; | 685 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
693 | if (!pcmcia_request_io(p_dev)) | 686 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
694 | return 0; | 687 | |
695 | } | 688 | return pcmcia_request_io(p_dev); |
696 | return -ENODEV; | ||
697 | } | 689 | } |
698 | 690 | ||
699 | static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev, | 691 | static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev, |
700 | cistpl_cftable_entry_t *cf, | ||
701 | cistpl_cftable_entry_t *dflt, | ||
702 | unsigned int vcc, | ||
703 | void *priv_data) | 692 | void *priv_data) |
704 | { | 693 | { |
705 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | 694 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
706 | int j; | 695 | int j; |
707 | 696 | ||
708 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | 697 | if (p_dev->io_lines > 3) |
709 | for (j = 0; j < 5; j++) { | 698 | return -ENODEV; |
710 | p_dev->resource[0]->start = base[j]; | 699 | |
711 | p_dev->io_lines = base[j] ? 16 : 3; | 700 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
712 | if (!pcmcia_request_io(p_dev)) | 701 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
713 | return 0; | 702 | p_dev->resource[0]->end = 8; |
714 | } | 703 | |
704 | for (j = 0; j < 5; j++) { | ||
705 | p_dev->resource[0]->start = base[j]; | ||
706 | p_dev->io_lines = base[j] ? 16 : 3; | ||
707 | if (!pcmcia_request_io(p_dev)) | ||
708 | return 0; | ||
715 | } | 709 | } |
716 | return -ENODEV; | 710 | return -ENODEV; |
717 | } | 711 | } |
@@ -742,7 +736,7 @@ found_port: | |||
742 | if (i != 0) | 736 | if (i != 0) |
743 | goto failed; | 737 | goto failed; |
744 | 738 | ||
745 | i = pcmcia_request_configuration(link, &link->conf); | 739 | i = pcmcia_enable_device(link); |
746 | if (i != 0) | 740 | if (i != 0) |
747 | goto failed; | 741 | goto failed; |
748 | 742 | ||
@@ -775,9 +769,7 @@ MODULE_DEVICE_TABLE(pcmcia, bt3c_ids); | |||
775 | 769 | ||
776 | static struct pcmcia_driver bt3c_driver = { | 770 | static struct pcmcia_driver bt3c_driver = { |
777 | .owner = THIS_MODULE, | 771 | .owner = THIS_MODULE, |
778 | .drv = { | 772 | .name = "bt3c_cs", |
779 | .name = "bt3c_cs", | ||
780 | }, | ||
781 | .probe = bt3c_probe, | 773 | .probe = bt3c_probe, |
782 | .remove = bt3c_detach, | 774 | .remove = bt3c_detach, |
783 | .id_table = bt3c_ids, | 775 | .id_table = bt3c_ids, |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 1c4f5e863b03..f8a0708e2311 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/io.h> | 42 | #include <asm/io.h> |
43 | 43 | ||
44 | #include <pcmcia/cs.h> | ||
45 | #include <pcmcia/cistpl.h> | 44 | #include <pcmcia/cistpl.h> |
46 | #include <pcmcia/ciscode.h> | 45 | #include <pcmcia/ciscode.h> |
47 | #include <pcmcia/ds.h> | 46 | #include <pcmcia/ds.h> |
@@ -586,11 +585,8 @@ static int btuart_probe(struct pcmcia_device *link) | |||
586 | info->p_dev = link; | 585 | info->p_dev = link; |
587 | link->priv = info; | 586 | link->priv = info; |
588 | 587 | ||
589 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 588 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | |
590 | link->resource[0]->end = 8; | 589 | CONF_AUTO_SET_IO; |
591 | |||
592 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
593 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
594 | 590 | ||
595 | return btuart_config(link); | 591 | return btuart_config(link); |
596 | } | 592 | } |
@@ -604,43 +600,41 @@ static void btuart_detach(struct pcmcia_device *link) | |||
604 | kfree(info); | 600 | kfree(info); |
605 | } | 601 | } |
606 | 602 | ||
607 | static int btuart_check_config(struct pcmcia_device *p_dev, | 603 | static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data) |
608 | cistpl_cftable_entry_t *cf, | ||
609 | cistpl_cftable_entry_t *dflt, | ||
610 | unsigned int vcc, | ||
611 | void *priv_data) | ||
612 | { | 604 | { |
613 | int *try = priv_data; | 605 | int *try = priv_data; |
614 | 606 | ||
615 | p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | 607 | if (try == 0) |
608 | p_dev->io_lines = 16; | ||
616 | 609 | ||
617 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 610 | if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0)) |
618 | p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 611 | return -EINVAL; |
619 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && | 612 | |
620 | (cf->io.win[0].base != 0)) { | 613 | p_dev->resource[0]->end = 8; |
621 | p_dev->resource[0]->start = cf->io.win[0].base; | 614 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
622 | if (!pcmcia_request_io(p_dev)) | 615 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
623 | return 0; | 616 | |
624 | } | 617 | return pcmcia_request_io(p_dev); |
625 | return -ENODEV; | ||
626 | } | 618 | } |
627 | 619 | ||
628 | static int btuart_check_config_notpicky(struct pcmcia_device *p_dev, | 620 | static int btuart_check_config_notpicky(struct pcmcia_device *p_dev, |
629 | cistpl_cftable_entry_t *cf, | ||
630 | cistpl_cftable_entry_t *dflt, | ||
631 | unsigned int vcc, | ||
632 | void *priv_data) | 621 | void *priv_data) |
633 | { | 622 | { |
634 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | 623 | static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
635 | int j; | 624 | int j; |
636 | 625 | ||
637 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | 626 | if (p_dev->io_lines > 3) |
638 | for (j = 0; j < 5; j++) { | 627 | return -ENODEV; |
639 | p_dev->resource[0]->start = base[j]; | 628 | |
640 | p_dev->io_lines = base[j] ? 16 : 3; | 629 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
641 | if (!pcmcia_request_io(p_dev)) | 630 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
642 | return 0; | 631 | p_dev->resource[0]->end = 8; |
643 | } | 632 | |
633 | for (j = 0; j < 5; j++) { | ||
634 | p_dev->resource[0]->start = base[j]; | ||
635 | p_dev->io_lines = base[j] ? 16 : 3; | ||
636 | if (!pcmcia_request_io(p_dev)) | ||
637 | return 0; | ||
644 | } | 638 | } |
645 | return -ENODEV; | 639 | return -ENODEV; |
646 | } | 640 | } |
@@ -671,7 +665,7 @@ found_port: | |||
671 | if (i != 0) | 665 | if (i != 0) |
672 | goto failed; | 666 | goto failed; |
673 | 667 | ||
674 | i = pcmcia_request_configuration(link, &link->conf); | 668 | i = pcmcia_enable_device(link); |
675 | if (i != 0) | 669 | if (i != 0) |
676 | goto failed; | 670 | goto failed; |
677 | 671 | ||
@@ -703,9 +697,7 @@ MODULE_DEVICE_TABLE(pcmcia, btuart_ids); | |||
703 | 697 | ||
704 | static struct pcmcia_driver btuart_driver = { | 698 | static struct pcmcia_driver btuart_driver = { |
705 | .owner = THIS_MODULE, | 699 | .owner = THIS_MODULE, |
706 | .drv = { | 700 | .name = "btuart_cs", |
707 | .name = "btuart_cs", | ||
708 | }, | ||
709 | .probe = btuart_probe, | 701 | .probe = btuart_probe, |
710 | .remove = btuart_detach, | 702 | .remove = btuart_detach, |
711 | .id_table = btuart_ids, | 703 | .id_table = btuart_ids, |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index db7c8db695fc..26ee0cf88d20 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/io.h> | 42 | #include <asm/io.h> |
43 | 43 | ||
44 | #include <pcmcia/cs.h> | ||
45 | #include <pcmcia/cistpl.h> | 44 | #include <pcmcia/cistpl.h> |
46 | #include <pcmcia/ciscode.h> | 45 | #include <pcmcia/ciscode.h> |
47 | #include <pcmcia/ds.h> | 46 | #include <pcmcia/ds.h> |
@@ -572,11 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link) | |||
572 | info->p_dev = link; | 571 | info->p_dev = link; |
573 | link->priv = info; | 572 | link->priv = info; |
574 | 573 | ||
575 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 574 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
576 | link->resource[0]->end = 8; | ||
577 | |||
578 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
579 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
580 | 575 | ||
581 | return dtl1_config(link); | 576 | return dtl1_config(link); |
582 | } | 577 | } |
@@ -591,18 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link) | |||
591 | kfree(info); | 586 | kfree(info); |
592 | } | 587 | } |
593 | 588 | ||
594 | static int dtl1_confcheck(struct pcmcia_device *p_dev, | 589 | static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data) |
595 | cistpl_cftable_entry_t *cf, | ||
596 | cistpl_cftable_entry_t *dflt, | ||
597 | unsigned int vcc, | ||
598 | void *priv_data) | ||
599 | { | 590 | { |
600 | if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8)) | 591 | if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8)) |
601 | return -ENODEV; | 592 | return -ENODEV; |
602 | 593 | ||
603 | p_dev->resource[0]->start = cf->io.win[0].base; | 594 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
604 | p_dev->resource[0]->end = cf->io.win[0].len; /*yo */ | 595 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
605 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 596 | |
606 | return pcmcia_request_io(p_dev); | 597 | return pcmcia_request_io(p_dev); |
607 | } | 598 | } |
608 | 599 | ||
@@ -620,7 +611,7 @@ static int dtl1_config(struct pcmcia_device *link) | |||
620 | if (i != 0) | 611 | if (i != 0) |
621 | goto failed; | 612 | goto failed; |
622 | 613 | ||
623 | i = pcmcia_request_configuration(link, &link->conf); | 614 | i = pcmcia_enable_device(link); |
624 | if (i != 0) | 615 | if (i != 0) |
625 | goto failed; | 616 | goto failed; |
626 | 617 | ||
@@ -656,9 +647,7 @@ MODULE_DEVICE_TABLE(pcmcia, dtl1_ids); | |||
656 | 647 | ||
657 | static struct pcmcia_driver dtl1_driver = { | 648 | static struct pcmcia_driver dtl1_driver = { |
658 | .owner = THIS_MODULE, | 649 | .owner = THIS_MODULE, |
659 | .drv = { | 650 | .name = "dtl1_cs", |
660 | .name = "dtl1_cs", | ||
661 | }, | ||
662 | .probe = dtl1_probe, | 651 | .probe = dtl1_probe, |
663 | .remove = dtl1_detach, | 652 | .remove = dtl1_detach, |
664 | .id_table = dtl1_ids, | 653 | .id_table = dtl1_ids, |
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 4b66c69eaf57..5ddf67e76f8b 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -57,7 +57,7 @@ config AGP_AMD | |||
57 | 57 | ||
58 | config AGP_AMD64 | 58 | config AGP_AMD64 |
59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" | 59 | tristate "AMD Opteron/Athlon64 on-CPU GART support" |
60 | depends on AGP && X86 && K8_NB | 60 | depends on AGP && X86 && AMD_NB |
61 | help | 61 | help |
62 | This option gives you AGP support for the GLX component of | 62 | This option gives you AGP support for the GLX component of |
63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. | 63 | X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 70312da4c968..42396df55556 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/mmzone.h> | 15 | #include <linux/mmzone.h> |
16 | #include <asm/page.h> /* PAGE_SIZE */ | 16 | #include <asm/page.h> /* PAGE_SIZE */ |
17 | #include <asm/e820.h> | 17 | #include <asm/e820.h> |
18 | #include <asm/k8.h> | 18 | #include <asm/amd_nb.h> |
19 | #include <asm/gart.h> | 19 | #include <asm/gart.h> |
20 | #include "agp.h" | 20 | #include "agp.h" |
21 | 21 | ||
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void) | |||
124 | u32 temp; | 124 | u32 temp; |
125 | struct aper_size_info_32 *values; | 125 | struct aper_size_info_32 *values; |
126 | 126 | ||
127 | dev = k8_northbridges[0]; | 127 | dev = k8_northbridges.nb_misc[0]; |
128 | if (dev==NULL) | 128 | if (dev==NULL) |
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -181,10 +181,14 @@ static int amd_8151_configure(void) | |||
181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); | 181 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); |
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | if (!k8_northbridges.gart_supported) | ||
185 | return 0; | ||
186 | |||
184 | /* Configure AGP regs in each x86-64 host bridge. */ | 187 | /* Configure AGP regs in each x86-64 host bridge. */ |
185 | for (i = 0; i < num_k8_northbridges; i++) { | 188 | for (i = 0; i < k8_northbridges.num; i++) { |
186 | agp_bridge->gart_bus_addr = | 189 | agp_bridge->gart_bus_addr = |
187 | amd64_configure(k8_northbridges[i], gatt_bus); | 190 | amd64_configure(k8_northbridges.nb_misc[i], |
191 | gatt_bus); | ||
188 | } | 192 | } |
189 | k8_flush_garts(); | 193 | k8_flush_garts(); |
190 | return 0; | 194 | return 0; |
@@ -195,11 +199,15 @@ static void amd64_cleanup(void) | |||
195 | { | 199 | { |
196 | u32 tmp; | 200 | u32 tmp; |
197 | int i; | 201 | int i; |
198 | for (i = 0; i < num_k8_northbridges; i++) { | 202 | |
199 | struct pci_dev *dev = k8_northbridges[i]; | 203 | if (!k8_northbridges.gart_supported) |
204 | return; | ||
205 | |||
206 | for (i = 0; i < k8_northbridges.num; i++) { | ||
207 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | ||
200 | /* disable gart translation */ | 208 | /* disable gart translation */ |
201 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); | 209 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp); |
202 | tmp &= ~AMD64_GARTEN; | 210 | tmp &= ~GARTEN; |
203 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); | 211 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp); |
204 | } | 212 | } |
205 | } | 213 | } |
@@ -313,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, | |||
313 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) | 321 | if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) |
314 | return -1; | 322 | return -1; |
315 | 323 | ||
316 | pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1); | 324 | gart_set_size_and_enable(nb, order); |
317 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); | 325 | pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25); |
318 | 326 | ||
319 | return 0; | 327 | return 0; |
320 | } | 328 | } |
321 | 329 | ||
322 | static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) | 330 | static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) |
323 | { | 331 | { |
324 | int i; | 332 | int i; |
325 | 333 | ||
326 | if (cache_k8_northbridges() < 0) | 334 | if (cache_k8_northbridges() < 0) |
327 | return -ENODEV; | 335 | return -ENODEV; |
328 | 336 | ||
337 | if (!k8_northbridges.gart_supported) | ||
338 | return -ENODEV; | ||
339 | |||
329 | i = 0; | 340 | i = 0; |
330 | for (i = 0; i < num_k8_northbridges; i++) { | 341 | for (i = 0; i < k8_northbridges.num; i++) { |
331 | struct pci_dev *dev = k8_northbridges[i]; | 342 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; |
332 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { | 343 | if (fix_northbridge(dev, pdev, cap_ptr) < 0) { |
333 | dev_err(&dev->dev, "no usable aperture found\n"); | 344 | dev_err(&dev->dev, "no usable aperture found\n"); |
334 | #ifdef __x86_64__ | 345 | #ifdef __x86_64__ |
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
405 | } | 416 | } |
406 | 417 | ||
407 | /* shadow x86-64 registers into ULi registers */ | 418 | /* shadow x86-64 registers into ULi registers */ |
408 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); | 419 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
420 | &httfea); | ||
409 | 421 | ||
410 | /* if x86-64 aperture base is beyond 4G, exit here */ | 422 | /* if x86-64 aperture base is beyond 4G, exit here */ |
411 | if ((httfea & 0x7fff) >> (32 - 25)) { | 423 | if ((httfea & 0x7fff) >> (32 - 25)) { |
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
472 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); | 484 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); |
473 | 485 | ||
474 | /* shadow x86-64 registers into NVIDIA registers */ | 486 | /* shadow x86-64 registers into NVIDIA registers */ |
475 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); | 487 | pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE, |
488 | &apbase); | ||
476 | 489 | ||
477 | /* if x86-64 aperture base is beyond 4G, exit here */ | 490 | /* if x86-64 aperture base is beyond 4G, exit here */ |
478 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 491 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d2abf5143983..64255cef8a7d 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -984,7 +984,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
984 | 984 | ||
985 | bridge->driver->cache_flush(); | 985 | bridge->driver->cache_flush(); |
986 | #ifdef CONFIG_X86 | 986 | #ifdef CONFIG_X86 |
987 | set_memory_uc((unsigned long)table, 1 << page_order); | 987 | if (set_memory_uc((unsigned long)table, 1 << page_order)) |
988 | printk(KERN_WARNING "Could not set GATT table memory to UC!"); | ||
989 | |||
988 | bridge->gatt_table = (void *)table; | 990 | bridge->gatt_table = (void *)table; |
989 | #else | 991 | #else |
990 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | 992 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index ec73d9f6d9ed..c7b482d15e2a 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | 36 | ||
37 | #include <pcmcia/cs.h> | ||
38 | #include <pcmcia/cistpl.h> | 37 | #include <pcmcia/cistpl.h> |
39 | #include <pcmcia/cisreg.h> | 38 | #include <pcmcia/cisreg.h> |
40 | #include <pcmcia/ciscode.h> | 39 | #include <pcmcia/ciscode.h> |
@@ -55,8 +54,6 @@ | |||
55 | __func__ , ## args); \ | 54 | __func__ , ## args); \ |
56 | } while (0) | 55 | } while (0) |
57 | 56 | ||
58 | static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; | ||
59 | |||
60 | #define T_1SEC (HZ) | 57 | #define T_1SEC (HZ) |
61 | #define T_10MSEC msecs_to_jiffies(10) | 58 | #define T_10MSEC msecs_to_jiffies(10) |
62 | #define T_20MSEC msecs_to_jiffies(20) | 59 | #define T_20MSEC msecs_to_jiffies(20) |
@@ -1742,20 +1739,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link) | |||
1742 | 1739 | ||
1743 | /*==== Interface to PCMCIA Layer =======================================*/ | 1740 | /*==== Interface to PCMCIA Layer =======================================*/ |
1744 | 1741 | ||
1745 | static int cm4000_config_check(struct pcmcia_device *p_dev, | 1742 | static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data) |
1746 | cistpl_cftable_entry_t *cfg, | ||
1747 | cistpl_cftable_entry_t *dflt, | ||
1748 | unsigned int vcc, | ||
1749 | void *priv_data) | ||
1750 | { | 1743 | { |
1751 | if (!cfg->io.nwin) | ||
1752 | return -ENODEV; | ||
1753 | |||
1754 | p_dev->resource[0]->start = cfg->io.win[0].base; | ||
1755 | p_dev->resource[0]->end = cfg->io.win[0].len; | ||
1756 | p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); | ||
1757 | p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
1758 | |||
1759 | return pcmcia_request_io(p_dev); | 1744 | return pcmcia_request_io(p_dev); |
1760 | } | 1745 | } |
1761 | 1746 | ||
@@ -1763,13 +1748,13 @@ static int cm4000_config(struct pcmcia_device * link, int devno) | |||
1763 | { | 1748 | { |
1764 | struct cm4000_dev *dev; | 1749 | struct cm4000_dev *dev; |
1765 | 1750 | ||
1751 | link->config_flags |= CONF_AUTO_SET_IO; | ||
1752 | |||
1766 | /* read the config-tuples */ | 1753 | /* read the config-tuples */ |
1767 | if (pcmcia_loop_config(link, cm4000_config_check, NULL)) | 1754 | if (pcmcia_loop_config(link, cm4000_config_check, NULL)) |
1768 | goto cs_release; | 1755 | goto cs_release; |
1769 | 1756 | ||
1770 | link->conf.IntType = 00000002; | 1757 | if (pcmcia_enable_device(link)) |
1771 | |||
1772 | if (pcmcia_request_configuration(link, &link->conf)) | ||
1773 | goto cs_release; | 1758 | goto cs_release; |
1774 | 1759 | ||
1775 | dev = link->priv; | 1760 | dev = link->priv; |
@@ -1829,7 +1814,6 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
1829 | 1814 | ||
1830 | dev->p_dev = link; | 1815 | dev->p_dev = link; |
1831 | link->priv = dev; | 1816 | link->priv = dev; |
1832 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1833 | dev_table[i] = link; | 1817 | dev_table[i] = link; |
1834 | 1818 | ||
1835 | init_waitqueue_head(&dev->devq); | 1819 | init_waitqueue_head(&dev->devq); |
@@ -1891,9 +1875,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); | |||
1891 | 1875 | ||
1892 | static struct pcmcia_driver cm4000_driver = { | 1876 | static struct pcmcia_driver cm4000_driver = { |
1893 | .owner = THIS_MODULE, | 1877 | .owner = THIS_MODULE, |
1894 | .drv = { | 1878 | .name = "cm4000_cs", |
1895 | .name = "cm4000_cs", | ||
1896 | }, | ||
1897 | .probe = cm4000_probe, | 1879 | .probe = cm4000_probe, |
1898 | .remove = cm4000_detach, | 1880 | .remove = cm4000_detach, |
1899 | .suspend = cm4000_suspend, | 1881 | .suspend = cm4000_suspend, |
@@ -1905,8 +1887,6 @@ static int __init cmm_init(void) | |||
1905 | { | 1887 | { |
1906 | int rc; | 1888 | int rc; |
1907 | 1889 | ||
1908 | printk(KERN_INFO "%s\n", version); | ||
1909 | |||
1910 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); | 1890 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); |
1911 | if (IS_ERR(cmm_class)) | 1891 | if (IS_ERR(cmm_class)) |
1912 | return PTR_ERR(cmm_class); | 1892 | return PTR_ERR(cmm_class); |
@@ -1931,7 +1911,6 @@ static int __init cmm_init(void) | |||
1931 | 1911 | ||
1932 | static void __exit cmm_exit(void) | 1912 | static void __exit cmm_exit(void) |
1933 | { | 1913 | { |
1934 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
1935 | pcmcia_unregister_driver(&cm4000_driver); | 1914 | pcmcia_unregister_driver(&cm4000_driver); |
1936 | unregister_chrdev(major, DEVICE_NAME); | 1915 | unregister_chrdev(major, DEVICE_NAME); |
1937 | class_destroy(cmm_class); | 1916 | class_destroy(cmm_class); |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 815cde1d0570..bf2f046fc2c1 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | 31 | ||
32 | #include <pcmcia/cs.h> | ||
33 | #include <pcmcia/cistpl.h> | 32 | #include <pcmcia/cistpl.h> |
34 | #include <pcmcia/cisreg.h> | 33 | #include <pcmcia/cisreg.h> |
35 | #include <pcmcia/ciscode.h> | 34 | #include <pcmcia/ciscode.h> |
@@ -49,9 +48,6 @@ | |||
49 | __func__ , ## args); \ | 48 | __func__ , ## args); \ |
50 | } while (0) | 49 | } while (0) |
51 | 50 | ||
52 | static char *version = | ||
53 | "OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte"; | ||
54 | |||
55 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) | 51 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) |
56 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) | 52 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) |
57 | #define CCID_DRIVER_MINIMUM_TIMEOUT (3*HZ) | 53 | #define CCID_DRIVER_MINIMUM_TIMEOUT (3*HZ) |
@@ -516,26 +512,9 @@ static void cm4040_reader_release(struct pcmcia_device *link) | |||
516 | return; | 512 | return; |
517 | } | 513 | } |
518 | 514 | ||
519 | static int cm4040_config_check(struct pcmcia_device *p_dev, | 515 | static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data) |
520 | cistpl_cftable_entry_t *cfg, | ||
521 | cistpl_cftable_entry_t *dflt, | ||
522 | unsigned int vcc, | ||
523 | void *priv_data) | ||
524 | { | 516 | { |
525 | int rc; | 517 | return pcmcia_request_io(p_dev); |
526 | if (!cfg->io.nwin) | ||
527 | return -ENODEV; | ||
528 | |||
529 | /* Get the IOaddr */ | ||
530 | p_dev->resource[0]->start = cfg->io.win[0].base; | ||
531 | p_dev->resource[0]->end = cfg->io.win[0].len; | ||
532 | p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); | ||
533 | p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
534 | rc = pcmcia_request_io(p_dev); | ||
535 | |||
536 | dev_printk(KERN_INFO, &p_dev->dev, | ||
537 | "pcmcia_request_io returned 0x%x\n", rc); | ||
538 | return rc; | ||
539 | } | 518 | } |
540 | 519 | ||
541 | 520 | ||
@@ -544,15 +523,15 @@ static int reader_config(struct pcmcia_device *link, int devno) | |||
544 | struct reader_dev *dev; | 523 | struct reader_dev *dev; |
545 | int fail_rc; | 524 | int fail_rc; |
546 | 525 | ||
526 | link->config_flags |= CONF_AUTO_SET_IO; | ||
527 | |||
547 | if (pcmcia_loop_config(link, cm4040_config_check, NULL)) | 528 | if (pcmcia_loop_config(link, cm4040_config_check, NULL)) |
548 | goto cs_release; | 529 | goto cs_release; |
549 | 530 | ||
550 | link->conf.IntType = 00000002; | 531 | fail_rc = pcmcia_enable_device(link); |
551 | |||
552 | fail_rc = pcmcia_request_configuration(link, &link->conf); | ||
553 | if (fail_rc != 0) { | 532 | if (fail_rc != 0) { |
554 | dev_printk(KERN_INFO, &link->dev, | 533 | dev_printk(KERN_INFO, &link->dev, |
555 | "pcmcia_request_configuration failed 0x%x\n", | 534 | "pcmcia_enable_device failed 0x%x\n", |
556 | fail_rc); | 535 | fail_rc); |
557 | goto cs_release; | 536 | goto cs_release; |
558 | } | 537 | } |
@@ -599,7 +578,6 @@ static int reader_probe(struct pcmcia_device *link) | |||
599 | link->priv = dev; | 578 | link->priv = dev; |
600 | dev->p_dev = link; | 579 | dev->p_dev = link; |
601 | 580 | ||
602 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
603 | dev_table[i] = link; | 581 | dev_table[i] = link; |
604 | 582 | ||
605 | init_waitqueue_head(&dev->devq); | 583 | init_waitqueue_head(&dev->devq); |
@@ -662,9 +640,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4040_ids); | |||
662 | 640 | ||
663 | static struct pcmcia_driver reader_driver = { | 641 | static struct pcmcia_driver reader_driver = { |
664 | .owner = THIS_MODULE, | 642 | .owner = THIS_MODULE, |
665 | .drv = { | 643 | .name = "cm4040_cs", |
666 | .name = "cm4040_cs", | ||
667 | }, | ||
668 | .probe = reader_probe, | 644 | .probe = reader_probe, |
669 | .remove = reader_detach, | 645 | .remove = reader_detach, |
670 | .id_table = cm4040_ids, | 646 | .id_table = cm4040_ids, |
@@ -674,7 +650,6 @@ static int __init cm4040_init(void) | |||
674 | { | 650 | { |
675 | int rc; | 651 | int rc; |
676 | 652 | ||
677 | printk(KERN_INFO "%s\n", version); | ||
678 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); | 653 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); |
679 | if (IS_ERR(cmx_class)) | 654 | if (IS_ERR(cmx_class)) |
680 | return PTR_ERR(cmx_class); | 655 | return PTR_ERR(cmx_class); |
@@ -699,7 +674,6 @@ static int __init cm4040_init(void) | |||
699 | 674 | ||
700 | static void __exit cm4040_exit(void) | 675 | static void __exit cm4040_exit(void) |
701 | { | 676 | { |
702 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
703 | pcmcia_unregister_driver(&reader_driver); | 677 | pcmcia_unregister_driver(&reader_driver); |
704 | unregister_chrdev(major, DEVICE_NAME); | 678 | unregister_chrdev(major, DEVICE_NAME); |
705 | class_destroy(cmx_class); | 679 | class_destroy(cmx_class); |
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 67bdb05798b1..94b8eb4d691d 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <pcmcia/device_id.h> | 32 | #include <pcmcia/device_id.h> |
33 | #include <pcmcia/ss.h> | 33 | #include <pcmcia/ss.h> |
34 | #include <pcmcia/ds.h> | 34 | #include <pcmcia/ds.h> |
35 | #include <pcmcia/cs.h> | ||
36 | 35 | ||
37 | static struct pcmcia_device_id ipw_ids[] = { | 36 | static struct pcmcia_device_id ipw_ids[] = { |
38 | PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), | 37 | PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), |
@@ -76,23 +75,18 @@ static void signalled_reboot_callback(void *callback_data) | |||
76 | schedule_work(&ipw->work_reboot); | 75 | schedule_work(&ipw->work_reboot); |
77 | } | 76 | } |
78 | 77 | ||
79 | static int ipwireless_probe(struct pcmcia_device *p_dev, | 78 | static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) |
80 | cistpl_cftable_entry_t *cfg, | ||
81 | cistpl_cftable_entry_t *dflt, | ||
82 | unsigned int vcc, | ||
83 | void *priv_data) | ||
84 | { | 79 | { |
85 | struct ipw_dev *ipw = priv_data; | 80 | struct ipw_dev *ipw = priv_data; |
86 | struct resource *io_resource; | 81 | struct resource *io_resource; |
87 | int ret; | 82 | int ret; |
88 | 83 | ||
84 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
89 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 85 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
90 | p_dev->resource[0]->start = cfg->io.win[0].base; | ||
91 | p_dev->resource[0]->end = cfg->io.win[0].len; | ||
92 | 86 | ||
93 | /* 0x40 causes it to generate level mode interrupts. */ | 87 | /* 0x40 causes it to generate level mode interrupts. */ |
94 | /* 0x04 enables IREQ pin. */ | 88 | /* 0x04 enables IREQ pin. */ |
95 | p_dev->conf.ConfigIndex = cfg->index | 0x44; | 89 | p_dev->config_index |= 0x44; |
96 | p_dev->io_lines = 16; | 90 | p_dev->io_lines = 16; |
97 | ret = pcmcia_request_io(p_dev); | 91 | ret = pcmcia_request_io(p_dev); |
98 | if (ret) | 92 | if (ret) |
@@ -102,65 +96,49 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, | |||
102 | resource_size(p_dev->resource[0]), | 96 | resource_size(p_dev->resource[0]), |
103 | IPWIRELESS_PCCARD_NAME); | 97 | IPWIRELESS_PCCARD_NAME); |
104 | 98 | ||
105 | if (cfg->mem.nwin == 0) | 99 | p_dev->resource[2]->flags |= |
106 | return 0; | ||
107 | |||
108 | ipw->request_common_memory.Attributes = | ||
109 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | 100 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
110 | ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; | ||
111 | ipw->request_common_memory.Size = cfg->mem.win[0].len; | ||
112 | if (ipw->request_common_memory.Size < 0x1000) | ||
113 | ipw->request_common_memory.Size = 0x1000; | ||
114 | ipw->request_common_memory.AccessSpeed = 0; | ||
115 | |||
116 | ret = pcmcia_request_window(p_dev, &ipw->request_common_memory, | ||
117 | &ipw->handle_common_memory); | ||
118 | 101 | ||
102 | ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0); | ||
119 | if (ret != 0) | 103 | if (ret != 0) |
120 | goto exit1; | 104 | goto exit1; |
121 | 105 | ||
122 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory, | 106 | ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr); |
123 | cfg->mem.win[0].card_addr); | ||
124 | |||
125 | if (ret != 0) | 107 | if (ret != 0) |
126 | goto exit2; | 108 | goto exit2; |
127 | 109 | ||
128 | ipw->is_v2_card = cfg->mem.win[0].len == 0x100; | 110 | ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100; |
129 | 111 | ||
130 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, | 112 | ipw->attr_memory = ioremap(p_dev->resource[2]->start, |
131 | ipw->request_common_memory.Size); | 113 | resource_size(p_dev->resource[2])); |
132 | request_mem_region(ipw->request_common_memory.Base, | 114 | request_mem_region(p_dev->resource[2]->start, |
133 | ipw->request_common_memory.Size, | 115 | resource_size(p_dev->resource[2]), |
134 | IPWIRELESS_PCCARD_NAME); | 116 | IPWIRELESS_PCCARD_NAME); |
135 | 117 | ||
136 | ipw->request_attr_memory.Attributes = | 118 | p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | |
137 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 119 | WIN_ENABLE; |
138 | ipw->request_attr_memory.Base = 0; | 120 | p_dev->resource[3]->end = 0; /* this used to be 0x1000 */ |
139 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 121 | ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0); |
140 | ipw->request_attr_memory.AccessSpeed = 0; | ||
141 | |||
142 | ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory, | ||
143 | &ipw->handle_attr_memory); | ||
144 | |||
145 | if (ret != 0) | 122 | if (ret != 0) |
146 | goto exit2; | 123 | goto exit2; |
147 | 124 | ||
148 | ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0); | 125 | ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0); |
149 | if (ret != 0) | 126 | if (ret != 0) |
150 | goto exit3; | 127 | goto exit3; |
151 | 128 | ||
152 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, | 129 | ipw->attr_memory = ioremap(p_dev->resource[3]->start, |
153 | ipw->request_attr_memory.Size); | 130 | resource_size(p_dev->resource[3])); |
154 | request_mem_region(ipw->request_attr_memory.Base, | 131 | request_mem_region(p_dev->resource[3]->start, |
155 | ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); | 132 | resource_size(p_dev->resource[3]), |
133 | IPWIRELESS_PCCARD_NAME); | ||
156 | 134 | ||
157 | return 0; | 135 | return 0; |
158 | 136 | ||
159 | exit3: | 137 | exit3: |
160 | exit2: | 138 | exit2: |
161 | if (ipw->common_memory) { | 139 | if (ipw->common_memory) { |
162 | release_mem_region(ipw->request_common_memory.Base, | 140 | release_mem_region(p_dev->resource[2]->start, |
163 | ipw->request_common_memory.Size); | 141 | resource_size(p_dev->resource[2])); |
164 | iounmap(ipw->common_memory); | 142 | iounmap(ipw->common_memory); |
165 | } | 143 | } |
166 | exit1: | 144 | exit1: |
@@ -175,14 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
175 | int ret = 0; | 153 | int ret = 0; |
176 | 154 | ||
177 | ipw->is_v2_card = 0; | 155 | ipw->is_v2_card = 0; |
156 | link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM | | ||
157 | CONF_ENABLE_IRQ; | ||
178 | 158 | ||
179 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); | 159 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); |
180 | if (ret != 0) | 160 | if (ret != 0) |
181 | return ret; | 161 | return ret; |
182 | 162 | ||
183 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
184 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
185 | |||
186 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 163 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
187 | 164 | ||
188 | ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, | 165 | ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start, |
@@ -201,13 +178,9 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
201 | (unsigned int) link->irq); | 178 | (unsigned int) link->irq); |
202 | if (ipw->attr_memory && ipw->common_memory) | 179 | if (ipw->attr_memory && ipw->common_memory) |
203 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME | 180 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME |
204 | ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", | 181 | ": attr memory %pR, common memory %pR\n", |
205 | ipw->request_attr_memory.Base, | 182 | link->resource[3], |
206 | ipw->request_attr_memory.Base | 183 | link->resource[2]); |
207 | + ipw->request_attr_memory.Size - 1, | ||
208 | ipw->request_common_memory.Base, | ||
209 | ipw->request_common_memory.Base | ||
210 | + ipw->request_common_memory.Size - 1); | ||
211 | 184 | ||
212 | ipw->network = ipwireless_network_create(ipw->hardware); | 185 | ipw->network = ipwireless_network_create(ipw->hardware); |
213 | if (!ipw->network) | 186 | if (!ipw->network) |
@@ -223,25 +196,23 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
223 | * Do the RequestConfiguration last, because it enables interrupts. | 196 | * Do the RequestConfiguration last, because it enables interrupts. |
224 | * Then we don't get any interrupts before we're ready for them. | 197 | * Then we don't get any interrupts before we're ready for them. |
225 | */ | 198 | */ |
226 | ret = pcmcia_request_configuration(link, &link->conf); | 199 | ret = pcmcia_enable_device(link); |
227 | |||
228 | if (ret != 0) | 200 | if (ret != 0) |
229 | goto exit; | 201 | goto exit; |
230 | 202 | ||
231 | return 0; | 203 | return 0; |
232 | 204 | ||
233 | exit: | 205 | exit: |
234 | if (ipw->attr_memory) { | ||
235 | release_mem_region(ipw->request_attr_memory.Base, | ||
236 | ipw->request_attr_memory.Size); | ||
237 | iounmap(ipw->attr_memory); | ||
238 | |||
239 | } | ||
240 | if (ipw->common_memory) { | 206 | if (ipw->common_memory) { |
241 | release_mem_region(ipw->request_common_memory.Base, | 207 | release_mem_region(link->resource[2]->start, |
242 | ipw->request_common_memory.Size); | 208 | resource_size(link->resource[2])); |
243 | iounmap(ipw->common_memory); | 209 | iounmap(ipw->common_memory); |
244 | } | 210 | } |
211 | if (ipw->attr_memory) { | ||
212 | release_mem_region(link->resource[3]->start, | ||
213 | resource_size(link->resource[3])); | ||
214 | iounmap(ipw->attr_memory); | ||
215 | } | ||
245 | pcmcia_disable_device(link); | 216 | pcmcia_disable_device(link); |
246 | return -1; | 217 | return -1; |
247 | } | 218 | } |
@@ -249,13 +220,13 @@ exit: | |||
249 | static void release_ipwireless(struct ipw_dev *ipw) | 220 | static void release_ipwireless(struct ipw_dev *ipw) |
250 | { | 221 | { |
251 | if (ipw->common_memory) { | 222 | if (ipw->common_memory) { |
252 | release_mem_region(ipw->request_common_memory.Base, | 223 | release_mem_region(ipw->link->resource[2]->start, |
253 | ipw->request_common_memory.Size); | 224 | resource_size(ipw->link->resource[2])); |
254 | iounmap(ipw->common_memory); | 225 | iounmap(ipw->common_memory); |
255 | } | 226 | } |
256 | if (ipw->attr_memory) { | 227 | if (ipw->attr_memory) { |
257 | release_mem_region(ipw->request_attr_memory.Base, | 228 | release_mem_region(ipw->link->resource[3]->start, |
258 | ipw->request_attr_memory.Size); | 229 | resource_size(ipw->link->resource[3])); |
259 | iounmap(ipw->attr_memory); | 230 | iounmap(ipw->attr_memory); |
260 | } | 231 | } |
261 | pcmcia_disable_device(ipw->link); | 232 | pcmcia_disable_device(ipw->link); |
@@ -324,7 +295,7 @@ static struct pcmcia_driver me = { | |||
324 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
325 | .probe = ipwireless_attach, | 296 | .probe = ipwireless_attach, |
326 | .remove = ipwireless_detach, | 297 | .remove = ipwireless_detach, |
327 | .drv = { .name = IPWIRELESS_PCCARD_NAME }, | 298 | .name = IPWIRELESS_PCCARD_NAME, |
328 | .id_table = ipw_ids | 299 | .id_table = ipw_ids |
329 | }; | 300 | }; |
330 | 301 | ||
@@ -336,9 +307,6 @@ static int __init init_ipwireless(void) | |||
336 | { | 307 | { |
337 | int ret; | 308 | int ret; |
338 | 309 | ||
339 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " | ||
340 | IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n"); | ||
341 | |||
342 | ret = ipwireless_tty_init(); | 310 | ret = ipwireless_tty_init(); |
343 | if (ret != 0) | 311 | if (ret != 0) |
344 | return ret; | 312 | return ret; |
@@ -355,9 +323,6 @@ static int __init init_ipwireless(void) | |||
355 | */ | 323 | */ |
356 | static void __exit exit_ipwireless(void) | 324 | static void __exit exit_ipwireless(void) |
357 | { | 325 | { |
358 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " | ||
359 | IPWIRELESS_PCMCIA_VERSION " removed\n"); | ||
360 | |||
361 | pcmcia_unregister_driver(&me); | 326 | pcmcia_unregister_driver(&me); |
362 | ipwireless_tty_release(); | 327 | ipwireless_tty_release(); |
363 | } | 328 | } |
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index c207be87b597..f2cbb116bccb 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | 23 | ||
24 | #include <pcmcia/cs.h> | ||
25 | #include <pcmcia/cistpl.h> | 24 | #include <pcmcia/cistpl.h> |
26 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
27 | 26 | ||
@@ -45,13 +44,9 @@ struct ipw_dev { | |||
45 | struct pcmcia_device *link; | 44 | struct pcmcia_device *link; |
46 | int is_v2_card; | 45 | int is_v2_card; |
47 | 46 | ||
48 | window_handle_t handle_attr_memory; | ||
49 | void __iomem *attr_memory; | 47 | void __iomem *attr_memory; |
50 | win_req_t request_attr_memory; | ||
51 | 48 | ||
52 | window_handle_t handle_common_memory; | ||
53 | void __iomem *common_memory; | 49 | void __iomem *common_memory; |
54 | win_req_t request_common_memory; | ||
55 | 50 | ||
56 | /* Reference to attribute memory, containing CIS data */ | 51 | /* Reference to attribute memory, containing CIS data */ |
57 | void *attribute_memory; | 52 | void *attribute_memory; |
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h index 3e163d4cab15..747b2d637860 100644 --- a/drivers/char/pcmcia/ipwireless/tty.h +++ b/drivers/char/pcmcia/ipwireless/tty.h | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | 23 | ||
24 | #include <pcmcia/cs.h> | ||
25 | #include <pcmcia/cistpl.h> | 24 | #include <pcmcia/cistpl.h> |
26 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
27 | 26 | ||
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 9ecd6bef5d3b..be1810057607 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -70,7 +70,6 @@ | |||
70 | #include <linux/workqueue.h> | 70 | #include <linux/workqueue.h> |
71 | #include <linux/hdlc.h> | 71 | #include <linux/hdlc.h> |
72 | 72 | ||
73 | #include <pcmcia/cs.h> | ||
74 | #include <pcmcia/cistpl.h> | 73 | #include <pcmcia/cistpl.h> |
75 | #include <pcmcia/cisreg.h> | 74 | #include <pcmcia/cisreg.h> |
76 | #include <pcmcia/ds.h> | 75 | #include <pcmcia/ds.h> |
@@ -550,9 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
550 | 549 | ||
551 | /* Initialize the struct pcmcia_device structure */ | 550 | /* Initialize the struct pcmcia_device structure */ |
552 | 551 | ||
553 | link->conf.Attributes = 0; | ||
554 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
555 | |||
556 | ret = mgslpc_config(link); | 552 | ret = mgslpc_config(link); |
557 | if (ret) | 553 | if (ret) |
558 | return ret; | 554 | return ret; |
@@ -565,20 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
565 | /* Card has been inserted. | 561 | /* Card has been inserted. |
566 | */ | 562 | */ |
567 | 563 | ||
568 | static int mgslpc_ioprobe(struct pcmcia_device *p_dev, | 564 | static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data) |
569 | cistpl_cftable_entry_t *cfg, | ||
570 | cistpl_cftable_entry_t *dflt, | ||
571 | unsigned int vcc, | ||
572 | void *priv_data) | ||
573 | { | 565 | { |
574 | if (!cfg->io.nwin) | ||
575 | return -ENODEV; | ||
576 | |||
577 | p_dev->resource[0]->start = cfg->io.win[0].base; | ||
578 | p_dev->resource[0]->end = cfg->io.win[0].len; | ||
579 | p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags); | ||
580 | p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
581 | |||
582 | return pcmcia_request_io(p_dev); | 566 | return pcmcia_request_io(p_dev); |
583 | } | 567 | } |
584 | 568 | ||
@@ -590,32 +574,24 @@ static int mgslpc_config(struct pcmcia_device *link) | |||
590 | if (debug_level >= DEBUG_LEVEL_INFO) | 574 | if (debug_level >= DEBUG_LEVEL_INFO) |
591 | printk("mgslpc_config(0x%p)\n", link); | 575 | printk("mgslpc_config(0x%p)\n", link); |
592 | 576 | ||
577 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
578 | |||
593 | ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); | 579 | ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); |
594 | if (ret != 0) | 580 | if (ret != 0) |
595 | goto failed; | 581 | goto failed; |
596 | 582 | ||
597 | link->conf.Attributes = CONF_ENABLE_IRQ; | 583 | link->config_index = 8; |
598 | link->conf.IntType = INT_MEMORY_AND_IO; | 584 | link->config_regs = PRESENT_OPTION; |
599 | link->conf.ConfigIndex = 8; | ||
600 | link->conf.Present = PRESENT_OPTION; | ||
601 | 585 | ||
602 | ret = pcmcia_request_irq(link, mgslpc_isr); | 586 | ret = pcmcia_request_irq(link, mgslpc_isr); |
603 | if (ret) | 587 | if (ret) |
604 | goto failed; | 588 | goto failed; |
605 | ret = pcmcia_request_configuration(link, &link->conf); | 589 | ret = pcmcia_enable_device(link); |
606 | if (ret) | 590 | if (ret) |
607 | goto failed; | 591 | goto failed; |
608 | 592 | ||
609 | info->io_base = link->resource[0]->start; | 593 | info->io_base = link->resource[0]->start; |
610 | info->irq_level = link->irq; | 594 | info->irq_level = link->irq; |
611 | |||
612 | dev_info(&link->dev, "index 0x%02x:", | ||
613 | link->conf.ConfigIndex); | ||
614 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
615 | printk(", irq %d", link->irq); | ||
616 | if (link->resource[0]) | ||
617 | printk(", io %pR", link->resource[0]); | ||
618 | printk("\n"); | ||
619 | return 0; | 595 | return 0; |
620 | 596 | ||
621 | failed: | 597 | failed: |
@@ -2797,9 +2773,7 @@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids); | |||
2797 | 2773 | ||
2798 | static struct pcmcia_driver mgslpc_driver = { | 2774 | static struct pcmcia_driver mgslpc_driver = { |
2799 | .owner = THIS_MODULE, | 2775 | .owner = THIS_MODULE, |
2800 | .drv = { | 2776 | .name = "synclink_cs", |
2801 | .name = "synclink_cs", | ||
2802 | }, | ||
2803 | .probe = mgslpc_probe, | 2777 | .probe = mgslpc_probe, |
2804 | .remove = mgslpc_detach, | 2778 | .remove = mgslpc_detach, |
2805 | .id_table = mgslpc_ids, | 2779 | .id_table = mgslpc_ids, |
@@ -2835,8 +2809,6 @@ static void synclink_cs_cleanup(void) | |||
2835 | { | 2809 | { |
2836 | int rc; | 2810 | int rc; |
2837 | 2811 | ||
2838 | printk("Unloading %s: version %s\n", driver_name, driver_version); | ||
2839 | |||
2840 | while(mgslpc_device_list) | 2812 | while(mgslpc_device_list) |
2841 | mgslpc_remove_device(mgslpc_device_list); | 2813 | mgslpc_remove_device(mgslpc_device_list); |
2842 | 2814 | ||
@@ -2859,8 +2831,6 @@ static int __init synclink_cs_init(void) | |||
2859 | BREAKPOINT(); | 2831 | BREAKPOINT(); |
2860 | } | 2832 | } |
2861 | 2833 | ||
2862 | printk("%s %s\n", driver_name, driver_version); | ||
2863 | |||
2864 | if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) | 2834 | if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) |
2865 | return rc; | 2835 | return rc; |
2866 | 2836 | ||
@@ -4127,6 +4097,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4127 | if (cmd != SIOCWANDEV) | 4097 | if (cmd != SIOCWANDEV) |
4128 | return hdlc_ioctl(dev, ifr, cmd); | 4098 | return hdlc_ioctl(dev, ifr, cmd); |
4129 | 4099 | ||
4100 | memset(&new_line, 0, size); | ||
4101 | |||
4130 | switch(ifr->ifr_settings.type) { | 4102 | switch(ifr->ifr_settings.type) { |
4131 | case IF_GET_IFACE: /* return current sync_serial_settings */ | 4103 | case IF_GET_IFACE: /* return current sync_serial_settings */ |
4132 | 4104 | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 05ad4a17a28f..7c4133582dba 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -47,6 +47,16 @@ enum tpm_duration { | |||
47 | #define TPM_MAX_PROTECTED_ORDINAL 12 | 47 | #define TPM_MAX_PROTECTED_ORDINAL 12 |
48 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF | 48 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF |
49 | 49 | ||
50 | /* | ||
51 | * Bug workaround - some TPM's don't flush the most | ||
52 | * recently changed pcr on suspend, so force the flush | ||
53 | * with an extend to the selected _unused_ non-volatile pcr. | ||
54 | */ | ||
55 | static int tpm_suspend_pcr; | ||
56 | module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); | ||
57 | MODULE_PARM_DESC(suspend_pcr, | ||
58 | "PCR to use for dummy writes to faciltate flush on suspend."); | ||
59 | |||
50 | static LIST_HEAD(tpm_chip_list); | 60 | static LIST_HEAD(tpm_chip_list); |
51 | static DEFINE_SPINLOCK(driver_lock); | 61 | static DEFINE_SPINLOCK(driver_lock); |
52 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); | 62 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); |
@@ -1077,18 +1087,6 @@ static struct tpm_input_header savestate_header = { | |||
1077 | .ordinal = TPM_ORD_SAVESTATE | 1087 | .ordinal = TPM_ORD_SAVESTATE |
1078 | }; | 1088 | }; |
1079 | 1089 | ||
1080 | /* Bug workaround - some TPM's don't flush the most | ||
1081 | * recently changed pcr on suspend, so force the flush | ||
1082 | * with an extend to the selected _unused_ non-volatile pcr. | ||
1083 | */ | ||
1084 | static int tpm_suspend_pcr; | ||
1085 | static int __init tpm_suspend_setup(char *str) | ||
1086 | { | ||
1087 | get_option(&str, &tpm_suspend_pcr); | ||
1088 | return 1; | ||
1089 | } | ||
1090 | __setup("tpm_suspend_pcr=", tpm_suspend_setup); | ||
1091 | |||
1092 | /* | 1090 | /* |
1093 | * We are about to suspend. Save the TPM state | 1091 | * We are about to suspend. Save the TPM state |
1094 | * so that it can be restored. | 1092 | * so that it can be restored. |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index c810481a5bc2..6c1b676643a9 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -48,6 +48,9 @@ struct ports_driver_data { | |||
48 | /* Used for exporting per-port information to debugfs */ | 48 | /* Used for exporting per-port information to debugfs */ |
49 | struct dentry *debugfs_dir; | 49 | struct dentry *debugfs_dir; |
50 | 50 | ||
51 | /* List of all the devices we're handling */ | ||
52 | struct list_head portdevs; | ||
53 | |||
51 | /* Number of devices this driver is handling */ | 54 | /* Number of devices this driver is handling */ |
52 | unsigned int index; | 55 | unsigned int index; |
53 | 56 | ||
@@ -108,6 +111,9 @@ struct port_buffer { | |||
108 | * ports for that device (vdev->priv). | 111 | * ports for that device (vdev->priv). |
109 | */ | 112 | */ |
110 | struct ports_device { | 113 | struct ports_device { |
114 | /* Next portdev in the list, head is in the pdrvdata struct */ | ||
115 | struct list_head list; | ||
116 | |||
111 | /* | 117 | /* |
112 | * Workqueue handlers where we process deferred work after | 118 | * Workqueue handlers where we process deferred work after |
113 | * notification | 119 | * notification |
@@ -178,15 +184,21 @@ struct port { | |||
178 | struct console cons; | 184 | struct console cons; |
179 | 185 | ||
180 | /* Each port associates with a separate char device */ | 186 | /* Each port associates with a separate char device */ |
181 | struct cdev cdev; | 187 | struct cdev *cdev; |
182 | struct device *dev; | 188 | struct device *dev; |
183 | 189 | ||
190 | /* Reference-counting to handle port hot-unplugs and file operations */ | ||
191 | struct kref kref; | ||
192 | |||
184 | /* A waitqueue for poll() or blocking read operations */ | 193 | /* A waitqueue for poll() or blocking read operations */ |
185 | wait_queue_head_t waitqueue; | 194 | wait_queue_head_t waitqueue; |
186 | 195 | ||
187 | /* The 'name' of the port that we expose via sysfs properties */ | 196 | /* The 'name' of the port that we expose via sysfs properties */ |
188 | char *name; | 197 | char *name; |
189 | 198 | ||
199 | /* We can notify apps of host connect / disconnect events via SIGIO */ | ||
200 | struct fasync_struct *async_queue; | ||
201 | |||
190 | /* The 'id' to identify the port with the Host */ | 202 | /* The 'id' to identify the port with the Host */ |
191 | u32 id; | 203 | u32 id; |
192 | 204 | ||
@@ -221,6 +233,41 @@ out: | |||
221 | return port; | 233 | return port; |
222 | } | 234 | } |
223 | 235 | ||
236 | static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, | ||
237 | dev_t dev) | ||
238 | { | ||
239 | struct port *port; | ||
240 | unsigned long flags; | ||
241 | |||
242 | spin_lock_irqsave(&portdev->ports_lock, flags); | ||
243 | list_for_each_entry(port, &portdev->ports, list) | ||
244 | if (port->cdev->dev == dev) | ||
245 | goto out; | ||
246 | port = NULL; | ||
247 | out: | ||
248 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | ||
249 | |||
250 | return port; | ||
251 | } | ||
252 | |||
253 | static struct port *find_port_by_devt(dev_t dev) | ||
254 | { | ||
255 | struct ports_device *portdev; | ||
256 | struct port *port; | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&pdrvdata_lock, flags); | ||
260 | list_for_each_entry(portdev, &pdrvdata.portdevs, list) { | ||
261 | port = find_port_by_devt_in_portdev(portdev, dev); | ||
262 | if (port) | ||
263 | goto out; | ||
264 | } | ||
265 | port = NULL; | ||
266 | out: | ||
267 | spin_unlock_irqrestore(&pdrvdata_lock, flags); | ||
268 | return port; | ||
269 | } | ||
270 | |||
224 | static struct port *find_port_by_id(struct ports_device *portdev, u32 id) | 271 | static struct port *find_port_by_id(struct ports_device *portdev, u32 id) |
225 | { | 272 | { |
226 | struct port *port; | 273 | struct port *port; |
@@ -410,7 +457,10 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
410 | static ssize_t send_control_msg(struct port *port, unsigned int event, | 457 | static ssize_t send_control_msg(struct port *port, unsigned int event, |
411 | unsigned int value) | 458 | unsigned int value) |
412 | { | 459 | { |
413 | return __send_control_msg(port->portdev, port->id, event, value); | 460 | /* Did the port get unplugged before userspace closed it? */ |
461 | if (port->portdev) | ||
462 | return __send_control_msg(port->portdev, port->id, event, value); | ||
463 | return 0; | ||
414 | } | 464 | } |
415 | 465 | ||
416 | /* Callers must take the port->outvq_lock */ | 466 | /* Callers must take the port->outvq_lock */ |
@@ -459,9 +509,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | |||
459 | 509 | ||
460 | /* | 510 | /* |
461 | * Wait till the host acknowledges it pushed out the data we | 511 | * Wait till the host acknowledges it pushed out the data we |
462 | * sent. This is done for ports in blocking mode or for data | 512 | * sent. This is done for data from the hvc_console; the tty |
463 | * from the hvc_console; the tty operations are performed with | 513 | * operations are performed with spinlocks held so we can't |
464 | * spinlocks held so we can't sleep here. | 514 | * sleep here. An alternative would be to copy the data to a |
515 | * buffer and relax the spinning requirement. The downside is | ||
516 | * we need to kmalloc a GFP_ATOMIC buffer each time the | ||
517 | * console driver writes something out. | ||
465 | */ | 518 | */ |
466 | while (!virtqueue_get_buf(out_vq, &len)) | 519 | while (!virtqueue_get_buf(out_vq, &len)) |
467 | cpu_relax(); | 520 | cpu_relax(); |
@@ -522,6 +575,10 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, | |||
522 | /* The condition that must be true for polling to end */ | 575 | /* The condition that must be true for polling to end */ |
523 | static bool will_read_block(struct port *port) | 576 | static bool will_read_block(struct port *port) |
524 | { | 577 | { |
578 | if (!port->guest_connected) { | ||
579 | /* Port got hot-unplugged. Let's exit. */ | ||
580 | return false; | ||
581 | } | ||
525 | return !port_has_data(port) && port->host_connected; | 582 | return !port_has_data(port) && port->host_connected; |
526 | } | 583 | } |
527 | 584 | ||
@@ -572,6 +629,9 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
572 | if (ret < 0) | 629 | if (ret < 0) |
573 | return ret; | 630 | return ret; |
574 | } | 631 | } |
632 | /* Port got hot-unplugged. */ | ||
633 | if (!port->guest_connected) | ||
634 | return -ENODEV; | ||
575 | /* | 635 | /* |
576 | * We could've received a disconnection message while we were | 636 | * We could've received a disconnection message while we were |
577 | * waiting for more data. | 637 | * waiting for more data. |
@@ -613,6 +673,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
613 | if (ret < 0) | 673 | if (ret < 0) |
614 | return ret; | 674 | return ret; |
615 | } | 675 | } |
676 | /* Port got hot-unplugged. */ | ||
677 | if (!port->guest_connected) | ||
678 | return -ENODEV; | ||
616 | 679 | ||
617 | count = min((size_t)(32 * 1024), count); | 680 | count = min((size_t)(32 * 1024), count); |
618 | 681 | ||
@@ -626,6 +689,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
626 | goto free_buf; | 689 | goto free_buf; |
627 | } | 690 | } |
628 | 691 | ||
692 | /* | ||
693 | * We now ask send_buf() to not spin for generic ports -- we | ||
694 | * can re-use the same code path that non-blocking file | ||
695 | * descriptors take for blocking file descriptors since the | ||
696 | * wait is already done and we're certain the write will go | ||
697 | * through to the host. | ||
698 | */ | ||
699 | nonblock = true; | ||
629 | ret = send_buf(port, buf, count, nonblock); | 700 | ret = send_buf(port, buf, count, nonblock); |
630 | 701 | ||
631 | if (nonblock && ret > 0) | 702 | if (nonblock && ret > 0) |
@@ -645,6 +716,10 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | |||
645 | port = filp->private_data; | 716 | port = filp->private_data; |
646 | poll_wait(filp, &port->waitqueue, wait); | 717 | poll_wait(filp, &port->waitqueue, wait); |
647 | 718 | ||
719 | if (!port->guest_connected) { | ||
720 | /* Port got unplugged */ | ||
721 | return POLLHUP; | ||
722 | } | ||
648 | ret = 0; | 723 | ret = 0; |
649 | if (!will_read_block(port)) | 724 | if (!will_read_block(port)) |
650 | ret |= POLLIN | POLLRDNORM; | 725 | ret |= POLLIN | POLLRDNORM; |
@@ -656,6 +731,8 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | |||
656 | return ret; | 731 | return ret; |
657 | } | 732 | } |
658 | 733 | ||
734 | static void remove_port(struct kref *kref); | ||
735 | |||
659 | static int port_fops_release(struct inode *inode, struct file *filp) | 736 | static int port_fops_release(struct inode *inode, struct file *filp) |
660 | { | 737 | { |
661 | struct port *port; | 738 | struct port *port; |
@@ -676,6 +753,16 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
676 | reclaim_consumed_buffers(port); | 753 | reclaim_consumed_buffers(port); |
677 | spin_unlock_irq(&port->outvq_lock); | 754 | spin_unlock_irq(&port->outvq_lock); |
678 | 755 | ||
756 | /* | ||
757 | * Locks aren't necessary here as a port can't be opened after | ||
758 | * unplug, and if a port isn't unplugged, a kref would already | ||
759 | * exist for the port. Plus, taking ports_lock here would | ||
760 | * create a dependency on other locks taken by functions | ||
761 | * inside remove_port if we're the last holder of the port, | ||
762 | * creating many problems. | ||
763 | */ | ||
764 | kref_put(&port->kref, remove_port); | ||
765 | |||
679 | return 0; | 766 | return 0; |
680 | } | 767 | } |
681 | 768 | ||
@@ -683,22 +770,31 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
683 | { | 770 | { |
684 | struct cdev *cdev = inode->i_cdev; | 771 | struct cdev *cdev = inode->i_cdev; |
685 | struct port *port; | 772 | struct port *port; |
773 | int ret; | ||
686 | 774 | ||
687 | port = container_of(cdev, struct port, cdev); | 775 | port = find_port_by_devt(cdev->dev); |
688 | filp->private_data = port; | 776 | filp->private_data = port; |
689 | 777 | ||
778 | /* Prevent against a port getting hot-unplugged at the same time */ | ||
779 | spin_lock_irq(&port->portdev->ports_lock); | ||
780 | kref_get(&port->kref); | ||
781 | spin_unlock_irq(&port->portdev->ports_lock); | ||
782 | |||
690 | /* | 783 | /* |
691 | * Don't allow opening of console port devices -- that's done | 784 | * Don't allow opening of console port devices -- that's done |
692 | * via /dev/hvc | 785 | * via /dev/hvc |
693 | */ | 786 | */ |
694 | if (is_console_port(port)) | 787 | if (is_console_port(port)) { |
695 | return -ENXIO; | 788 | ret = -ENXIO; |
789 | goto out; | ||
790 | } | ||
696 | 791 | ||
697 | /* Allow only one process to open a particular port at a time */ | 792 | /* Allow only one process to open a particular port at a time */ |
698 | spin_lock_irq(&port->inbuf_lock); | 793 | spin_lock_irq(&port->inbuf_lock); |
699 | if (port->guest_connected) { | 794 | if (port->guest_connected) { |
700 | spin_unlock_irq(&port->inbuf_lock); | 795 | spin_unlock_irq(&port->inbuf_lock); |
701 | return -EMFILE; | 796 | ret = -EMFILE; |
797 | goto out; | ||
702 | } | 798 | } |
703 | 799 | ||
704 | port->guest_connected = true; | 800 | port->guest_connected = true; |
@@ -713,10 +809,23 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
713 | reclaim_consumed_buffers(port); | 809 | reclaim_consumed_buffers(port); |
714 | spin_unlock_irq(&port->outvq_lock); | 810 | spin_unlock_irq(&port->outvq_lock); |
715 | 811 | ||
812 | nonseekable_open(inode, filp); | ||
813 | |||
716 | /* Notify host of port being opened */ | 814 | /* Notify host of port being opened */ |
717 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); | 815 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); |
718 | 816 | ||
719 | return 0; | 817 | return 0; |
818 | out: | ||
819 | kref_put(&port->kref, remove_port); | ||
820 | return ret; | ||
821 | } | ||
822 | |||
823 | static int port_fops_fasync(int fd, struct file *filp, int mode) | ||
824 | { | ||
825 | struct port *port; | ||
826 | |||
827 | port = filp->private_data; | ||
828 | return fasync_helper(fd, filp, mode, &port->async_queue); | ||
720 | } | 829 | } |
721 | 830 | ||
722 | /* | 831 | /* |
@@ -732,6 +841,8 @@ static const struct file_operations port_fops = { | |||
732 | .write = port_fops_write, | 841 | .write = port_fops_write, |
733 | .poll = port_fops_poll, | 842 | .poll = port_fops_poll, |
734 | .release = port_fops_release, | 843 | .release = port_fops_release, |
844 | .fasync = port_fops_fasync, | ||
845 | .llseek = no_llseek, | ||
735 | }; | 846 | }; |
736 | 847 | ||
737 | /* | 848 | /* |
@@ -990,6 +1101,12 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
990 | return nr_added_bufs; | 1101 | return nr_added_bufs; |
991 | } | 1102 | } |
992 | 1103 | ||
1104 | static void send_sigio_to_port(struct port *port) | ||
1105 | { | ||
1106 | if (port->async_queue && port->guest_connected) | ||
1107 | kill_fasync(&port->async_queue, SIGIO, POLL_OUT); | ||
1108 | } | ||
1109 | |||
993 | static int add_port(struct ports_device *portdev, u32 id) | 1110 | static int add_port(struct ports_device *portdev, u32 id) |
994 | { | 1111 | { |
995 | char debugfs_name[16]; | 1112 | char debugfs_name[16]; |
@@ -1004,6 +1121,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1004 | err = -ENOMEM; | 1121 | err = -ENOMEM; |
1005 | goto fail; | 1122 | goto fail; |
1006 | } | 1123 | } |
1124 | kref_init(&port->kref); | ||
1007 | 1125 | ||
1008 | port->portdev = portdev; | 1126 | port->portdev = portdev; |
1009 | port->id = id; | 1127 | port->id = id; |
@@ -1011,6 +1129,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1011 | port->name = NULL; | 1129 | port->name = NULL; |
1012 | port->inbuf = NULL; | 1130 | port->inbuf = NULL; |
1013 | port->cons.hvc = NULL; | 1131 | port->cons.hvc = NULL; |
1132 | port->async_queue = NULL; | ||
1014 | 1133 | ||
1015 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; | 1134 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; |
1016 | 1135 | ||
@@ -1021,14 +1140,20 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1021 | port->in_vq = portdev->in_vqs[port->id]; | 1140 | port->in_vq = portdev->in_vqs[port->id]; |
1022 | port->out_vq = portdev->out_vqs[port->id]; | 1141 | port->out_vq = portdev->out_vqs[port->id]; |
1023 | 1142 | ||
1024 | cdev_init(&port->cdev, &port_fops); | 1143 | port->cdev = cdev_alloc(); |
1144 | if (!port->cdev) { | ||
1145 | dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n"); | ||
1146 | err = -ENOMEM; | ||
1147 | goto free_port; | ||
1148 | } | ||
1149 | port->cdev->ops = &port_fops; | ||
1025 | 1150 | ||
1026 | devt = MKDEV(portdev->chr_major, id); | 1151 | devt = MKDEV(portdev->chr_major, id); |
1027 | err = cdev_add(&port->cdev, devt, 1); | 1152 | err = cdev_add(port->cdev, devt, 1); |
1028 | if (err < 0) { | 1153 | if (err < 0) { |
1029 | dev_err(&port->portdev->vdev->dev, | 1154 | dev_err(&port->portdev->vdev->dev, |
1030 | "Error %d adding cdev for port %u\n", err, id); | 1155 | "Error %d adding cdev for port %u\n", err, id); |
1031 | goto free_port; | 1156 | goto free_cdev; |
1032 | } | 1157 | } |
1033 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, | 1158 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, |
1034 | devt, port, "vport%up%u", | 1159 | devt, port, "vport%up%u", |
@@ -1093,7 +1218,7 @@ free_inbufs: | |||
1093 | free_device: | 1218 | free_device: |
1094 | device_destroy(pdrvdata.class, port->dev->devt); | 1219 | device_destroy(pdrvdata.class, port->dev->devt); |
1095 | free_cdev: | 1220 | free_cdev: |
1096 | cdev_del(&port->cdev); | 1221 | cdev_del(port->cdev); |
1097 | free_port: | 1222 | free_port: |
1098 | kfree(port); | 1223 | kfree(port); |
1099 | fail: | 1224 | fail: |
@@ -1102,21 +1227,45 @@ fail: | |||
1102 | return err; | 1227 | return err; |
1103 | } | 1228 | } |
1104 | 1229 | ||
1105 | /* Remove all port-specific data. */ | 1230 | /* No users remain, remove all port-specific data. */ |
1106 | static int remove_port(struct port *port) | 1231 | static void remove_port(struct kref *kref) |
1232 | { | ||
1233 | struct port *port; | ||
1234 | |||
1235 | port = container_of(kref, struct port, kref); | ||
1236 | |||
1237 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1238 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1239 | cdev_del(port->cdev); | ||
1240 | |||
1241 | kfree(port->name); | ||
1242 | |||
1243 | debugfs_remove(port->debugfs_file); | ||
1244 | |||
1245 | kfree(port); | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * Port got unplugged. Remove port from portdev's list and drop the | ||
1250 | * kref reference. If no userspace has this port opened, it will | ||
1251 | * result in immediate removal the port. | ||
1252 | */ | ||
1253 | static void unplug_port(struct port *port) | ||
1107 | { | 1254 | { |
1108 | struct port_buffer *buf; | 1255 | struct port_buffer *buf; |
1109 | 1256 | ||
1257 | spin_lock_irq(&port->portdev->ports_lock); | ||
1258 | list_del(&port->list); | ||
1259 | spin_unlock_irq(&port->portdev->ports_lock); | ||
1260 | |||
1110 | if (port->guest_connected) { | 1261 | if (port->guest_connected) { |
1111 | port->guest_connected = false; | 1262 | port->guest_connected = false; |
1112 | port->host_connected = false; | 1263 | port->host_connected = false; |
1113 | wake_up_interruptible(&port->waitqueue); | 1264 | wake_up_interruptible(&port->waitqueue); |
1114 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); | ||
1115 | } | ||
1116 | 1265 | ||
1117 | spin_lock_irq(&port->portdev->ports_lock); | 1266 | /* Let the app know the port is going down. */ |
1118 | list_del(&port->list); | 1267 | send_sigio_to_port(port); |
1119 | spin_unlock_irq(&port->portdev->ports_lock); | 1268 | } |
1120 | 1269 | ||
1121 | if (is_console_port(port)) { | 1270 | if (is_console_port(port)) { |
1122 | spin_lock_irq(&pdrvdata_lock); | 1271 | spin_lock_irq(&pdrvdata_lock); |
@@ -1135,9 +1284,6 @@ static int remove_port(struct port *port) | |||
1135 | hvc_remove(port->cons.hvc); | 1284 | hvc_remove(port->cons.hvc); |
1136 | #endif | 1285 | #endif |
1137 | } | 1286 | } |
1138 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1139 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1140 | cdev_del(&port->cdev); | ||
1141 | 1287 | ||
1142 | /* Remove unused data this port might have received. */ | 1288 | /* Remove unused data this port might have received. */ |
1143 | discard_port_data(port); | 1289 | discard_port_data(port); |
@@ -1148,12 +1294,19 @@ static int remove_port(struct port *port) | |||
1148 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1294 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
1149 | free_buf(buf); | 1295 | free_buf(buf); |
1150 | 1296 | ||
1151 | kfree(port->name); | 1297 | /* |
1152 | 1298 | * We should just assume the device itself has gone off -- | |
1153 | debugfs_remove(port->debugfs_file); | 1299 | * else a close on an open port later will try to send out a |
1300 | * control message. | ||
1301 | */ | ||
1302 | port->portdev = NULL; | ||
1154 | 1303 | ||
1155 | kfree(port); | 1304 | /* |
1156 | return 0; | 1305 | * Locks around here are not necessary - a port can't be |
1306 | * opened after we removed the port struct from ports_list | ||
1307 | * above. | ||
1308 | */ | ||
1309 | kref_put(&port->kref, remove_port); | ||
1157 | } | 1310 | } |
1158 | 1311 | ||
1159 | /* Any private messages that the Host and Guest want to share */ | 1312 | /* Any private messages that the Host and Guest want to share */ |
@@ -1192,7 +1345,7 @@ static void handle_control_message(struct ports_device *portdev, | |||
1192 | add_port(portdev, cpkt->id); | 1345 | add_port(portdev, cpkt->id); |
1193 | break; | 1346 | break; |
1194 | case VIRTIO_CONSOLE_PORT_REMOVE: | 1347 | case VIRTIO_CONSOLE_PORT_REMOVE: |
1195 | remove_port(port); | 1348 | unplug_port(port); |
1196 | break; | 1349 | break; |
1197 | case VIRTIO_CONSOLE_CONSOLE_PORT: | 1350 | case VIRTIO_CONSOLE_CONSOLE_PORT: |
1198 | if (!cpkt->value) | 1351 | if (!cpkt->value) |
@@ -1234,6 +1387,12 @@ static void handle_control_message(struct ports_device *portdev, | |||
1234 | spin_lock_irq(&port->outvq_lock); | 1387 | spin_lock_irq(&port->outvq_lock); |
1235 | reclaim_consumed_buffers(port); | 1388 | reclaim_consumed_buffers(port); |
1236 | spin_unlock_irq(&port->outvq_lock); | 1389 | spin_unlock_irq(&port->outvq_lock); |
1390 | |||
1391 | /* | ||
1392 | * If the guest is connected, it'll be interested in | ||
1393 | * knowing the host connection state changed. | ||
1394 | */ | ||
1395 | send_sigio_to_port(port); | ||
1237 | break; | 1396 | break; |
1238 | case VIRTIO_CONSOLE_PORT_NAME: | 1397 | case VIRTIO_CONSOLE_PORT_NAME: |
1239 | /* | 1398 | /* |
@@ -1330,6 +1489,9 @@ static void in_intr(struct virtqueue *vq) | |||
1330 | 1489 | ||
1331 | wake_up_interruptible(&port->waitqueue); | 1490 | wake_up_interruptible(&port->waitqueue); |
1332 | 1491 | ||
1492 | /* Send a SIGIO indicating new data in case the process asked for it */ | ||
1493 | send_sigio_to_port(port); | ||
1494 | |||
1333 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) | 1495 | if (is_console_port(port) && hvc_poll(port->cons.hvc)) |
1334 | hvc_kick(); | 1496 | hvc_kick(); |
1335 | } | 1497 | } |
@@ -1566,6 +1728,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1566 | add_port(portdev, 0); | 1728 | add_port(portdev, 0); |
1567 | } | 1729 | } |
1568 | 1730 | ||
1731 | spin_lock_irq(&pdrvdata_lock); | ||
1732 | list_add_tail(&portdev->list, &pdrvdata.portdevs); | ||
1733 | spin_unlock_irq(&pdrvdata_lock); | ||
1734 | |||
1569 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1735 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
1570 | VIRTIO_CONSOLE_DEVICE_READY, 1); | 1736 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
1571 | return 0; | 1737 | return 0; |
@@ -1589,23 +1755,41 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
1589 | { | 1755 | { |
1590 | struct ports_device *portdev; | 1756 | struct ports_device *portdev; |
1591 | struct port *port, *port2; | 1757 | struct port *port, *port2; |
1592 | struct port_buffer *buf; | ||
1593 | unsigned int len; | ||
1594 | 1758 | ||
1595 | portdev = vdev->priv; | 1759 | portdev = vdev->priv; |
1596 | 1760 | ||
1761 | spin_lock_irq(&pdrvdata_lock); | ||
1762 | list_del(&portdev->list); | ||
1763 | spin_unlock_irq(&pdrvdata_lock); | ||
1764 | |||
1765 | /* Disable interrupts for vqs */ | ||
1766 | vdev->config->reset(vdev); | ||
1767 | /* Finish up work that's lined up */ | ||
1597 | cancel_work_sync(&portdev->control_work); | 1768 | cancel_work_sync(&portdev->control_work); |
1598 | 1769 | ||
1599 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 1770 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
1600 | remove_port(port); | 1771 | unplug_port(port); |
1601 | 1772 | ||
1602 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1773 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
1603 | 1774 | ||
1604 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | 1775 | /* |
1605 | free_buf(buf); | 1776 | * When yanking out a device, we immediately lose the |
1777 | * (device-side) queues. So there's no point in keeping the | ||
1778 | * guest side around till we drop our final reference. This | ||
1779 | * also means that any ports which are in an open state will | ||
1780 | * have to just stop using the port, as the vqs are going | ||
1781 | * away. | ||
1782 | */ | ||
1783 | if (use_multiport(portdev)) { | ||
1784 | struct port_buffer *buf; | ||
1785 | unsigned int len; | ||
1606 | 1786 | ||
1607 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | 1787 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) |
1608 | free_buf(buf); | 1788 | free_buf(buf); |
1789 | |||
1790 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
1791 | free_buf(buf); | ||
1792 | } | ||
1609 | 1793 | ||
1610 | vdev->config->del_vqs(vdev); | 1794 | vdev->config->del_vqs(vdev); |
1611 | kfree(portdev->in_vqs); | 1795 | kfree(portdev->in_vqs); |
@@ -1652,6 +1836,7 @@ static int __init init(void) | |||
1652 | PTR_ERR(pdrvdata.debugfs_dir)); | 1836 | PTR_ERR(pdrvdata.debugfs_dir)); |
1653 | } | 1837 | } |
1654 | INIT_LIST_HEAD(&pdrvdata.consoles); | 1838 | INIT_LIST_HEAD(&pdrvdata.consoles); |
1839 | INIT_LIST_HEAD(&pdrvdata.portdevs); | ||
1655 | 1840 | ||
1656 | return register_virtio_driver(&virtio_console); | 1841 | return register_virtio_driver(&virtio_console); |
1657 | } | 1842 | } |
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 216f9d383b5b..effd140fc042 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c | |||
@@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) | |||
879 | dma->device_issue_pending = ioat2_issue_pending; | 879 | dma->device_issue_pending = ioat2_issue_pending; |
880 | dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; | 880 | dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; |
881 | dma->device_free_chan_resources = ioat2_free_chan_resources; | 881 | dma->device_free_chan_resources = ioat2_free_chan_resources; |
882 | dma->device_tx_status = ioat_tx_status; | 882 | dma->device_tx_status = ioat_dma_tx_status; |
883 | 883 | ||
884 | err = ioat_probe(device); | 884 | err = ioat_probe(device); |
885 | if (err) | 885 | if (err) |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 70bb350de996..9dbb28b9559f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -39,7 +39,7 @@ config EDAC_DEBUG | |||
39 | there're four debug levels (x=0,1,2,3 from low to high). | 39 | there're four debug levels (x=0,1,2,3 from low to high). |
40 | Usually you should select 'N'. | 40 | Usually you should select 'N'. |
41 | 41 | ||
42 | config EDAC_DECODE_MCE | 42 | config EDAC_DECODE_MCE |
43 | tristate "Decode MCEs in human-readable form (only on AMD for now)" | 43 | tristate "Decode MCEs in human-readable form (only on AMD for now)" |
44 | depends on CPU_SUP_AMD && X86_MCE | 44 | depends on CPU_SUP_AMD && X86_MCE |
45 | default y | 45 | default y |
@@ -51,6 +51,16 @@ config EDAC_DEBUG | |||
51 | which occur really early upon boot, before the module infrastructure | 51 | which occur really early upon boot, before the module infrastructure |
52 | has been initialized. | 52 | has been initialized. |
53 | 53 | ||
54 | config EDAC_MCE_INJ | ||
55 | tristate "Simple MCE injection interface over /sysfs" | ||
56 | depends on EDAC_DECODE_MCE | ||
57 | default n | ||
58 | help | ||
59 | This is a simple interface to inject MCEs over /sysfs and test | ||
60 | the MCE decoding code in EDAC. | ||
61 | |||
62 | This is currently AMD-only. | ||
63 | |||
54 | config EDAC_MM_EDAC | 64 | config EDAC_MM_EDAC |
55 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" | 65 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" |
56 | help | 66 | help |
@@ -66,13 +76,13 @@ config EDAC_MCE | |||
66 | 76 | ||
67 | config EDAC_AMD64 | 77 | config EDAC_AMD64 |
68 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" | 78 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" |
69 | depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE | 79 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE |
70 | help | 80 | help |
71 | Support for error detection and correction on the AMD 64 | 81 | Support for error detection and correction on the AMD 64 |
72 | Families of Memory Controllers (K8, F10h and F11h) | 82 | Families of Memory Controllers (K8, F10h and F11h) |
73 | 83 | ||
74 | config EDAC_AMD64_ERROR_INJECTION | 84 | config EDAC_AMD64_ERROR_INJECTION |
75 | bool "Sysfs Error Injection facilities" | 85 | bool "Sysfs HW Error injection facilities" |
76 | depends on EDAC_AMD64 | 86 | depends on EDAC_AMD64 |
77 | help | 87 | help |
78 | Recent Opterons (Family 10h and later) provide for Memory Error | 88 | Recent Opterons (Family 10h and later) provide for Memory Error |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index ca6b1bb24ccc..32c7bc93c525 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
@@ -17,6 +17,9 @@ ifdef CONFIG_PCI | |||
17 | edac_core-objs += edac_pci.o edac_pci_sysfs.o | 17 | edac_core-objs += edac_pci.o edac_pci_sysfs.o |
18 | endif | 18 | endif |
19 | 19 | ||
20 | obj-$(CONFIG_EDAC_MCE_INJ) += mce_amd_inj.o | ||
21 | |||
22 | edac_mce_amd-objs := mce_amd.o | ||
20 | obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o | 23 | obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o |
21 | 24 | ||
22 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o | 25 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e7d5d6b5dcf6..8521401bbd75 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | #include "amd64_edac.h" | 1 | #include "amd64_edac.h" |
2 | #include <asm/k8.h> | 2 | #include <asm/amd_nb.h> |
3 | 3 | ||
4 | static struct edac_pci_ctl_info *amd64_ctl_pci; | 4 | static struct edac_pci_ctl_info *amd64_ctl_pci; |
5 | 5 | ||
@@ -2073,11 +2073,18 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
2073 | amd64_handle_ue(mci, info); | 2073 | amd64_handle_ue(mci, info); |
2074 | } | 2074 | } |
2075 | 2075 | ||
2076 | void amd64_decode_bus_error(int node_id, struct err_regs *regs) | 2076 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) |
2077 | { | 2077 | { |
2078 | struct mem_ctl_info *mci = mci_lookup[node_id]; | 2078 | struct mem_ctl_info *mci = mci_lookup[node_id]; |
2079 | struct err_regs regs; | ||
2079 | 2080 | ||
2080 | __amd64_decode_bus_error(mci, regs); | 2081 | regs.nbsl = (u32) m->status; |
2082 | regs.nbsh = (u32)(m->status >> 32); | ||
2083 | regs.nbeal = (u32) m->addr; | ||
2084 | regs.nbeah = (u32)(m->addr >> 32); | ||
2085 | regs.nbcfg = nbcfg; | ||
2086 | |||
2087 | __amd64_decode_bus_error(mci, ®s); | ||
2081 | 2088 | ||
2082 | /* | 2089 | /* |
2083 | * Check the UE bit of the NB status high register, if set generate some | 2090 | * Check the UE bit of the NB status high register, if set generate some |
@@ -2086,7 +2093,7 @@ void amd64_decode_bus_error(int node_id, struct err_regs *regs) | |||
2086 | * | 2093 | * |
2087 | * FIXME: this should go somewhere else, if at all. | 2094 | * FIXME: this should go somewhere else, if at all. |
2088 | */ | 2095 | */ |
2089 | if (regs->nbsh & K8_NBSH_UC_ERR && !report_gart_errors) | 2096 | if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors) |
2090 | edac_mc_handle_ue_no_info(mci, "UE bit is set"); | 2097 | edac_mc_handle_ue_no_info(mci, "UE bit is set"); |
2091 | 2098 | ||
2092 | } | 2099 | } |
@@ -2927,7 +2934,7 @@ static int __init amd64_edac_init(void) | |||
2927 | * to finish initialization of the MC instances. | 2934 | * to finish initialization of the MC instances. |
2928 | */ | 2935 | */ |
2929 | err = -ENODEV; | 2936 | err = -ENODEV; |
2930 | for (nb = 0; nb < num_k8_northbridges; nb++) { | 2937 | for (nb = 0; nb < k8_northbridges.num; nb++) { |
2931 | if (!pvt_lookup[nb]) | 2938 | if (!pvt_lookup[nb]) |
2932 | continue; | 2939 | continue; |
2933 | 2940 | ||
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 613b9381e71a..044aee4f944d 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -72,7 +72,7 @@ | |||
72 | #include <linux/edac.h> | 72 | #include <linux/edac.h> |
73 | #include <asm/msr.h> | 73 | #include <asm/msr.h> |
74 | #include "edac_core.h" | 74 | #include "edac_core.h" |
75 | #include "edac_mce_amd.h" | 75 | #include "mce_amd.h" |
76 | 76 | ||
77 | #define amd64_printk(level, fmt, arg...) \ | 77 | #define amd64_printk(level, fmt, arg...) \ |
78 | edac_printk(level, "amd64", fmt, ##arg) | 78 | edac_printk(level, "amd64", fmt, ##arg) |
@@ -482,11 +482,10 @@ extern const char *rrrr_msgs[16]; | |||
482 | extern const char *to_msgs[2]; | 482 | extern const char *to_msgs[2]; |
483 | extern const char *pp_msgs[4]; | 483 | extern const char *pp_msgs[4]; |
484 | extern const char *ii_msgs[4]; | 484 | extern const char *ii_msgs[4]; |
485 | extern const char *ext_msgs[32]; | ||
486 | extern const char *htlink_msgs[8]; | 485 | extern const char *htlink_msgs[8]; |
487 | 486 | ||
488 | #ifdef CONFIG_EDAC_DEBUG | 487 | #ifdef CONFIG_EDAC_DEBUG |
489 | #define NUM_DBG_ATTRS 9 | 488 | #define NUM_DBG_ATTRS 5 |
490 | #else | 489 | #else |
491 | #define NUM_DBG_ATTRS 0 | 490 | #define NUM_DBG_ATTRS 0 |
492 | #endif | 491 | #endif |
diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c index 59cf2cf6e11e..e3562288f4ce 100644 --- a/drivers/edac/amd64_edac_dbg.c +++ b/drivers/edac/amd64_edac_dbg.c | |||
@@ -1,167 +1,16 @@ | |||
1 | #include "amd64_edac.h" | 1 | #include "amd64_edac.h" |
2 | 2 | ||
3 | /* | 3 | #define EDAC_DCT_ATTR_SHOW(reg) \ |
4 | * accept a hex value and store it into the virtual error register file, field: | 4 | static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \ |
5 | * nbeal and nbeah. Assume virtual error values have already been set for: NBSL, | 5 | { \ |
6 | * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and | 6 | struct amd64_pvt *pvt = mci->pvt_info; \ |
7 | * CHANNEL | 7 | return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \ |
8 | */ | ||
9 | static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data, | ||
10 | size_t count) | ||
11 | { | ||
12 | struct amd64_pvt *pvt = mci->pvt_info; | ||
13 | unsigned long long value; | ||
14 | int ret = 0; | ||
15 | |||
16 | ret = strict_strtoull(data, 16, &value); | ||
17 | if (ret != -EINVAL) { | ||
18 | debugf0("received NBEA= 0x%llx\n", value); | ||
19 | |||
20 | /* place the value into the virtual error packet */ | ||
21 | pvt->ctl_error_info.nbeal = (u32) value; | ||
22 | value >>= 32; | ||
23 | pvt->ctl_error_info.nbeah = (u32) value; | ||
24 | |||
25 | /* Process the Mapping request */ | ||
26 | /* TODO: Add race prevention */ | ||
27 | amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1); | ||
28 | |||
29 | return count; | ||
30 | } | ||
31 | return ret; | ||
32 | } | ||
33 | |||
34 | /* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */ | ||
35 | static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data) | ||
36 | { | ||
37 | struct amd64_pvt *pvt = mci->pvt_info; | ||
38 | u64 value; | ||
39 | |||
40 | value = pvt->ctl_error_info.nbeah; | ||
41 | value <<= 32; | ||
42 | value |= pvt->ctl_error_info.nbeal; | ||
43 | |||
44 | return sprintf(data, "%llx\n", value); | ||
45 | } | ||
46 | |||
47 | /* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */ | ||
48 | static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data, | ||
49 | size_t count) | ||
50 | { | ||
51 | struct amd64_pvt *pvt = mci->pvt_info; | ||
52 | unsigned long value; | ||
53 | int ret = 0; | ||
54 | |||
55 | ret = strict_strtoul(data, 16, &value); | ||
56 | if (ret != -EINVAL) { | ||
57 | debugf0("received NBSL= 0x%lx\n", value); | ||
58 | |||
59 | pvt->ctl_error_info.nbsl = (u32) value; | ||
60 | |||
61 | return count; | ||
62 | } | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | /* display back what the last NBSL value written */ | ||
67 | static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data) | ||
68 | { | ||
69 | struct amd64_pvt *pvt = mci->pvt_info; | ||
70 | u32 value; | ||
71 | |||
72 | value = pvt->ctl_error_info.nbsl; | ||
73 | |||
74 | return sprintf(data, "%x\n", value); | ||
75 | } | ||
76 | |||
77 | /* store the NBSH (MCA NB Status High) value user desires */ | ||
78 | static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data, | ||
79 | size_t count) | ||
80 | { | ||
81 | struct amd64_pvt *pvt = mci->pvt_info; | ||
82 | unsigned long value; | ||
83 | int ret = 0; | ||
84 | |||
85 | ret = strict_strtoul(data, 16, &value); | ||
86 | if (ret != -EINVAL) { | ||
87 | debugf0("received NBSH= 0x%lx\n", value); | ||
88 | |||
89 | pvt->ctl_error_info.nbsh = (u32) value; | ||
90 | |||
91 | return count; | ||
92 | } | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* display back what the last NBSH value written */ | ||
97 | static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data) | ||
98 | { | ||
99 | struct amd64_pvt *pvt = mci->pvt_info; | ||
100 | u32 value; | ||
101 | |||
102 | value = pvt->ctl_error_info.nbsh; | ||
103 | |||
104 | return sprintf(data, "%x\n", value); | ||
105 | } | 8 | } |
106 | 9 | ||
107 | /* accept and store the NBCFG (MCA NB Configuration) value user desires */ | 10 | EDAC_DCT_ATTR_SHOW(dhar); |
108 | static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci, | 11 | EDAC_DCT_ATTR_SHOW(dbam0); |
109 | const char *data, size_t count) | 12 | EDAC_DCT_ATTR_SHOW(top_mem); |
110 | { | 13 | EDAC_DCT_ATTR_SHOW(top_mem2); |
111 | struct amd64_pvt *pvt = mci->pvt_info; | ||
112 | unsigned long value; | ||
113 | int ret = 0; | ||
114 | |||
115 | ret = strict_strtoul(data, 16, &value); | ||
116 | if (ret != -EINVAL) { | ||
117 | debugf0("received NBCFG= 0x%lx\n", value); | ||
118 | |||
119 | pvt->ctl_error_info.nbcfg = (u32) value; | ||
120 | |||
121 | return count; | ||
122 | } | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | /* various show routines for the controls of a MCI */ | ||
127 | static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data) | ||
128 | { | ||
129 | struct amd64_pvt *pvt = mci->pvt_info; | ||
130 | |||
131 | return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg); | ||
132 | } | ||
133 | |||
134 | |||
135 | static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data) | ||
136 | { | ||
137 | struct amd64_pvt *pvt = mci->pvt_info; | ||
138 | |||
139 | return sprintf(data, "%x\n", pvt->dhar); | ||
140 | } | ||
141 | |||
142 | |||
143 | static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data) | ||
144 | { | ||
145 | struct amd64_pvt *pvt = mci->pvt_info; | ||
146 | |||
147 | return sprintf(data, "%x\n", pvt->dbam0); | ||
148 | } | ||
149 | |||
150 | |||
151 | static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data) | ||
152 | { | ||
153 | struct amd64_pvt *pvt = mci->pvt_info; | ||
154 | |||
155 | return sprintf(data, "%llx\n", pvt->top_mem); | ||
156 | } | ||
157 | |||
158 | |||
159 | static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data) | ||
160 | { | ||
161 | struct amd64_pvt *pvt = mci->pvt_info; | ||
162 | |||
163 | return sprintf(data, "%llx\n", pvt->top_mem2); | ||
164 | } | ||
165 | 14 | ||
166 | static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) | 15 | static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) |
167 | { | 16 | { |
@@ -182,38 +31,6 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { | |||
182 | 31 | ||
183 | { | 32 | { |
184 | .attr = { | 33 | .attr = { |
185 | .name = "nbea_ctl", | ||
186 | .mode = (S_IRUGO | S_IWUSR) | ||
187 | }, | ||
188 | .show = amd64_nbea_show, | ||
189 | .store = amd64_nbea_store, | ||
190 | }, | ||
191 | { | ||
192 | .attr = { | ||
193 | .name = "nbsl_ctl", | ||
194 | .mode = (S_IRUGO | S_IWUSR) | ||
195 | }, | ||
196 | .show = amd64_nbsl_show, | ||
197 | .store = amd64_nbsl_store, | ||
198 | }, | ||
199 | { | ||
200 | .attr = { | ||
201 | .name = "nbsh_ctl", | ||
202 | .mode = (S_IRUGO | S_IWUSR) | ||
203 | }, | ||
204 | .show = amd64_nbsh_show, | ||
205 | .store = amd64_nbsh_store, | ||
206 | }, | ||
207 | { | ||
208 | .attr = { | ||
209 | .name = "nbcfg_ctl", | ||
210 | .mode = (S_IRUGO | S_IWUSR) | ||
211 | }, | ||
212 | .show = amd64_nbcfg_show, | ||
213 | .store = amd64_nbcfg_store, | ||
214 | }, | ||
215 | { | ||
216 | .attr = { | ||
217 | .name = "dhar", | 34 | .name = "dhar", |
218 | .mode = (S_IRUGO) | 35 | .mode = (S_IRUGO) |
219 | }, | 36 | }, |
@@ -225,7 +42,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { | |||
225 | .name = "dbam", | 42 | .name = "dbam", |
226 | .mode = (S_IRUGO) | 43 | .mode = (S_IRUGO) |
227 | }, | 44 | }, |
228 | .show = amd64_dbam_show, | 45 | .show = amd64_dbam0_show, |
229 | .store = NULL, | 46 | .store = NULL, |
230 | }, | 47 | }, |
231 | { | 48 | { |
@@ -233,7 +50,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { | |||
233 | .name = "topmem", | 50 | .name = "topmem", |
234 | .mode = (S_IRUGO) | 51 | .mode = (S_IRUGO) |
235 | }, | 52 | }, |
236 | .show = amd64_topmem_show, | 53 | .show = amd64_top_mem_show, |
237 | .store = NULL, | 54 | .store = NULL, |
238 | }, | 55 | }, |
239 | { | 56 | { |
@@ -241,7 +58,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { | |||
241 | .name = "topmem2", | 58 | .name = "topmem2", |
242 | .mode = (S_IRUGO) | 59 | .mode = (S_IRUGO) |
243 | }, | 60 | }, |
244 | .show = amd64_topmem2_show, | 61 | .show = amd64_top_mem2_show, |
245 | .store = NULL, | 62 | .store = NULL, |
246 | }, | 63 | }, |
247 | { | 64 | { |
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index 070968178a24..2941dca91aae 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/ctype.h> | 13 | #include <linux/ctype.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/edac.h> | ||
16 | 17 | ||
17 | #include "edac_core.h" | 18 | #include "edac_core.h" |
18 | #include "edac_module.h" | 19 | #include "edac_module.h" |
@@ -235,7 +236,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) | |||
235 | debugf1("%s()\n", __func__); | 236 | debugf1("%s()\n", __func__); |
236 | 237 | ||
237 | /* get the /sys/devices/system/edac reference */ | 238 | /* get the /sys/devices/system/edac reference */ |
238 | edac_class = edac_get_edac_class(); | 239 | edac_class = edac_get_sysfs_class(); |
239 | if (edac_class == NULL) { | 240 | if (edac_class == NULL) { |
240 | debugf1("%s() no edac_class error\n", __func__); | 241 | debugf1("%s() no edac_class error\n", __func__); |
241 | err = -ENODEV; | 242 | err = -ENODEV; |
@@ -255,7 +256,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) | |||
255 | 256 | ||
256 | if (!try_module_get(edac_dev->owner)) { | 257 | if (!try_module_get(edac_dev->owner)) { |
257 | err = -ENODEV; | 258 | err = -ENODEV; |
258 | goto err_out; | 259 | goto err_mod_get; |
259 | } | 260 | } |
260 | 261 | ||
261 | /* register */ | 262 | /* register */ |
@@ -282,6 +283,9 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) | |||
282 | err_kobj_reg: | 283 | err_kobj_reg: |
283 | module_put(edac_dev->owner); | 284 | module_put(edac_dev->owner); |
284 | 285 | ||
286 | err_mod_get: | ||
287 | edac_put_sysfs_class(); | ||
288 | |||
285 | err_out: | 289 | err_out: |
286 | return err; | 290 | return err; |
287 | } | 291 | } |
@@ -290,12 +294,11 @@ err_out: | |||
290 | * edac_device_unregister_sysfs_main_kobj: | 294 | * edac_device_unregister_sysfs_main_kobj: |
291 | * the '..../edac/<name>' kobject | 295 | * the '..../edac/<name>' kobject |
292 | */ | 296 | */ |
293 | void edac_device_unregister_sysfs_main_kobj( | 297 | void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) |
294 | struct edac_device_ctl_info *edac_dev) | ||
295 | { | 298 | { |
296 | debugf0("%s()\n", __func__); | 299 | debugf0("%s()\n", __func__); |
297 | debugf4("%s() name of kobject is: %s\n", | 300 | debugf4("%s() name of kobject is: %s\n", |
298 | __func__, kobject_name(&edac_dev->kobj)); | 301 | __func__, kobject_name(&dev->kobj)); |
299 | 302 | ||
300 | /* | 303 | /* |
301 | * Unregister the edac device's kobject and | 304 | * Unregister the edac device's kobject and |
@@ -304,7 +307,8 @@ void edac_device_unregister_sysfs_main_kobj( | |||
304 | * a) module_put() this module | 307 | * a) module_put() this module |
305 | * b) 'kfree' the memory | 308 | * b) 'kfree' the memory |
306 | */ | 309 | */ |
307 | kobject_put(&edac_dev->kobj); | 310 | kobject_put(&dev->kobj); |
311 | edac_put_sysfs_class(); | ||
308 | } | 312 | } |
309 | 313 | ||
310 | /* edac_dev -> instance information */ | 314 | /* edac_dev -> instance information */ |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 8aad94d10c0c..a4135860149b 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/edac.h> | ||
14 | #include <linux/bug.h> | 15 | #include <linux/bug.h> |
15 | 16 | ||
16 | #include "edac_core.h" | 17 | #include "edac_core.h" |
@@ -1011,13 +1012,13 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) | |||
1011 | */ | 1012 | */ |
1012 | int edac_sysfs_setup_mc_kset(void) | 1013 | int edac_sysfs_setup_mc_kset(void) |
1013 | { | 1014 | { |
1014 | int err = 0; | 1015 | int err = -EINVAL; |
1015 | struct sysdev_class *edac_class; | 1016 | struct sysdev_class *edac_class; |
1016 | 1017 | ||
1017 | debugf1("%s()\n", __func__); | 1018 | debugf1("%s()\n", __func__); |
1018 | 1019 | ||
1019 | /* get the /sys/devices/system/edac class reference */ | 1020 | /* get the /sys/devices/system/edac class reference */ |
1020 | edac_class = edac_get_edac_class(); | 1021 | edac_class = edac_get_sysfs_class(); |
1021 | if (edac_class == NULL) { | 1022 | if (edac_class == NULL) { |
1022 | debugf1("%s() no edac_class error=%d\n", __func__, err); | 1023 | debugf1("%s() no edac_class error=%d\n", __func__, err); |
1023 | goto fail_out; | 1024 | goto fail_out; |
@@ -1028,15 +1029,16 @@ int edac_sysfs_setup_mc_kset(void) | |||
1028 | if (!mc_kset) { | 1029 | if (!mc_kset) { |
1029 | err = -ENOMEM; | 1030 | err = -ENOMEM; |
1030 | debugf1("%s() Failed to register '.../edac/mc'\n", __func__); | 1031 | debugf1("%s() Failed to register '.../edac/mc'\n", __func__); |
1031 | goto fail_out; | 1032 | goto fail_kset; |
1032 | } | 1033 | } |
1033 | 1034 | ||
1034 | debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); | 1035 | debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); |
1035 | 1036 | ||
1036 | return 0; | 1037 | return 0; |
1037 | 1038 | ||
1039 | fail_kset: | ||
1040 | edac_put_sysfs_class(); | ||
1038 | 1041 | ||
1039 | /* error unwind stack */ | ||
1040 | fail_out: | 1042 | fail_out: |
1041 | return err; | 1043 | return err; |
1042 | } | 1044 | } |
@@ -1049,5 +1051,6 @@ fail_out: | |||
1049 | void edac_sysfs_teardown_mc_kset(void) | 1051 | void edac_sysfs_teardown_mc_kset(void) |
1050 | { | 1052 | { |
1051 | kset_unregister(mc_kset); | 1053 | kset_unregister(mc_kset); |
1054 | edac_put_sysfs_class(); | ||
1052 | } | 1055 | } |
1053 | 1056 | ||
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c deleted file mode 100644 index 9014df6f605d..000000000000 --- a/drivers/edac/edac_mce_amd.c +++ /dev/null | |||
@@ -1,452 +0,0 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include "edac_mce_amd.h" | ||
3 | |||
4 | static bool report_gart_errors; | ||
5 | static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); | ||
6 | |||
7 | void amd_report_gart_errors(bool v) | ||
8 | { | ||
9 | report_gart_errors = v; | ||
10 | } | ||
11 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); | ||
12 | |||
13 | void amd_register_ecc_decoder(void (*f)(int, struct err_regs *)) | ||
14 | { | ||
15 | nb_bus_decoder = f; | ||
16 | } | ||
17 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); | ||
18 | |||
19 | void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *)) | ||
20 | { | ||
21 | if (nb_bus_decoder) { | ||
22 | WARN_ON(nb_bus_decoder != f); | ||
23 | |||
24 | nb_bus_decoder = NULL; | ||
25 | } | ||
26 | } | ||
27 | EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder); | ||
28 | |||
29 | /* | ||
30 | * string representation for the different MCA reported error types, see F3x48 | ||
31 | * or MSR0000_0411. | ||
32 | */ | ||
33 | const char *tt_msgs[] = { /* transaction type */ | ||
34 | "instruction", | ||
35 | "data", | ||
36 | "generic", | ||
37 | "reserved" | ||
38 | }; | ||
39 | EXPORT_SYMBOL_GPL(tt_msgs); | ||
40 | |||
41 | const char *ll_msgs[] = { /* cache level */ | ||
42 | "L0", | ||
43 | "L1", | ||
44 | "L2", | ||
45 | "L3/generic" | ||
46 | }; | ||
47 | EXPORT_SYMBOL_GPL(ll_msgs); | ||
48 | |||
49 | const char *rrrr_msgs[] = { | ||
50 | "generic", | ||
51 | "generic read", | ||
52 | "generic write", | ||
53 | "data read", | ||
54 | "data write", | ||
55 | "inst fetch", | ||
56 | "prefetch", | ||
57 | "evict", | ||
58 | "snoop", | ||
59 | "reserved RRRR= 9", | ||
60 | "reserved RRRR= 10", | ||
61 | "reserved RRRR= 11", | ||
62 | "reserved RRRR= 12", | ||
63 | "reserved RRRR= 13", | ||
64 | "reserved RRRR= 14", | ||
65 | "reserved RRRR= 15" | ||
66 | }; | ||
67 | EXPORT_SYMBOL_GPL(rrrr_msgs); | ||
68 | |||
69 | const char *pp_msgs[] = { /* participating processor */ | ||
70 | "local node originated (SRC)", | ||
71 | "local node responded to request (RES)", | ||
72 | "local node observed as 3rd party (OBS)", | ||
73 | "generic" | ||
74 | }; | ||
75 | EXPORT_SYMBOL_GPL(pp_msgs); | ||
76 | |||
77 | const char *to_msgs[] = { | ||
78 | "no timeout", | ||
79 | "timed out" | ||
80 | }; | ||
81 | EXPORT_SYMBOL_GPL(to_msgs); | ||
82 | |||
83 | const char *ii_msgs[] = { /* memory or i/o */ | ||
84 | "mem access", | ||
85 | "reserved", | ||
86 | "i/o access", | ||
87 | "generic" | ||
88 | }; | ||
89 | EXPORT_SYMBOL_GPL(ii_msgs); | ||
90 | |||
91 | /* | ||
92 | * Map the 4 or 5 (family-specific) bits of Extended Error code to the | ||
93 | * string table. | ||
94 | */ | ||
95 | const char *ext_msgs[] = { | ||
96 | "K8 ECC error", /* 0_0000b */ | ||
97 | "CRC error on link", /* 0_0001b */ | ||
98 | "Sync error packets on link", /* 0_0010b */ | ||
99 | "Master Abort during link operation", /* 0_0011b */ | ||
100 | "Target Abort during link operation", /* 0_0100b */ | ||
101 | "Invalid GART PTE entry during table walk", /* 0_0101b */ | ||
102 | "Unsupported atomic RMW command received", /* 0_0110b */ | ||
103 | "WDT error: NB transaction timeout", /* 0_0111b */ | ||
104 | "ECC/ChipKill ECC error", /* 0_1000b */ | ||
105 | "SVM DEV Error", /* 0_1001b */ | ||
106 | "Link Data error", /* 0_1010b */ | ||
107 | "Link/L3/Probe Filter Protocol error", /* 0_1011b */ | ||
108 | "NB Internal Arrays Parity error", /* 0_1100b */ | ||
109 | "DRAM Address/Control Parity error", /* 0_1101b */ | ||
110 | "Link Transmission error", /* 0_1110b */ | ||
111 | "GART/DEV Table Walk Data error" /* 0_1111b */ | ||
112 | "Res 0x100 error", /* 1_0000b */ | ||
113 | "Res 0x101 error", /* 1_0001b */ | ||
114 | "Res 0x102 error", /* 1_0010b */ | ||
115 | "Res 0x103 error", /* 1_0011b */ | ||
116 | "Res 0x104 error", /* 1_0100b */ | ||
117 | "Res 0x105 error", /* 1_0101b */ | ||
118 | "Res 0x106 error", /* 1_0110b */ | ||
119 | "Res 0x107 error", /* 1_0111b */ | ||
120 | "Res 0x108 error", /* 1_1000b */ | ||
121 | "Res 0x109 error", /* 1_1001b */ | ||
122 | "Res 0x10A error", /* 1_1010b */ | ||
123 | "Res 0x10B error", /* 1_1011b */ | ||
124 | "ECC error in L3 Cache Data", /* 1_1100b */ | ||
125 | "L3 Cache Tag error", /* 1_1101b */ | ||
126 | "L3 Cache LRU Parity error", /* 1_1110b */ | ||
127 | "Probe Filter error" /* 1_1111b */ | ||
128 | }; | ||
129 | EXPORT_SYMBOL_GPL(ext_msgs); | ||
130 | |||
131 | static void amd_decode_dc_mce(u64 mc0_status) | ||
132 | { | ||
133 | u32 ec = mc0_status & 0xffff; | ||
134 | u32 xec = (mc0_status >> 16) & 0xf; | ||
135 | |||
136 | pr_emerg("Data Cache Error"); | ||
137 | |||
138 | if (xec == 1 && TLB_ERROR(ec)) | ||
139 | pr_cont(": %s TLB multimatch.\n", LL_MSG(ec)); | ||
140 | else if (xec == 0) { | ||
141 | if (mc0_status & (1ULL << 40)) | ||
142 | pr_cont(" during Data Scrub.\n"); | ||
143 | else if (TLB_ERROR(ec)) | ||
144 | pr_cont(": %s TLB parity error.\n", LL_MSG(ec)); | ||
145 | else if (MEM_ERROR(ec)) { | ||
146 | u8 ll = ec & 0x3; | ||
147 | u8 tt = (ec >> 2) & 0x3; | ||
148 | u8 rrrr = (ec >> 4) & 0xf; | ||
149 | |||
150 | /* see F10h BKDG (31116), Table 92. */ | ||
151 | if (ll == 0x1) { | ||
152 | if (tt != 0x1) | ||
153 | goto wrong_dc_mce; | ||
154 | |||
155 | pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec)); | ||
156 | |||
157 | } else if (ll == 0x2 && rrrr == 0x3) | ||
158 | pr_cont(" during L1 linefill from L2.\n"); | ||
159 | else | ||
160 | goto wrong_dc_mce; | ||
161 | } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf) | ||
162 | pr_cont(" during system linefill.\n"); | ||
163 | else | ||
164 | goto wrong_dc_mce; | ||
165 | } else | ||
166 | goto wrong_dc_mce; | ||
167 | |||
168 | return; | ||
169 | |||
170 | wrong_dc_mce: | ||
171 | pr_warning("Corrupted DC MCE info?\n"); | ||
172 | } | ||
173 | |||
174 | static void amd_decode_ic_mce(u64 mc1_status) | ||
175 | { | ||
176 | u32 ec = mc1_status & 0xffff; | ||
177 | u32 xec = (mc1_status >> 16) & 0xf; | ||
178 | |||
179 | pr_emerg("Instruction Cache Error"); | ||
180 | |||
181 | if (xec == 1 && TLB_ERROR(ec)) | ||
182 | pr_cont(": %s TLB multimatch.\n", LL_MSG(ec)); | ||
183 | else if (xec == 0) { | ||
184 | if (TLB_ERROR(ec)) | ||
185 | pr_cont(": %s TLB Parity error.\n", LL_MSG(ec)); | ||
186 | else if (BUS_ERROR(ec)) { | ||
187 | if (boot_cpu_data.x86 == 0xf && | ||
188 | (mc1_status & (1ULL << 58))) | ||
189 | pr_cont(" during system linefill.\n"); | ||
190 | else | ||
191 | pr_cont(" during attempted NB data read.\n"); | ||
192 | } else if (MEM_ERROR(ec)) { | ||
193 | u8 ll = ec & 0x3; | ||
194 | u8 rrrr = (ec >> 4) & 0xf; | ||
195 | |||
196 | if (ll == 0x2) | ||
197 | pr_cont(" during a linefill from L2.\n"); | ||
198 | else if (ll == 0x1) { | ||
199 | |||
200 | switch (rrrr) { | ||
201 | case 0x5: | ||
202 | pr_cont(": Parity error during " | ||
203 | "data load.\n"); | ||
204 | break; | ||
205 | |||
206 | case 0x7: | ||
207 | pr_cont(": Copyback Parity/Victim" | ||
208 | " error.\n"); | ||
209 | break; | ||
210 | |||
211 | case 0x8: | ||
212 | pr_cont(": Tag Snoop error.\n"); | ||
213 | break; | ||
214 | |||
215 | default: | ||
216 | goto wrong_ic_mce; | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | } else | ||
221 | goto wrong_ic_mce; | ||
222 | } else | ||
223 | goto wrong_ic_mce; | ||
224 | |||
225 | return; | ||
226 | |||
227 | wrong_ic_mce: | ||
228 | pr_warning("Corrupted IC MCE info?\n"); | ||
229 | } | ||
230 | |||
231 | static void amd_decode_bu_mce(u64 mc2_status) | ||
232 | { | ||
233 | u32 ec = mc2_status & 0xffff; | ||
234 | u32 xec = (mc2_status >> 16) & 0xf; | ||
235 | |||
236 | pr_emerg("Bus Unit Error"); | ||
237 | |||
238 | if (xec == 0x1) | ||
239 | pr_cont(" in the write data buffers.\n"); | ||
240 | else if (xec == 0x3) | ||
241 | pr_cont(" in the victim data buffers.\n"); | ||
242 | else if (xec == 0x2 && MEM_ERROR(ec)) | ||
243 | pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec)); | ||
244 | else if (xec == 0x0) { | ||
245 | if (TLB_ERROR(ec)) | ||
246 | pr_cont(": %s error in a Page Descriptor Cache or " | ||
247 | "Guest TLB.\n", TT_MSG(ec)); | ||
248 | else if (BUS_ERROR(ec)) | ||
249 | pr_cont(": %s/ECC error in data read from NB: %s.\n", | ||
250 | RRRR_MSG(ec), PP_MSG(ec)); | ||
251 | else if (MEM_ERROR(ec)) { | ||
252 | u8 rrrr = (ec >> 4) & 0xf; | ||
253 | |||
254 | if (rrrr >= 0x7) | ||
255 | pr_cont(": %s error during data copyback.\n", | ||
256 | RRRR_MSG(ec)); | ||
257 | else if (rrrr <= 0x1) | ||
258 | pr_cont(": %s parity/ECC error during data " | ||
259 | "access from L2.\n", RRRR_MSG(ec)); | ||
260 | else | ||
261 | goto wrong_bu_mce; | ||
262 | } else | ||
263 | goto wrong_bu_mce; | ||
264 | } else | ||
265 | goto wrong_bu_mce; | ||
266 | |||
267 | return; | ||
268 | |||
269 | wrong_bu_mce: | ||
270 | pr_warning("Corrupted BU MCE info?\n"); | ||
271 | } | ||
272 | |||
273 | static void amd_decode_ls_mce(u64 mc3_status) | ||
274 | { | ||
275 | u32 ec = mc3_status & 0xffff; | ||
276 | u32 xec = (mc3_status >> 16) & 0xf; | ||
277 | |||
278 | pr_emerg("Load Store Error"); | ||
279 | |||
280 | if (xec == 0x0) { | ||
281 | u8 rrrr = (ec >> 4) & 0xf; | ||
282 | |||
283 | if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4)) | ||
284 | goto wrong_ls_mce; | ||
285 | |||
286 | pr_cont(" during %s.\n", RRRR_MSG(ec)); | ||
287 | } | ||
288 | return; | ||
289 | |||
290 | wrong_ls_mce: | ||
291 | pr_warning("Corrupted LS MCE info?\n"); | ||
292 | } | ||
293 | |||
294 | void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors) | ||
295 | { | ||
296 | u32 ec = ERROR_CODE(regs->nbsl); | ||
297 | |||
298 | if (!handle_errors) | ||
299 | return; | ||
300 | |||
301 | /* | ||
302 | * GART TLB error reporting is disabled by default. Bail out early. | ||
303 | */ | ||
304 | if (TLB_ERROR(ec) && !report_gart_errors) | ||
305 | return; | ||
306 | |||
307 | pr_emerg("Northbridge Error, node %d", node_id); | ||
308 | |||
309 | /* | ||
310 | * F10h, revD can disable ErrCpu[3:0] so check that first and also the | ||
311 | * value encoding has changed so interpret those differently | ||
312 | */ | ||
313 | if ((boot_cpu_data.x86 == 0x10) && | ||
314 | (boot_cpu_data.x86_model > 7)) { | ||
315 | if (regs->nbsh & K8_NBSH_ERR_CPU_VAL) | ||
316 | pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf)); | ||
317 | } else { | ||
318 | u8 assoc_cpus = regs->nbsh & 0xf; | ||
319 | |||
320 | if (assoc_cpus > 0) | ||
321 | pr_cont(", core: %d", fls(assoc_cpus) - 1); | ||
322 | |||
323 | pr_cont("\n"); | ||
324 | } | ||
325 | |||
326 | pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl)); | ||
327 | |||
328 | if (BUS_ERROR(ec) && nb_bus_decoder) | ||
329 | nb_bus_decoder(node_id, regs); | ||
330 | } | ||
331 | EXPORT_SYMBOL_GPL(amd_decode_nb_mce); | ||
332 | |||
333 | static void amd_decode_fr_mce(u64 mc5_status) | ||
334 | { | ||
335 | /* we have only one error signature so match all fields at once. */ | ||
336 | if ((mc5_status & 0xffff) == 0x0f0f) | ||
337 | pr_emerg(" FR Error: CPU Watchdog timer expire.\n"); | ||
338 | else | ||
339 | pr_warning("Corrupted FR MCE info?\n"); | ||
340 | } | ||
341 | |||
342 | static inline void amd_decode_err_code(unsigned int ec) | ||
343 | { | ||
344 | if (TLB_ERROR(ec)) { | ||
345 | pr_emerg("Transaction: %s, Cache Level %s\n", | ||
346 | TT_MSG(ec), LL_MSG(ec)); | ||
347 | } else if (MEM_ERROR(ec)) { | ||
348 | pr_emerg("Transaction: %s, Type: %s, Cache Level: %s", | ||
349 | RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec)); | ||
350 | } else if (BUS_ERROR(ec)) { | ||
351 | pr_emerg("Transaction type: %s(%s), %s, Cache Level: %s, " | ||
352 | "Participating Processor: %s\n", | ||
353 | RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec), | ||
354 | PP_MSG(ec)); | ||
355 | } else | ||
356 | pr_warning("Huh? Unknown MCE error 0x%x\n", ec); | ||
357 | } | ||
358 | |||
359 | static int amd_decode_mce(struct notifier_block *nb, unsigned long val, | ||
360 | void *data) | ||
361 | { | ||
362 | struct mce *m = (struct mce *)data; | ||
363 | struct err_regs regs; | ||
364 | int node, ecc; | ||
365 | |||
366 | pr_emerg("MC%d_STATUS: ", m->bank); | ||
367 | |||
368 | pr_cont("%sorrected error, other errors lost: %s, " | ||
369 | "CPU context corrupt: %s", | ||
370 | ((m->status & MCI_STATUS_UC) ? "Unc" : "C"), | ||
371 | ((m->status & MCI_STATUS_OVER) ? "yes" : "no"), | ||
372 | ((m->status & MCI_STATUS_PCC) ? "yes" : "no")); | ||
373 | |||
374 | /* do the two bits[14:13] together */ | ||
375 | ecc = (m->status >> 45) & 0x3; | ||
376 | if (ecc) | ||
377 | pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); | ||
378 | |||
379 | pr_cont("\n"); | ||
380 | |||
381 | switch (m->bank) { | ||
382 | case 0: | ||
383 | amd_decode_dc_mce(m->status); | ||
384 | break; | ||
385 | |||
386 | case 1: | ||
387 | amd_decode_ic_mce(m->status); | ||
388 | break; | ||
389 | |||
390 | case 2: | ||
391 | amd_decode_bu_mce(m->status); | ||
392 | break; | ||
393 | |||
394 | case 3: | ||
395 | amd_decode_ls_mce(m->status); | ||
396 | break; | ||
397 | |||
398 | case 4: | ||
399 | regs.nbsl = (u32) m->status; | ||
400 | regs.nbsh = (u32)(m->status >> 32); | ||
401 | regs.nbeal = (u32) m->addr; | ||
402 | regs.nbeah = (u32)(m->addr >> 32); | ||
403 | node = amd_get_nb_id(m->extcpu); | ||
404 | |||
405 | amd_decode_nb_mce(node, ®s, 1); | ||
406 | break; | ||
407 | |||
408 | case 5: | ||
409 | amd_decode_fr_mce(m->status); | ||
410 | break; | ||
411 | |||
412 | default: | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | amd_decode_err_code(m->status & 0xffff); | ||
417 | |||
418 | return NOTIFY_STOP; | ||
419 | } | ||
420 | |||
421 | static struct notifier_block amd_mce_dec_nb = { | ||
422 | .notifier_call = amd_decode_mce, | ||
423 | }; | ||
424 | |||
425 | static int __init mce_amd_init(void) | ||
426 | { | ||
427 | /* | ||
428 | * We can decode MCEs for K8, F10h and F11h CPUs: | ||
429 | */ | ||
430 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||
431 | return 0; | ||
432 | |||
433 | if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11) | ||
434 | return 0; | ||
435 | |||
436 | atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | early_initcall(mce_amd_init); | ||
441 | |||
442 | #ifdef MODULE | ||
443 | static void __exit mce_amd_exit(void) | ||
444 | { | ||
445 | atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb); | ||
446 | } | ||
447 | |||
448 | MODULE_DESCRIPTION("AMD MCE decoder"); | ||
449 | MODULE_ALIAS("edac-mce-amd"); | ||
450 | MODULE_LICENSE("GPL"); | ||
451 | module_exit(mce_amd_exit); | ||
452 | #endif | ||
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 7e1374afd967..be4b075c3098 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c | |||
@@ -27,15 +27,6 @@ EXPORT_SYMBOL_GPL(edac_debug_level); | |||
27 | struct workqueue_struct *edac_workqueue; | 27 | struct workqueue_struct *edac_workqueue; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * sysfs object: /sys/devices/system/edac | ||
31 | * need to export to other files in this modules | ||
32 | */ | ||
33 | static struct sysdev_class edac_class = { | ||
34 | .name = "edac", | ||
35 | }; | ||
36 | static int edac_class_valid; | ||
37 | |||
38 | /* | ||
39 | * edac_op_state_to_string() | 30 | * edac_op_state_to_string() |
40 | */ | 31 | */ |
41 | char *edac_op_state_to_string(int opstate) | 32 | char *edac_op_state_to_string(int opstate) |
@@ -55,60 +46,6 @@ char *edac_op_state_to_string(int opstate) | |||
55 | } | 46 | } |
56 | 47 | ||
57 | /* | 48 | /* |
58 | * edac_get_edac_class() | ||
59 | * | ||
60 | * return pointer to the edac class of 'edac' | ||
61 | */ | ||
62 | struct sysdev_class *edac_get_edac_class(void) | ||
63 | { | ||
64 | struct sysdev_class *classptr = NULL; | ||
65 | |||
66 | if (edac_class_valid) | ||
67 | classptr = &edac_class; | ||
68 | |||
69 | return classptr; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * edac_register_sysfs_edac_name() | ||
74 | * | ||
75 | * register the 'edac' into /sys/devices/system | ||
76 | * | ||
77 | * return: | ||
78 | * 0 success | ||
79 | * !0 error | ||
80 | */ | ||
81 | static int edac_register_sysfs_edac_name(void) | ||
82 | { | ||
83 | int err; | ||
84 | |||
85 | /* create the /sys/devices/system/edac directory */ | ||
86 | err = sysdev_class_register(&edac_class); | ||
87 | |||
88 | if (err) { | ||
89 | debugf1("%s() error=%d\n", __func__, err); | ||
90 | return err; | ||
91 | } | ||
92 | |||
93 | edac_class_valid = 1; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * sysdev_class_unregister() | ||
99 | * | ||
100 | * unregister the 'edac' from /sys/devices/system | ||
101 | */ | ||
102 | static void edac_unregister_sysfs_edac_name(void) | ||
103 | { | ||
104 | /* only if currently registered, then unregister it */ | ||
105 | if (edac_class_valid) | ||
106 | sysdev_class_unregister(&edac_class); | ||
107 | |||
108 | edac_class_valid = 0; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * edac_workqueue_setup | 49 | * edac_workqueue_setup |
113 | * initialize the edac work queue for polling operations | 50 | * initialize the edac work queue for polling operations |
114 | */ | 51 | */ |
@@ -154,21 +91,11 @@ static int __init edac_init(void) | |||
154 | edac_pci_clear_parity_errors(); | 91 | edac_pci_clear_parity_errors(); |
155 | 92 | ||
156 | /* | 93 | /* |
157 | * perform the registration of the /sys/devices/system/edac class object | ||
158 | */ | ||
159 | if (edac_register_sysfs_edac_name()) { | ||
160 | edac_printk(KERN_ERR, EDAC_MC, | ||
161 | "Error initializing 'edac' kobject\n"); | ||
162 | err = -ENODEV; | ||
163 | goto error; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * now set up the mc_kset under the edac class object | 94 | * now set up the mc_kset under the edac class object |
168 | */ | 95 | */ |
169 | err = edac_sysfs_setup_mc_kset(); | 96 | err = edac_sysfs_setup_mc_kset(); |
170 | if (err) | 97 | if (err) |
171 | goto sysfs_setup_fail; | 98 | goto error; |
172 | 99 | ||
173 | /* Setup/Initialize the workq for this core */ | 100 | /* Setup/Initialize the workq for this core */ |
174 | err = edac_workqueue_setup(); | 101 | err = edac_workqueue_setup(); |
@@ -183,9 +110,6 @@ static int __init edac_init(void) | |||
183 | workq_fail: | 110 | workq_fail: |
184 | edac_sysfs_teardown_mc_kset(); | 111 | edac_sysfs_teardown_mc_kset(); |
185 | 112 | ||
186 | sysfs_setup_fail: | ||
187 | edac_unregister_sysfs_edac_name(); | ||
188 | |||
189 | error: | 113 | error: |
190 | return err; | 114 | return err; |
191 | } | 115 | } |
@@ -201,7 +125,6 @@ static void __exit edac_exit(void) | |||
201 | /* tear down the various subsystems */ | 125 | /* tear down the various subsystems */ |
202 | edac_workqueue_teardown(); | 126 | edac_workqueue_teardown(); |
203 | edac_sysfs_teardown_mc_kset(); | 127 | edac_sysfs_teardown_mc_kset(); |
204 | edac_unregister_sysfs_edac_name(); | ||
205 | } | 128 | } |
206 | 129 | ||
207 | /* | 130 | /* |
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 233d4798c3aa..17aabb7b90ec 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h | |||
@@ -42,7 +42,6 @@ extern void edac_device_unregister_sysfs_main_kobj( | |||
42 | struct edac_device_ctl_info *edac_dev); | 42 | struct edac_device_ctl_info *edac_dev); |
43 | extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev); | 43 | extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev); |
44 | extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev); | 44 | extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev); |
45 | extern struct sysdev_class *edac_get_edac_class(void); | ||
46 | 45 | ||
47 | /* edac core workqueue: single CPU mode */ | 46 | /* edac core workqueue: single CPU mode */ |
48 | extern struct workqueue_struct *edac_workqueue; | 47 | extern struct workqueue_struct *edac_workqueue; |
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index c39697df9cb4..023b01cb5175 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/sysdev.h> | 10 | #include <linux/edac.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | 13 | ||
@@ -354,7 +354,7 @@ static int edac_pci_main_kobj_setup(void) | |||
354 | /* First time, so create the main kobject and its | 354 | /* First time, so create the main kobject and its |
355 | * controls and atributes | 355 | * controls and atributes |
356 | */ | 356 | */ |
357 | edac_class = edac_get_edac_class(); | 357 | edac_class = edac_get_sysfs_class(); |
358 | if (edac_class == NULL) { | 358 | if (edac_class == NULL) { |
359 | debugf1("%s() no edac_class\n", __func__); | 359 | debugf1("%s() no edac_class\n", __func__); |
360 | err = -ENODEV; | 360 | err = -ENODEV; |
@@ -368,7 +368,7 @@ static int edac_pci_main_kobj_setup(void) | |||
368 | if (!try_module_get(THIS_MODULE)) { | 368 | if (!try_module_get(THIS_MODULE)) { |
369 | debugf1("%s() try_module_get() failed\n", __func__); | 369 | debugf1("%s() try_module_get() failed\n", __func__); |
370 | err = -ENODEV; | 370 | err = -ENODEV; |
371 | goto decrement_count_fail; | 371 | goto mod_get_fail; |
372 | } | 372 | } |
373 | 373 | ||
374 | edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | 374 | edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); |
@@ -403,6 +403,9 @@ kobject_init_and_add_fail: | |||
403 | kzalloc_fail: | 403 | kzalloc_fail: |
404 | module_put(THIS_MODULE); | 404 | module_put(THIS_MODULE); |
405 | 405 | ||
406 | mod_get_fail: | ||
407 | edac_put_sysfs_class(); | ||
408 | |||
406 | decrement_count_fail: | 409 | decrement_count_fail: |
407 | /* if are on this error exit, nothing to tear down */ | 410 | /* if are on this error exit, nothing to tear down */ |
408 | atomic_dec(&edac_pci_sysfs_refcount); | 411 | atomic_dec(&edac_pci_sysfs_refcount); |
@@ -429,6 +432,7 @@ static void edac_pci_main_kobj_teardown(void) | |||
429 | __func__); | 432 | __func__); |
430 | kobject_put(edac_pci_top_main_kobj); | 433 | kobject_put(edac_pci_top_main_kobj); |
431 | } | 434 | } |
435 | edac_put_sysfs_class(); | ||
432 | } | 436 | } |
433 | 437 | ||
434 | /* | 438 | /* |
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c index 20b428aa155e..aab970760b75 100644 --- a/drivers/edac/edac_stub.c +++ b/drivers/edac/edac_stub.c | |||
@@ -3,10 +3,13 @@ | |||
3 | * | 3 | * |
4 | * Author: Dave Jiang <djiang@mvista.com> | 4 | * Author: Dave Jiang <djiang@mvista.com> |
5 | * | 5 | * |
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | 6 | * 2007 (c) MontaVista Software, Inc. |
7 | * the terms of the GNU General Public License version 2. This program | 7 | * 2010 (c) Advanced Micro Devices Inc. |
8 | * is licensed "as is" without any warranty of any kind, whether express | 8 | * Borislav Petkov <borislav.petkov@amd.com> |
9 | * or implied. | 9 | * |
10 | * This file is licensed under the terms of the GNU General Public | ||
11 | * License version 2. This program is licensed "as is" without any | ||
12 | * warranty of any kind, whether express or implied. | ||
10 | * | 13 | * |
11 | */ | 14 | */ |
12 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -23,6 +26,8 @@ EXPORT_SYMBOL_GPL(edac_handlers); | |||
23 | int edac_err_assert = 0; | 26 | int edac_err_assert = 0; |
24 | EXPORT_SYMBOL_GPL(edac_err_assert); | 27 | EXPORT_SYMBOL_GPL(edac_err_assert); |
25 | 28 | ||
29 | static atomic_t edac_class_valid = ATOMIC_INIT(0); | ||
30 | |||
26 | /* | 31 | /* |
27 | * called to determine if there is an EDAC driver interested in | 32 | * called to determine if there is an EDAC driver interested in |
28 | * knowing an event (such as NMI) occurred | 33 | * knowing an event (such as NMI) occurred |
@@ -44,3 +49,41 @@ void edac_atomic_assert_error(void) | |||
44 | edac_err_assert++; | 49 | edac_err_assert++; |
45 | } | 50 | } |
46 | EXPORT_SYMBOL_GPL(edac_atomic_assert_error); | 51 | EXPORT_SYMBOL_GPL(edac_atomic_assert_error); |
52 | |||
53 | /* | ||
54 | * sysfs object: /sys/devices/system/edac | ||
55 | * need to export to other files | ||
56 | */ | ||
57 | struct sysdev_class edac_class = { | ||
58 | .name = "edac", | ||
59 | }; | ||
60 | EXPORT_SYMBOL_GPL(edac_class); | ||
61 | |||
62 | /* return pointer to the 'edac' node in sysfs */ | ||
63 | struct sysdev_class *edac_get_sysfs_class(void) | ||
64 | { | ||
65 | int err = 0; | ||
66 | |||
67 | if (atomic_read(&edac_class_valid)) | ||
68 | goto out; | ||
69 | |||
70 | /* create the /sys/devices/system/edac directory */ | ||
71 | err = sysdev_class_register(&edac_class); | ||
72 | if (err) { | ||
73 | printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n"); | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | out: | ||
78 | atomic_inc(&edac_class_valid); | ||
79 | return &edac_class; | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(edac_get_sysfs_class); | ||
82 | |||
83 | void edac_put_sysfs_class(void) | ||
84 | { | ||
85 | /* last user unregisters it */ | ||
86 | if (atomic_dec_and_test(&edac_class_valid)) | ||
87 | sysdev_class_unregister(&edac_class); | ||
88 | } | ||
89 | EXPORT_SYMBOL_GPL(edac_put_sysfs_class); | ||
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c new file mode 100644 index 000000000000..c0181093b490 --- /dev/null +++ b/drivers/edac/mce_amd.c | |||
@@ -0,0 +1,680 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/slab.h> | ||
3 | |||
4 | #include "mce_amd.h" | ||
5 | |||
6 | static struct amd_decoder_ops *fam_ops; | ||
7 | |||
8 | static u8 nb_err_cpumask = 0xf; | ||
9 | |||
10 | static bool report_gart_errors; | ||
11 | static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg); | ||
12 | |||
13 | void amd_report_gart_errors(bool v) | ||
14 | { | ||
15 | report_gart_errors = v; | ||
16 | } | ||
17 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); | ||
18 | |||
19 | void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)) | ||
20 | { | ||
21 | nb_bus_decoder = f; | ||
22 | } | ||
23 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); | ||
24 | |||
25 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)) | ||
26 | { | ||
27 | if (nb_bus_decoder) { | ||
28 | WARN_ON(nb_bus_decoder != f); | ||
29 | |||
30 | nb_bus_decoder = NULL; | ||
31 | } | ||
32 | } | ||
33 | EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder); | ||
34 | |||
35 | /* | ||
36 | * string representation for the different MCA reported error types, see F3x48 | ||
37 | * or MSR0000_0411. | ||
38 | */ | ||
39 | |||
40 | /* transaction type */ | ||
41 | const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" }; | ||
42 | EXPORT_SYMBOL_GPL(tt_msgs); | ||
43 | |||
44 | /* cache level */ | ||
45 | const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" }; | ||
46 | EXPORT_SYMBOL_GPL(ll_msgs); | ||
47 | |||
48 | /* memory transaction type */ | ||
49 | const char *rrrr_msgs[] = { | ||
50 | "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP" | ||
51 | }; | ||
52 | EXPORT_SYMBOL_GPL(rrrr_msgs); | ||
53 | |||
54 | /* participating processor */ | ||
55 | const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" }; | ||
56 | EXPORT_SYMBOL_GPL(pp_msgs); | ||
57 | |||
58 | /* request timeout */ | ||
59 | const char *to_msgs[] = { "no timeout", "timed out" }; | ||
60 | EXPORT_SYMBOL_GPL(to_msgs); | ||
61 | |||
62 | /* memory or i/o */ | ||
63 | const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; | ||
64 | EXPORT_SYMBOL_GPL(ii_msgs); | ||
65 | |||
66 | static const char *f10h_nb_mce_desc[] = { | ||
67 | "HT link data error", | ||
68 | "Protocol error (link, L3, probe filter, etc.)", | ||
69 | "Parity error in NB-internal arrays", | ||
70 | "Link Retry due to IO link transmission error", | ||
71 | "L3 ECC data cache error", | ||
72 | "ECC error in L3 cache tag", | ||
73 | "L3 LRU parity bits error", | ||
74 | "ECC Error in the Probe Filter directory" | ||
75 | }; | ||
76 | |||
77 | static bool f12h_dc_mce(u16 ec) | ||
78 | { | ||
79 | bool ret = false; | ||
80 | |||
81 | if (MEM_ERROR(ec)) { | ||
82 | u8 ll = ec & 0x3; | ||
83 | ret = true; | ||
84 | |||
85 | if (ll == LL_L2) | ||
86 | pr_cont("during L1 linefill from L2.\n"); | ||
87 | else if (ll == LL_L1) | ||
88 | pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec)); | ||
89 | else | ||
90 | ret = false; | ||
91 | } | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | static bool f10h_dc_mce(u16 ec) | ||
96 | { | ||
97 | u8 r4 = (ec >> 4) & 0xf; | ||
98 | u8 ll = ec & 0x3; | ||
99 | |||
100 | if (r4 == R4_GEN && ll == LL_L1) { | ||
101 | pr_cont("during data scrub.\n"); | ||
102 | return true; | ||
103 | } | ||
104 | return f12h_dc_mce(ec); | ||
105 | } | ||
106 | |||
107 | static bool k8_dc_mce(u16 ec) | ||
108 | { | ||
109 | if (BUS_ERROR(ec)) { | ||
110 | pr_cont("during system linefill.\n"); | ||
111 | return true; | ||
112 | } | ||
113 | |||
114 | return f10h_dc_mce(ec); | ||
115 | } | ||
116 | |||
117 | static bool f14h_dc_mce(u16 ec) | ||
118 | { | ||
119 | u8 r4 = (ec >> 4) & 0xf; | ||
120 | u8 ll = ec & 0x3; | ||
121 | u8 tt = (ec >> 2) & 0x3; | ||
122 | u8 ii = tt; | ||
123 | bool ret = true; | ||
124 | |||
125 | if (MEM_ERROR(ec)) { | ||
126 | |||
127 | if (tt != TT_DATA || ll != LL_L1) | ||
128 | return false; | ||
129 | |||
130 | switch (r4) { | ||
131 | case R4_DRD: | ||
132 | case R4_DWR: | ||
133 | pr_cont("Data/Tag parity error due to %s.\n", | ||
134 | (r4 == R4_DRD ? "load/hw prf" : "store")); | ||
135 | break; | ||
136 | case R4_EVICT: | ||
137 | pr_cont("Copyback parity error on a tag miss.\n"); | ||
138 | break; | ||
139 | case R4_SNOOP: | ||
140 | pr_cont("Tag parity error during snoop.\n"); | ||
141 | break; | ||
142 | default: | ||
143 | ret = false; | ||
144 | } | ||
145 | } else if (BUS_ERROR(ec)) { | ||
146 | |||
147 | if ((ii != II_MEM && ii != II_IO) || ll != LL_LG) | ||
148 | return false; | ||
149 | |||
150 | pr_cont("System read data error on a "); | ||
151 | |||
152 | switch (r4) { | ||
153 | case R4_RD: | ||
154 | pr_cont("TLB reload.\n"); | ||
155 | break; | ||
156 | case R4_DWR: | ||
157 | pr_cont("store.\n"); | ||
158 | break; | ||
159 | case R4_DRD: | ||
160 | pr_cont("load.\n"); | ||
161 | break; | ||
162 | default: | ||
163 | ret = false; | ||
164 | } | ||
165 | } else { | ||
166 | ret = false; | ||
167 | } | ||
168 | |||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | static void amd_decode_dc_mce(struct mce *m) | ||
173 | { | ||
174 | u16 ec = m->status & 0xffff; | ||
175 | u8 xec = (m->status >> 16) & 0xf; | ||
176 | |||
177 | pr_emerg(HW_ERR "Data Cache Error: "); | ||
178 | |||
179 | /* TLB error signatures are the same across families */ | ||
180 | if (TLB_ERROR(ec)) { | ||
181 | u8 tt = (ec >> 2) & 0x3; | ||
182 | |||
183 | if (tt == TT_DATA) { | ||
184 | pr_cont("%s TLB %s.\n", LL_MSG(ec), | ||
185 | (xec ? "multimatch" : "parity error")); | ||
186 | return; | ||
187 | } | ||
188 | else | ||
189 | goto wrong_dc_mce; | ||
190 | } | ||
191 | |||
192 | if (!fam_ops->dc_mce(ec)) | ||
193 | goto wrong_dc_mce; | ||
194 | |||
195 | return; | ||
196 | |||
197 | wrong_dc_mce: | ||
198 | pr_emerg(HW_ERR "Corrupted DC MCE info?\n"); | ||
199 | } | ||
200 | |||
201 | static bool k8_ic_mce(u16 ec) | ||
202 | { | ||
203 | u8 ll = ec & 0x3; | ||
204 | u8 r4 = (ec >> 4) & 0xf; | ||
205 | bool ret = true; | ||
206 | |||
207 | if (!MEM_ERROR(ec)) | ||
208 | return false; | ||
209 | |||
210 | if (ll == 0x2) | ||
211 | pr_cont("during a linefill from L2.\n"); | ||
212 | else if (ll == 0x1) { | ||
213 | switch (r4) { | ||
214 | case R4_IRD: | ||
215 | pr_cont("Parity error during data load.\n"); | ||
216 | break; | ||
217 | |||
218 | case R4_EVICT: | ||
219 | pr_cont("Copyback Parity/Victim error.\n"); | ||
220 | break; | ||
221 | |||
222 | case R4_SNOOP: | ||
223 | pr_cont("Tag Snoop error.\n"); | ||
224 | break; | ||
225 | |||
226 | default: | ||
227 | ret = false; | ||
228 | break; | ||
229 | } | ||
230 | } else | ||
231 | ret = false; | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static bool f14h_ic_mce(u16 ec) | ||
237 | { | ||
238 | u8 ll = ec & 0x3; | ||
239 | u8 tt = (ec >> 2) & 0x3; | ||
240 | u8 r4 = (ec >> 4) & 0xf; | ||
241 | bool ret = true; | ||
242 | |||
243 | if (MEM_ERROR(ec)) { | ||
244 | if (tt != 0 || ll != 1) | ||
245 | ret = false; | ||
246 | |||
247 | if (r4 == R4_IRD) | ||
248 | pr_cont("Data/tag array parity error for a tag hit.\n"); | ||
249 | else if (r4 == R4_SNOOP) | ||
250 | pr_cont("Tag error during snoop/victimization.\n"); | ||
251 | else | ||
252 | ret = false; | ||
253 | } | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static void amd_decode_ic_mce(struct mce *m) | ||
258 | { | ||
259 | u16 ec = m->status & 0xffff; | ||
260 | u8 xec = (m->status >> 16) & 0xf; | ||
261 | |||
262 | pr_emerg(HW_ERR "Instruction Cache Error: "); | ||
263 | |||
264 | if (TLB_ERROR(ec)) | ||
265 | pr_cont("%s TLB %s.\n", LL_MSG(ec), | ||
266 | (xec ? "multimatch" : "parity error")); | ||
267 | else if (BUS_ERROR(ec)) { | ||
268 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); | ||
269 | |||
270 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); | ||
271 | } else if (fam_ops->ic_mce(ec)) | ||
272 | ; | ||
273 | else | ||
274 | pr_emerg(HW_ERR "Corrupted IC MCE info?\n"); | ||
275 | } | ||
276 | |||
277 | static void amd_decode_bu_mce(struct mce *m) | ||
278 | { | ||
279 | u32 ec = m->status & 0xffff; | ||
280 | u32 xec = (m->status >> 16) & 0xf; | ||
281 | |||
282 | pr_emerg(HW_ERR "Bus Unit Error"); | ||
283 | |||
284 | if (xec == 0x1) | ||
285 | pr_cont(" in the write data buffers.\n"); | ||
286 | else if (xec == 0x3) | ||
287 | pr_cont(" in the victim data buffers.\n"); | ||
288 | else if (xec == 0x2 && MEM_ERROR(ec)) | ||
289 | pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec)); | ||
290 | else if (xec == 0x0) { | ||
291 | if (TLB_ERROR(ec)) | ||
292 | pr_cont(": %s error in a Page Descriptor Cache or " | ||
293 | "Guest TLB.\n", TT_MSG(ec)); | ||
294 | else if (BUS_ERROR(ec)) | ||
295 | pr_cont(": %s/ECC error in data read from NB: %s.\n", | ||
296 | RRRR_MSG(ec), PP_MSG(ec)); | ||
297 | else if (MEM_ERROR(ec)) { | ||
298 | u8 rrrr = (ec >> 4) & 0xf; | ||
299 | |||
300 | if (rrrr >= 0x7) | ||
301 | pr_cont(": %s error during data copyback.\n", | ||
302 | RRRR_MSG(ec)); | ||
303 | else if (rrrr <= 0x1) | ||
304 | pr_cont(": %s parity/ECC error during data " | ||
305 | "access from L2.\n", RRRR_MSG(ec)); | ||
306 | else | ||
307 | goto wrong_bu_mce; | ||
308 | } else | ||
309 | goto wrong_bu_mce; | ||
310 | } else | ||
311 | goto wrong_bu_mce; | ||
312 | |||
313 | return; | ||
314 | |||
315 | wrong_bu_mce: | ||
316 | pr_emerg(HW_ERR "Corrupted BU MCE info?\n"); | ||
317 | } | ||
318 | |||
319 | static void amd_decode_ls_mce(struct mce *m) | ||
320 | { | ||
321 | u16 ec = m->status & 0xffff; | ||
322 | u8 xec = (m->status >> 16) & 0xf; | ||
323 | |||
324 | if (boot_cpu_data.x86 == 0x14) { | ||
325 | pr_emerg("You shouldn't be seeing an LS MCE on this cpu family," | ||
326 | " please report on LKML.\n"); | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | pr_emerg(HW_ERR "Load Store Error"); | ||
331 | |||
332 | if (xec == 0x0) { | ||
333 | u8 r4 = (ec >> 4) & 0xf; | ||
334 | |||
335 | if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR)) | ||
336 | goto wrong_ls_mce; | ||
337 | |||
338 | pr_cont(" during %s.\n", RRRR_MSG(ec)); | ||
339 | } else | ||
340 | goto wrong_ls_mce; | ||
341 | |||
342 | return; | ||
343 | |||
344 | wrong_ls_mce: | ||
345 | pr_emerg(HW_ERR "Corrupted LS MCE info?\n"); | ||
346 | } | ||
347 | |||
348 | static bool k8_nb_mce(u16 ec, u8 xec) | ||
349 | { | ||
350 | bool ret = true; | ||
351 | |||
352 | switch (xec) { | ||
353 | case 0x1: | ||
354 | pr_cont("CRC error detected on HT link.\n"); | ||
355 | break; | ||
356 | |||
357 | case 0x5: | ||
358 | pr_cont("Invalid GART PTE entry during GART table walk.\n"); | ||
359 | break; | ||
360 | |||
361 | case 0x6: | ||
362 | pr_cont("Unsupported atomic RMW received from an IO link.\n"); | ||
363 | break; | ||
364 | |||
365 | case 0x0: | ||
366 | case 0x8: | ||
367 | if (boot_cpu_data.x86 == 0x11) | ||
368 | return false; | ||
369 | |||
370 | pr_cont("DRAM ECC error detected on the NB.\n"); | ||
371 | break; | ||
372 | |||
373 | case 0xd: | ||
374 | pr_cont("Parity error on the DRAM addr/ctl signals.\n"); | ||
375 | break; | ||
376 | |||
377 | default: | ||
378 | ret = false; | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | static bool f10h_nb_mce(u16 ec, u8 xec) | ||
386 | { | ||
387 | bool ret = true; | ||
388 | u8 offset = 0; | ||
389 | |||
390 | if (k8_nb_mce(ec, xec)) | ||
391 | return true; | ||
392 | |||
393 | switch(xec) { | ||
394 | case 0xa ... 0xc: | ||
395 | offset = 10; | ||
396 | break; | ||
397 | |||
398 | case 0xe: | ||
399 | offset = 11; | ||
400 | break; | ||
401 | |||
402 | case 0xf: | ||
403 | if (TLB_ERROR(ec)) | ||
404 | pr_cont("GART Table Walk data error.\n"); | ||
405 | else if (BUS_ERROR(ec)) | ||
406 | pr_cont("DMA Exclusion Vector Table Walk error.\n"); | ||
407 | else | ||
408 | ret = false; | ||
409 | |||
410 | goto out; | ||
411 | break; | ||
412 | |||
413 | case 0x1c ... 0x1f: | ||
414 | offset = 24; | ||
415 | break; | ||
416 | |||
417 | default: | ||
418 | ret = false; | ||
419 | |||
420 | goto out; | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]); | ||
425 | |||
426 | out: | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static bool nb_noop_mce(u16 ec, u8 xec) | ||
431 | { | ||
432 | return false; | ||
433 | } | ||
434 | |||
435 | void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) | ||
436 | { | ||
437 | u8 xec = (m->status >> 16) & 0x1f; | ||
438 | u16 ec = m->status & 0xffff; | ||
439 | u32 nbsh = (u32)(m->status >> 32); | ||
440 | |||
441 | pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id); | ||
442 | |||
443 | /* | ||
444 | * F10h, revD can disable ErrCpu[3:0] so check that first and also the | ||
445 | * value encoding has changed so interpret those differently | ||
446 | */ | ||
447 | if ((boot_cpu_data.x86 == 0x10) && | ||
448 | (boot_cpu_data.x86_model > 7)) { | ||
449 | if (nbsh & K8_NBSH_ERR_CPU_VAL) | ||
450 | pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask)); | ||
451 | } else { | ||
452 | u8 assoc_cpus = nbsh & nb_err_cpumask; | ||
453 | |||
454 | if (assoc_cpus > 0) | ||
455 | pr_cont(", core: %d", fls(assoc_cpus) - 1); | ||
456 | } | ||
457 | |||
458 | switch (xec) { | ||
459 | case 0x2: | ||
460 | pr_cont("Sync error (sync packets on HT link detected).\n"); | ||
461 | return; | ||
462 | |||
463 | case 0x3: | ||
464 | pr_cont("HT Master abort.\n"); | ||
465 | return; | ||
466 | |||
467 | case 0x4: | ||
468 | pr_cont("HT Target abort.\n"); | ||
469 | return; | ||
470 | |||
471 | case 0x7: | ||
472 | pr_cont("NB Watchdog timeout.\n"); | ||
473 | return; | ||
474 | |||
475 | case 0x9: | ||
476 | pr_cont("SVM DMA Exclusion Vector error.\n"); | ||
477 | return; | ||
478 | |||
479 | default: | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | if (!fam_ops->nb_mce(ec, xec)) | ||
484 | goto wrong_nb_mce; | ||
485 | |||
486 | if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10) | ||
487 | if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) | ||
488 | nb_bus_decoder(node_id, m, nbcfg); | ||
489 | |||
490 | return; | ||
491 | |||
492 | wrong_nb_mce: | ||
493 | pr_emerg(HW_ERR "Corrupted NB MCE info?\n"); | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(amd_decode_nb_mce); | ||
496 | |||
497 | static void amd_decode_fr_mce(struct mce *m) | ||
498 | { | ||
499 | if (boot_cpu_data.x86 == 0xf || | ||
500 | boot_cpu_data.x86 == 0x11) | ||
501 | goto wrong_fr_mce; | ||
502 | |||
503 | /* we have only one error signature so match all fields at once. */ | ||
504 | if ((m->status & 0xffff) == 0x0f0f) { | ||
505 | pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n"); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | wrong_fr_mce: | ||
510 | pr_emerg(HW_ERR "Corrupted FR MCE info?\n"); | ||
511 | } | ||
512 | |||
513 | static inline void amd_decode_err_code(u16 ec) | ||
514 | { | ||
515 | if (TLB_ERROR(ec)) { | ||
516 | pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n", | ||
517 | TT_MSG(ec), LL_MSG(ec)); | ||
518 | } else if (MEM_ERROR(ec)) { | ||
519 | pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n", | ||
520 | RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec)); | ||
521 | } else if (BUS_ERROR(ec)) { | ||
522 | pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, " | ||
523 | "Participating Processor: %s\n", | ||
524 | RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec), | ||
525 | PP_MSG(ec)); | ||
526 | } else | ||
527 | pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec); | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Filter out unwanted MCE signatures here. | ||
532 | */ | ||
533 | static bool amd_filter_mce(struct mce *m) | ||
534 | { | ||
535 | u8 xec = (m->status >> 16) & 0x1f; | ||
536 | |||
537 | /* | ||
538 | * NB GART TLB error reporting is disabled by default. | ||
539 | */ | ||
540 | if (m->bank == 4 && xec == 0x5 && !report_gart_errors) | ||
541 | return true; | ||
542 | |||
543 | return false; | ||
544 | } | ||
545 | |||
546 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | ||
547 | { | ||
548 | struct mce *m = (struct mce *)data; | ||
549 | int node, ecc; | ||
550 | |||
551 | if (amd_filter_mce(m)) | ||
552 | return NOTIFY_STOP; | ||
553 | |||
554 | pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank); | ||
555 | |||
556 | pr_cont("%sorrected error, other errors lost: %s, " | ||
557 | "CPU context corrupt: %s", | ||
558 | ((m->status & MCI_STATUS_UC) ? "Unc" : "C"), | ||
559 | ((m->status & MCI_STATUS_OVER) ? "yes" : "no"), | ||
560 | ((m->status & MCI_STATUS_PCC) ? "yes" : "no")); | ||
561 | |||
562 | /* do the two bits[14:13] together */ | ||
563 | ecc = (m->status >> 45) & 0x3; | ||
564 | if (ecc) | ||
565 | pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); | ||
566 | |||
567 | pr_cont("\n"); | ||
568 | |||
569 | switch (m->bank) { | ||
570 | case 0: | ||
571 | amd_decode_dc_mce(m); | ||
572 | break; | ||
573 | |||
574 | case 1: | ||
575 | amd_decode_ic_mce(m); | ||
576 | break; | ||
577 | |||
578 | case 2: | ||
579 | amd_decode_bu_mce(m); | ||
580 | break; | ||
581 | |||
582 | case 3: | ||
583 | amd_decode_ls_mce(m); | ||
584 | break; | ||
585 | |||
586 | case 4: | ||
587 | node = amd_get_nb_id(m->extcpu); | ||
588 | amd_decode_nb_mce(node, m, 0); | ||
589 | break; | ||
590 | |||
591 | case 5: | ||
592 | amd_decode_fr_mce(m); | ||
593 | break; | ||
594 | |||
595 | default: | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | amd_decode_err_code(m->status & 0xffff); | ||
600 | |||
601 | return NOTIFY_STOP; | ||
602 | } | ||
603 | EXPORT_SYMBOL_GPL(amd_decode_mce); | ||
604 | |||
605 | static struct notifier_block amd_mce_dec_nb = { | ||
606 | .notifier_call = amd_decode_mce, | ||
607 | }; | ||
608 | |||
609 | static int __init mce_amd_init(void) | ||
610 | { | ||
611 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||
612 | return 0; | ||
613 | |||
614 | if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) && | ||
615 | (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf)) | ||
616 | return 0; | ||
617 | |||
618 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); | ||
619 | if (!fam_ops) | ||
620 | return -ENOMEM; | ||
621 | |||
622 | switch (boot_cpu_data.x86) { | ||
623 | case 0xf: | ||
624 | fam_ops->dc_mce = k8_dc_mce; | ||
625 | fam_ops->ic_mce = k8_ic_mce; | ||
626 | fam_ops->nb_mce = k8_nb_mce; | ||
627 | break; | ||
628 | |||
629 | case 0x10: | ||
630 | fam_ops->dc_mce = f10h_dc_mce; | ||
631 | fam_ops->ic_mce = k8_ic_mce; | ||
632 | fam_ops->nb_mce = f10h_nb_mce; | ||
633 | break; | ||
634 | |||
635 | case 0x11: | ||
636 | fam_ops->dc_mce = k8_dc_mce; | ||
637 | fam_ops->ic_mce = k8_ic_mce; | ||
638 | fam_ops->nb_mce = f10h_nb_mce; | ||
639 | break; | ||
640 | |||
641 | case 0x12: | ||
642 | fam_ops->dc_mce = f12h_dc_mce; | ||
643 | fam_ops->ic_mce = k8_ic_mce; | ||
644 | fam_ops->nb_mce = nb_noop_mce; | ||
645 | break; | ||
646 | |||
647 | case 0x14: | ||
648 | nb_err_cpumask = 0x3; | ||
649 | fam_ops->dc_mce = f14h_dc_mce; | ||
650 | fam_ops->ic_mce = f14h_ic_mce; | ||
651 | fam_ops->nb_mce = nb_noop_mce; | ||
652 | break; | ||
653 | |||
654 | default: | ||
655 | printk(KERN_WARNING "Huh? What family is that: %d?!\n", | ||
656 | boot_cpu_data.x86); | ||
657 | kfree(fam_ops); | ||
658 | return -EINVAL; | ||
659 | } | ||
660 | |||
661 | pr_info("MCE: In-kernel MCE decoding enabled.\n"); | ||
662 | |||
663 | atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | early_initcall(mce_amd_init); | ||
668 | |||
669 | #ifdef MODULE | ||
670 | static void __exit mce_amd_exit(void) | ||
671 | { | ||
672 | atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb); | ||
673 | kfree(fam_ops); | ||
674 | } | ||
675 | |||
676 | MODULE_DESCRIPTION("AMD MCE decoder"); | ||
677 | MODULE_ALIAS("edac-mce-amd"); | ||
678 | MODULE_LICENSE("GPL"); | ||
679 | module_exit(mce_amd_exit); | ||
680 | #endif | ||
diff --git a/drivers/edac/edac_mce_amd.h b/drivers/edac/mce_amd.h index df23ee065f79..35f6e0e3b297 100644 --- a/drivers/edac/edac_mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -1,11 +1,14 @@ | |||
1 | #ifndef _EDAC_MCE_AMD_H | 1 | #ifndef _EDAC_MCE_AMD_H |
2 | #define _EDAC_MCE_AMD_H | 2 | #define _EDAC_MCE_AMD_H |
3 | 3 | ||
4 | #include <linux/notifier.h> | ||
5 | |||
4 | #include <asm/mce.h> | 6 | #include <asm/mce.h> |
5 | 7 | ||
8 | #define BIT_64(n) (U64_C(1) << (n)) | ||
9 | |||
6 | #define ERROR_CODE(x) ((x) & 0xffff) | 10 | #define ERROR_CODE(x) ((x) & 0xffff) |
7 | #define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f) | 11 | #define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f) |
8 | #define EXT_ERR_MSG(x) ext_msgs[EXT_ERROR_CODE(x)] | ||
9 | 12 | ||
10 | #define LOW_SYNDROME(x) (((x) >> 15) & 0xff) | 13 | #define LOW_SYNDROME(x) (((x) >> 15) & 0xff) |
11 | #define HIGH_SYNDROME(x) (((x) >> 24) & 0xff) | 14 | #define HIGH_SYNDROME(x) (((x) >> 24) & 0xff) |
@@ -20,13 +23,14 @@ | |||
20 | #define II_MSG(x) ii_msgs[II(x)] | 23 | #define II_MSG(x) ii_msgs[II(x)] |
21 | #define LL(x) (((x) >> 0) & 0x3) | 24 | #define LL(x) (((x) >> 0) & 0x3) |
22 | #define LL_MSG(x) ll_msgs[LL(x)] | 25 | #define LL_MSG(x) ll_msgs[LL(x)] |
23 | #define RRRR(x) (((x) >> 4) & 0xf) | ||
24 | #define RRRR_MSG(x) rrrr_msgs[RRRR(x)] | ||
25 | #define TO(x) (((x) >> 8) & 0x1) | 26 | #define TO(x) (((x) >> 8) & 0x1) |
26 | #define TO_MSG(x) to_msgs[TO(x)] | 27 | #define TO_MSG(x) to_msgs[TO(x)] |
27 | #define PP(x) (((x) >> 9) & 0x3) | 28 | #define PP(x) (((x) >> 9) & 0x3) |
28 | #define PP_MSG(x) pp_msgs[PP(x)] | 29 | #define PP_MSG(x) pp_msgs[PP(x)] |
29 | 30 | ||
31 | #define RRRR(x) (((x) >> 4) & 0xf) | ||
32 | #define RRRR_MSG(x) ((RRRR(x) < 9) ? rrrr_msgs[RRRR(x)] : "Wrong R4!") | ||
33 | |||
30 | #define K8_NBSH 0x4C | 34 | #define K8_NBSH 0x4C |
31 | 35 | ||
32 | #define K8_NBSH_VALID_BIT BIT(31) | 36 | #define K8_NBSH_VALID_BIT BIT(31) |
@@ -41,13 +45,45 @@ | |||
41 | #define K8_NBSH_UECC BIT(13) | 45 | #define K8_NBSH_UECC BIT(13) |
42 | #define K8_NBSH_ERR_SCRUBER BIT(8) | 46 | #define K8_NBSH_ERR_SCRUBER BIT(8) |
43 | 47 | ||
48 | enum tt_ids { | ||
49 | TT_INSTR = 0, | ||
50 | TT_DATA, | ||
51 | TT_GEN, | ||
52 | TT_RESV, | ||
53 | }; | ||
54 | |||
55 | enum ll_ids { | ||
56 | LL_RESV = 0, | ||
57 | LL_L1, | ||
58 | LL_L2, | ||
59 | LL_LG, | ||
60 | }; | ||
61 | |||
62 | enum ii_ids { | ||
63 | II_MEM = 0, | ||
64 | II_RESV, | ||
65 | II_IO, | ||
66 | II_GEN, | ||
67 | }; | ||
68 | |||
69 | enum rrrr_ids { | ||
70 | R4_GEN = 0, | ||
71 | R4_RD, | ||
72 | R4_WR, | ||
73 | R4_DRD, | ||
74 | R4_DWR, | ||
75 | R4_IRD, | ||
76 | R4_PREF, | ||
77 | R4_EVICT, | ||
78 | R4_SNOOP, | ||
79 | }; | ||
80 | |||
44 | extern const char *tt_msgs[]; | 81 | extern const char *tt_msgs[]; |
45 | extern const char *ll_msgs[]; | 82 | extern const char *ll_msgs[]; |
46 | extern const char *rrrr_msgs[]; | 83 | extern const char *rrrr_msgs[]; |
47 | extern const char *pp_msgs[]; | 84 | extern const char *pp_msgs[]; |
48 | extern const char *to_msgs[]; | 85 | extern const char *to_msgs[]; |
49 | extern const char *ii_msgs[]; | 86 | extern const char *ii_msgs[]; |
50 | extern const char *ext_msgs[]; | ||
51 | 87 | ||
52 | /* | 88 | /* |
53 | * relevant NB regs | 89 | * relevant NB regs |
@@ -60,10 +96,19 @@ struct err_regs { | |||
60 | u32 nbeal; | 96 | u32 nbeal; |
61 | }; | 97 | }; |
62 | 98 | ||
99 | /* | ||
100 | * per-family decoder ops | ||
101 | */ | ||
102 | struct amd_decoder_ops { | ||
103 | bool (*dc_mce)(u16); | ||
104 | bool (*ic_mce)(u16); | ||
105 | bool (*nb_mce)(u16, u8); | ||
106 | }; | ||
63 | 107 | ||
64 | void amd_report_gart_errors(bool); | 108 | void amd_report_gart_errors(bool); |
65 | void amd_register_ecc_decoder(void (*f)(int, struct err_regs *)); | 109 | void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)); |
66 | void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *)); | 110 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)); |
67 | void amd_decode_nb_mce(int, struct err_regs *, int); | 111 | void amd_decode_nb_mce(int, struct mce *, u32); |
112 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data); | ||
68 | 113 | ||
69 | #endif /* _EDAC_MCE_AMD_H */ | 114 | #endif /* _EDAC_MCE_AMD_H */ |
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c new file mode 100644 index 000000000000..8d0688f36d4c --- /dev/null +++ b/drivers/edac/mce_amd_inj.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * A simple MCE injection facility for testing the MCE decoding code. This | ||
3 | * driver should be built as module so that it can be loaded on production | ||
4 | * kernels for testing purposes. | ||
5 | * | ||
6 | * This file may be distributed under the terms of the GNU General Public | ||
7 | * License version 2. | ||
8 | * | ||
9 | * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com> | ||
10 | * Advanced Micro Devices Inc. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kobject.h> | ||
14 | #include <linux/sysdev.h> | ||
15 | #include <linux/edac.h> | ||
16 | #include <asm/mce.h> | ||
17 | |||
18 | #include "mce_amd.h" | ||
19 | |||
20 | struct edac_mce_attr { | ||
21 | struct attribute attr; | ||
22 | ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf); | ||
23 | ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr, | ||
24 | const char *buf, size_t count); | ||
25 | }; | ||
26 | |||
27 | #define EDAC_MCE_ATTR(_name, _mode, _show, _store) \ | ||
28 | static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store) | ||
29 | |||
30 | static struct kobject *mce_kobj; | ||
31 | |||
32 | /* | ||
33 | * Collect all the MCi_XXX settings | ||
34 | */ | ||
35 | static struct mce i_mce; | ||
36 | |||
37 | #define MCE_INJECT_STORE(reg) \ | ||
38 | static ssize_t edac_inject_##reg##_store(struct kobject *kobj, \ | ||
39 | struct edac_mce_attr *attr, \ | ||
40 | const char *data, size_t count)\ | ||
41 | { \ | ||
42 | int ret = 0; \ | ||
43 | unsigned long value; \ | ||
44 | \ | ||
45 | ret = strict_strtoul(data, 16, &value); \ | ||
46 | if (ret < 0) \ | ||
47 | printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \ | ||
48 | \ | ||
49 | i_mce.reg = value; \ | ||
50 | \ | ||
51 | return count; \ | ||
52 | } | ||
53 | |||
54 | MCE_INJECT_STORE(status); | ||
55 | MCE_INJECT_STORE(misc); | ||
56 | MCE_INJECT_STORE(addr); | ||
57 | |||
58 | #define MCE_INJECT_SHOW(reg) \ | ||
59 | static ssize_t edac_inject_##reg##_show(struct kobject *kobj, \ | ||
60 | struct edac_mce_attr *attr, \ | ||
61 | char *buf) \ | ||
62 | { \ | ||
63 | return sprintf(buf, "0x%016llx\n", i_mce.reg); \ | ||
64 | } | ||
65 | |||
66 | MCE_INJECT_SHOW(status); | ||
67 | MCE_INJECT_SHOW(misc); | ||
68 | MCE_INJECT_SHOW(addr); | ||
69 | |||
70 | EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store); | ||
71 | EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store); | ||
72 | EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store); | ||
73 | |||
74 | /* | ||
75 | * This denotes into which bank we're injecting and triggers | ||
76 | * the injection, at the same time. | ||
77 | */ | ||
78 | static ssize_t edac_inject_bank_store(struct kobject *kobj, | ||
79 | struct edac_mce_attr *attr, | ||
80 | const char *data, size_t count) | ||
81 | { | ||
82 | int ret = 0; | ||
83 | unsigned long value; | ||
84 | |||
85 | ret = strict_strtoul(data, 10, &value); | ||
86 | if (ret < 0) { | ||
87 | printk(KERN_ERR "Invalid bank value!\n"); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | if (value > 5) { | ||
92 | printk(KERN_ERR "Non-existant MCE bank: %lu\n", value); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | |||
96 | i_mce.bank = value; | ||
97 | |||
98 | amd_decode_mce(NULL, 0, &i_mce); | ||
99 | |||
100 | return count; | ||
101 | } | ||
102 | |||
103 | static ssize_t edac_inject_bank_show(struct kobject *kobj, | ||
104 | struct edac_mce_attr *attr, char *buf) | ||
105 | { | ||
106 | return sprintf(buf, "%d\n", i_mce.bank); | ||
107 | } | ||
108 | |||
109 | EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store); | ||
110 | |||
111 | static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc, | ||
112 | &mce_attr_addr, &mce_attr_bank | ||
113 | }; | ||
114 | |||
115 | static int __init edac_init_mce_inject(void) | ||
116 | { | ||
117 | struct sysdev_class *edac_class = NULL; | ||
118 | int i, err = 0; | ||
119 | |||
120 | edac_class = edac_get_sysfs_class(); | ||
121 | if (!edac_class) | ||
122 | return -EINVAL; | ||
123 | |||
124 | mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj); | ||
125 | if (!mce_kobj) { | ||
126 | printk(KERN_ERR "Error creating a mce kset.\n"); | ||
127 | err = -ENOMEM; | ||
128 | goto err_mce_kobj; | ||
129 | } | ||
130 | |||
131 | for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) { | ||
132 | err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr); | ||
133 | if (err) { | ||
134 | printk(KERN_ERR "Error creating %s in sysfs.\n", | ||
135 | sysfs_attrs[i]->attr.name); | ||
136 | goto err_sysfs_create; | ||
137 | } | ||
138 | } | ||
139 | return 0; | ||
140 | |||
141 | err_sysfs_create: | ||
142 | while (i-- >= 0) | ||
143 | sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr); | ||
144 | |||
145 | kobject_del(mce_kobj); | ||
146 | |||
147 | err_mce_kobj: | ||
148 | edac_put_sysfs_class(); | ||
149 | |||
150 | return err; | ||
151 | } | ||
152 | |||
153 | static void __exit edac_exit_mce_inject(void) | ||
154 | { | ||
155 | int i; | ||
156 | |||
157 | for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) | ||
158 | sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr); | ||
159 | |||
160 | kobject_del(mce_kobj); | ||
161 | |||
162 | edac_put_sysfs_class(); | ||
163 | } | ||
164 | |||
165 | module_init(edac_init_mce_inject); | ||
166 | module_exit(edac_exit_mce_inject); | ||
167 | |||
168 | MODULE_LICENSE("GPL"); | ||
169 | MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>"); | ||
170 | MODULE_AUTHOR("AMD Inc."); | ||
171 | MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding"); | ||
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 1b05896648bc..9dcb17d51aee 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -2840,7 +2840,7 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2840 | const struct pci_device_id *ent) | 2840 | const struct pci_device_id *ent) |
2841 | { | 2841 | { |
2842 | struct fw_ohci *ohci; | 2842 | struct fw_ohci *ohci; |
2843 | u32 bus_options, max_receive, link_speed, version, link_enh; | 2843 | u32 bus_options, max_receive, link_speed, version; |
2844 | u64 guid; | 2844 | u64 guid; |
2845 | int i, err, n_ir, n_it; | 2845 | int i, err, n_ir, n_it; |
2846 | size_t size; | 2846 | size_t size; |
@@ -2894,23 +2894,6 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2894 | if (param_quirks) | 2894 | if (param_quirks) |
2895 | ohci->quirks = param_quirks; | 2895 | ohci->quirks = param_quirks; |
2896 | 2896 | ||
2897 | /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ | ||
2898 | if (dev->vendor == PCI_VENDOR_ID_TI) { | ||
2899 | pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); | ||
2900 | |||
2901 | /* adjust latency of ATx FIFO: use 1.7 KB threshold */ | ||
2902 | link_enh &= ~TI_LinkEnh_atx_thresh_mask; | ||
2903 | link_enh |= TI_LinkEnh_atx_thresh_1_7K; | ||
2904 | |||
2905 | /* use priority arbitration for asynchronous responses */ | ||
2906 | link_enh |= TI_LinkEnh_enab_unfair; | ||
2907 | |||
2908 | /* required for aPhyEnhanceEnable to work */ | ||
2909 | link_enh |= TI_LinkEnh_enab_accel; | ||
2910 | |||
2911 | pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); | ||
2912 | } | ||
2913 | |||
2914 | ar_context_init(&ohci->ar_request_ctx, ohci, | 2897 | ar_context_init(&ohci->ar_request_ctx, ohci, |
2915 | OHCI1394_AsReqRcvContextControlSet); | 2898 | OHCI1394_AsReqRcvContextControlSet); |
2916 | 2899 | ||
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index 0e6c5a466908..ef5e7336da68 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h | |||
@@ -155,12 +155,4 @@ | |||
155 | 155 | ||
156 | #define OHCI1394_phy_tcode 0xe | 156 | #define OHCI1394_phy_tcode 0xe |
157 | 157 | ||
158 | /* TI extensions */ | ||
159 | |||
160 | #define PCI_CFG_TI_LinkEnh 0xf4 | ||
161 | #define TI_LinkEnh_enab_accel 0x00000002 | ||
162 | #define TI_LinkEnh_enab_unfair 0x00000080 | ||
163 | #define TI_LinkEnh_atx_thresh_mask 0x00003000 | ||
164 | #define TI_LinkEnh_atx_thresh_1_7K 0x00001000 | ||
165 | |||
166 | #endif /* _FIREWIRE_OHCI_H */ | 158 | #endif /* _FIREWIRE_OHCI_H */ |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 280c9b5ad9e3..88a3ae6cd023 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
@@ -125,7 +125,7 @@ config ISCSI_IBFT_FIND | |||
125 | config ISCSI_IBFT | 125 | config ISCSI_IBFT |
126 | tristate "iSCSI Boot Firmware Table Attributes module" | 126 | tristate "iSCSI Boot Firmware Table Attributes module" |
127 | select ISCSI_BOOT_SYSFS | 127 | select ISCSI_BOOT_SYSFS |
128 | depends on ISCSI_IBFT_FIND && SCSI | 128 | depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL |
129 | default n | 129 | default n |
130 | help | 130 | help |
131 | This option enables support for detection and exposing of iSCSI | 131 | This option enables support for detection and exposing of iSCSI |
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c index 1be6288780de..7e10c935a047 100644 --- a/drivers/gpio/tc35892-gpio.c +++ b/drivers/gpio/tc35892-gpio.c | |||
@@ -322,6 +322,9 @@ static int __devinit tc35892_gpio_probe(struct platform_device *pdev) | |||
322 | goto out_freeirq; | 322 | goto out_freeirq; |
323 | } | 323 | } |
324 | 324 | ||
325 | if (pdata->setup) | ||
326 | pdata->setup(tc35892, tc35892_gpio->chip.base); | ||
327 | |||
325 | platform_set_drvdata(pdev, tc35892_gpio); | 328 | platform_set_drvdata(pdev, tc35892_gpio); |
326 | 329 | ||
327 | return 0; | 330 | return 0; |
@@ -338,9 +341,14 @@ out_free: | |||
338 | static int __devexit tc35892_gpio_remove(struct platform_device *pdev) | 341 | static int __devexit tc35892_gpio_remove(struct platform_device *pdev) |
339 | { | 342 | { |
340 | struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); | 343 | struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); |
344 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
345 | struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio; | ||
341 | int irq = platform_get_irq(pdev, 0); | 346 | int irq = platform_get_irq(pdev, 0); |
342 | int ret; | 347 | int ret; |
343 | 348 | ||
349 | if (pdata->remove) | ||
350 | pdata->remove(tc35892, tc35892_gpio->chip.base); | ||
351 | |||
344 | ret = gpiochip_remove(&tc35892_gpio->chip); | 352 | ret = gpiochip_remove(&tc35892_gpio->chip); |
345 | if (ret < 0) { | 353 | if (ret < 0) { |
346 | dev_err(tc35892_gpio->dev, | 354 | dev_err(tc35892_gpio->dev, |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c74e4e8006d4..2dd2c93ebfa3 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -2231,6 +2231,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2231 | dev_priv->mchdev_lock = &mchdev_lock; | 2231 | dev_priv->mchdev_lock = &mchdev_lock; |
2232 | spin_unlock(&mchdev_lock); | 2232 | spin_unlock(&mchdev_lock); |
2233 | 2233 | ||
2234 | /* XXX Prevent module unload due to memory corruption bugs. */ | ||
2235 | __module_get(THIS_MODULE); | ||
2236 | |||
2234 | return 0; | 2237 | return 0; |
2235 | 2238 | ||
2236 | out_workqueue_free: | 2239 | out_workqueue_free: |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 79082d4398ae..2f93d46ae69a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1137,7 +1137,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | |||
1137 | 1137 | ||
1138 | WREG32(RCU_IND_INDEX, 0x203); | 1138 | WREG32(RCU_IND_INDEX, 0x203); |
1139 | efuse_straps_3 = RREG32(RCU_IND_DATA); | 1139 | efuse_straps_3 = RREG32(RCU_IND_DATA); |
1140 | efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28; | 1140 | efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); |
1141 | 1141 | ||
1142 | switch(efuse_box_bit_127_124) { | 1142 | switch(efuse_box_bit_127_124) { |
1143 | case 0x0: | 1143 | case 0x0: |
@@ -1407,6 +1407,7 @@ int evergreen_mc_init(struct radeon_device *rdev) | |||
1407 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; | 1407 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; |
1408 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; | 1408 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; |
1409 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 1409 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
1410 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1410 | r600_vram_gtt_location(rdev, &rdev->mc); | 1411 | r600_vram_gtt_location(rdev, &rdev->mc); |
1411 | radeon_update_bandwidth_info(rdev); | 1412 | radeon_update_bandwidth_info(rdev); |
1412 | 1413 | ||
@@ -1520,7 +1521,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) | |||
1520 | { | 1521 | { |
1521 | u32 tmp; | 1522 | u32 tmp; |
1522 | 1523 | ||
1523 | WREG32(CP_INT_CNTL, 0); | 1524 | WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); |
1524 | WREG32(GRBM_INT_CNTL, 0); | 1525 | WREG32(GRBM_INT_CNTL, 0); |
1525 | WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); | 1526 | WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); |
1526 | WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); | 1527 | WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e151f16a8f86..e59422320bb6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -1030,6 +1030,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
1030 | return r; | 1030 | return r; |
1031 | } | 1031 | } |
1032 | rdev->cp.ready = true; | 1032 | rdev->cp.ready = true; |
1033 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | ||
1033 | return 0; | 1034 | return 0; |
1034 | } | 1035 | } |
1035 | 1036 | ||
@@ -1047,6 +1048,7 @@ void r100_cp_fini(struct radeon_device *rdev) | |||
1047 | void r100_cp_disable(struct radeon_device *rdev) | 1048 | void r100_cp_disable(struct radeon_device *rdev) |
1048 | { | 1049 | { |
1049 | /* Disable ring */ | 1050 | /* Disable ring */ |
1051 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1050 | rdev->cp.ready = false; | 1052 | rdev->cp.ready = false; |
1051 | WREG32(RADEON_CP_CSQ_MODE, 0); | 1053 | WREG32(RADEON_CP_CSQ_MODE, 0); |
1052 | WREG32(RADEON_CP_CSQ_CNTL, 0); | 1054 | WREG32(RADEON_CP_CSQ_CNTL, 0); |
@@ -2295,6 +2297,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev) | |||
2295 | /* FIXME we don't use the second aperture yet when we could use it */ | 2297 | /* FIXME we don't use the second aperture yet when we could use it */ |
2296 | if (rdev->mc.visible_vram_size > rdev->mc.aper_size) | 2298 | if (rdev->mc.visible_vram_size > rdev->mc.aper_size) |
2297 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 2299 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
2300 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
2298 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | 2301 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); |
2299 | if (rdev->flags & RADEON_IS_IGP) { | 2302 | if (rdev->flags & RADEON_IS_IGP) { |
2300 | uint32_t tom; | 2303 | uint32_t tom; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 7a04959ba0ee..7b65e4efe8af 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1248,6 +1248,7 @@ int r600_mc_init(struct radeon_device *rdev) | |||
1248 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); | 1248 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); |
1249 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); | 1249 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
1250 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 1250 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
1251 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1251 | r600_vram_gtt_location(rdev, &rdev->mc); | 1252 | r600_vram_gtt_location(rdev, &rdev->mc); |
1252 | 1253 | ||
1253 | if (rdev->flags & RADEON_IS_IGP) { | 1254 | if (rdev->flags & RADEON_IS_IGP) { |
@@ -1917,6 +1918,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) | |||
1917 | */ | 1918 | */ |
1918 | void r600_cp_stop(struct radeon_device *rdev) | 1919 | void r600_cp_stop(struct radeon_device *rdev) |
1919 | { | 1920 | { |
1921 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1920 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | 1922 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); |
1921 | } | 1923 | } |
1922 | 1924 | ||
@@ -2910,7 +2912,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) | |||
2910 | { | 2912 | { |
2911 | u32 tmp; | 2913 | u32 tmp; |
2912 | 2914 | ||
2913 | WREG32(CP_INT_CNTL, 0); | 2915 | WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); |
2914 | WREG32(GRBM_INT_CNTL, 0); | 2916 | WREG32(GRBM_INT_CNTL, 0); |
2915 | WREG32(DxMODE_INT_MASK, 0); | 2917 | WREG32(DxMODE_INT_MASK, 0); |
2916 | if (ASIC_IS_DCE3(rdev)) { | 2918 | if (ASIC_IS_DCE3(rdev)) { |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 9ceb2a1ce799..3473c00781ff 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -532,6 +532,7 @@ int r600_blit_init(struct radeon_device *rdev) | |||
532 | memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); | 532 | memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); |
533 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 533 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
534 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 534 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
535 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | ||
535 | return 0; | 536 | return 0; |
536 | } | 537 | } |
537 | 538 | ||
@@ -539,6 +540,7 @@ void r600_blit_fini(struct radeon_device *rdev) | |||
539 | { | 540 | { |
540 | int r; | 541 | int r; |
541 | 542 | ||
543 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
542 | if (rdev->r600_blit.shader_obj == NULL) | 544 | if (rdev->r600_blit.shader_obj == NULL) |
543 | return; | 545 | return; |
544 | /* If we can't reserve the bo, unref should be enough to destroy | 546 | /* If we can't reserve the bo, unref should be enough to destroy |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a168d644bf9e..9ff38c99a6ea 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -344,6 +344,7 @@ struct radeon_mc { | |||
344 | * about vram size near mc fb location */ | 344 | * about vram size near mc fb location */ |
345 | u64 mc_vram_size; | 345 | u64 mc_vram_size; |
346 | u64 visible_vram_size; | 346 | u64 visible_vram_size; |
347 | u64 active_vram_size; | ||
347 | u64 gtt_size; | 348 | u64 gtt_size; |
348 | u64 gtt_start; | 349 | u64 gtt_start; |
349 | u64 gtt_end; | 350 | u64 gtt_end; |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 68932ba7b8a4..8e43ddae70cc 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -1558,39 +1558,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) | |||
1558 | switch (tv_info->ucTV_BootUpDefaultStandard) { | 1558 | switch (tv_info->ucTV_BootUpDefaultStandard) { |
1559 | case ATOM_TV_NTSC: | 1559 | case ATOM_TV_NTSC: |
1560 | tv_std = TV_STD_NTSC; | 1560 | tv_std = TV_STD_NTSC; |
1561 | DRM_INFO("Default TV standard: NTSC\n"); | 1561 | DRM_DEBUG_KMS("Default TV standard: NTSC\n"); |
1562 | break; | 1562 | break; |
1563 | case ATOM_TV_NTSCJ: | 1563 | case ATOM_TV_NTSCJ: |
1564 | tv_std = TV_STD_NTSC_J; | 1564 | tv_std = TV_STD_NTSC_J; |
1565 | DRM_INFO("Default TV standard: NTSC-J\n"); | 1565 | DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); |
1566 | break; | 1566 | break; |
1567 | case ATOM_TV_PAL: | 1567 | case ATOM_TV_PAL: |
1568 | tv_std = TV_STD_PAL; | 1568 | tv_std = TV_STD_PAL; |
1569 | DRM_INFO("Default TV standard: PAL\n"); | 1569 | DRM_DEBUG_KMS("Default TV standard: PAL\n"); |
1570 | break; | 1570 | break; |
1571 | case ATOM_TV_PALM: | 1571 | case ATOM_TV_PALM: |
1572 | tv_std = TV_STD_PAL_M; | 1572 | tv_std = TV_STD_PAL_M; |
1573 | DRM_INFO("Default TV standard: PAL-M\n"); | 1573 | DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); |
1574 | break; | 1574 | break; |
1575 | case ATOM_TV_PALN: | 1575 | case ATOM_TV_PALN: |
1576 | tv_std = TV_STD_PAL_N; | 1576 | tv_std = TV_STD_PAL_N; |
1577 | DRM_INFO("Default TV standard: PAL-N\n"); | 1577 | DRM_DEBUG_KMS("Default TV standard: PAL-N\n"); |
1578 | break; | 1578 | break; |
1579 | case ATOM_TV_PALCN: | 1579 | case ATOM_TV_PALCN: |
1580 | tv_std = TV_STD_PAL_CN; | 1580 | tv_std = TV_STD_PAL_CN; |
1581 | DRM_INFO("Default TV standard: PAL-CN\n"); | 1581 | DRM_DEBUG_KMS("Default TV standard: PAL-CN\n"); |
1582 | break; | 1582 | break; |
1583 | case ATOM_TV_PAL60: | 1583 | case ATOM_TV_PAL60: |
1584 | tv_std = TV_STD_PAL_60; | 1584 | tv_std = TV_STD_PAL_60; |
1585 | DRM_INFO("Default TV standard: PAL-60\n"); | 1585 | DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); |
1586 | break; | 1586 | break; |
1587 | case ATOM_TV_SECAM: | 1587 | case ATOM_TV_SECAM: |
1588 | tv_std = TV_STD_SECAM; | 1588 | tv_std = TV_STD_SECAM; |
1589 | DRM_INFO("Default TV standard: SECAM\n"); | 1589 | DRM_DEBUG_KMS("Default TV standard: SECAM\n"); |
1590 | break; | 1590 | break; |
1591 | default: | 1591 | default: |
1592 | tv_std = TV_STD_NTSC; | 1592 | tv_std = TV_STD_NTSC; |
1593 | DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); | 1593 | DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n"); |
1594 | break; | 1594 | break; |
1595 | } | 1595 | } |
1596 | } | 1596 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index a04b7a6ad95f..7b7ea269549c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) | |||
913 | switch (RBIOS8(tv_info + 7) & 0xf) { | 913 | switch (RBIOS8(tv_info + 7) & 0xf) { |
914 | case 1: | 914 | case 1: |
915 | tv_std = TV_STD_NTSC; | 915 | tv_std = TV_STD_NTSC; |
916 | DRM_INFO("Default TV standard: NTSC\n"); | 916 | DRM_DEBUG_KMS("Default TV standard: NTSC\n"); |
917 | break; | 917 | break; |
918 | case 2: | 918 | case 2: |
919 | tv_std = TV_STD_PAL; | 919 | tv_std = TV_STD_PAL; |
920 | DRM_INFO("Default TV standard: PAL\n"); | 920 | DRM_DEBUG_KMS("Default TV standard: PAL\n"); |
921 | break; | 921 | break; |
922 | case 3: | 922 | case 3: |
923 | tv_std = TV_STD_PAL_M; | 923 | tv_std = TV_STD_PAL_M; |
924 | DRM_INFO("Default TV standard: PAL-M\n"); | 924 | DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); |
925 | break; | 925 | break; |
926 | case 4: | 926 | case 4: |
927 | tv_std = TV_STD_PAL_60; | 927 | tv_std = TV_STD_PAL_60; |
928 | DRM_INFO("Default TV standard: PAL-60\n"); | 928 | DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); |
929 | break; | 929 | break; |
930 | case 5: | 930 | case 5: |
931 | tv_std = TV_STD_NTSC_J; | 931 | tv_std = TV_STD_NTSC_J; |
932 | DRM_INFO("Default TV standard: NTSC-J\n"); | 932 | DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); |
933 | break; | 933 | break; |
934 | case 6: | 934 | case 6: |
935 | tv_std = TV_STD_SCART_PAL; | 935 | tv_std = TV_STD_SCART_PAL; |
936 | DRM_INFO("Default TV standard: SCART-PAL\n"); | 936 | DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n"); |
937 | break; | 937 | break; |
938 | default: | 938 | default: |
939 | tv_std = TV_STD_NTSC; | 939 | tv_std = TV_STD_NTSC; |
940 | DRM_INFO | 940 | DRM_DEBUG_KMS |
941 | ("Unknown TV standard; defaulting to NTSC\n"); | 941 | ("Unknown TV standard; defaulting to NTSC\n"); |
942 | break; | 942 | break; |
943 | } | 943 | } |
944 | 944 | ||
945 | switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { | 945 | switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { |
946 | case 0: | 946 | case 0: |
947 | DRM_INFO("29.498928713 MHz TV ref clk\n"); | 947 | DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n"); |
948 | break; | 948 | break; |
949 | case 1: | 949 | case 1: |
950 | DRM_INFO("28.636360000 MHz TV ref clk\n"); | 950 | DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n"); |
951 | break; | 951 | break; |
952 | case 2: | 952 | case 2: |
953 | DRM_INFO("14.318180000 MHz TV ref clk\n"); | 953 | DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n"); |
954 | break; | 954 | break; |
955 | case 3: | 955 | case 3: |
956 | DRM_INFO("27.000000000 MHz TV ref clk\n"); | 956 | DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n"); |
957 | break; | 957 | break; |
958 | default: | 958 | default: |
959 | break; | 959 | break; |
@@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, | |||
1324 | 1324 | ||
1325 | if (tmds_info) { | 1325 | if (tmds_info) { |
1326 | ver = RBIOS8(tmds_info); | 1326 | ver = RBIOS8(tmds_info); |
1327 | DRM_INFO("DFP table revision: %d\n", ver); | 1327 | DRM_DEBUG_KMS("DFP table revision: %d\n", ver); |
1328 | if (ver == 3) { | 1328 | if (ver == 3) { |
1329 | n = RBIOS8(tmds_info + 5) + 1; | 1329 | n = RBIOS8(tmds_info + 5) + 1; |
1330 | if (n > 4) | 1330 | if (n > 4) |
@@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder | |||
1408 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); | 1408 | offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); |
1409 | if (offset) { | 1409 | if (offset) { |
1410 | ver = RBIOS8(offset); | 1410 | ver = RBIOS8(offset); |
1411 | DRM_INFO("External TMDS Table revision: %d\n", ver); | 1411 | DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver); |
1412 | tmds->slave_addr = RBIOS8(offset + 4 + 2); | 1412 | tmds->slave_addr = RBIOS8(offset + 4 + 2); |
1413 | tmds->slave_addr >>= 1; /* 7 bit addressing */ | 1413 | tmds->slave_addr >>= 1; /* 7 bit addressing */ |
1414 | gpio = RBIOS8(offset + 4 + 3); | 1414 | gpio = RBIOS8(offset + 4 + 3); |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 5731fc9b1ae3..3eef567b0421 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -203,6 +203,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
203 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 203 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
204 | struct radeon_device *rdev = crtc->dev->dev_private; | 204 | struct radeon_device *rdev = crtc->dev->dev_private; |
205 | int xorigin = 0, yorigin = 0; | 205 | int xorigin = 0, yorigin = 0; |
206 | int w = radeon_crtc->cursor_width; | ||
206 | 207 | ||
207 | if (x < 0) | 208 | if (x < 0) |
208 | xorigin = -x + 1; | 209 | xorigin = -x + 1; |
@@ -213,22 +214,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
213 | if (yorigin >= CURSOR_HEIGHT) | 214 | if (yorigin >= CURSOR_HEIGHT) |
214 | yorigin = CURSOR_HEIGHT - 1; | 215 | yorigin = CURSOR_HEIGHT - 1; |
215 | 216 | ||
216 | radeon_lock_cursor(crtc, true); | 217 | if (ASIC_IS_AVIVO(rdev)) { |
217 | if (ASIC_IS_DCE4(rdev)) { | ||
218 | /* cursors are offset into the total surface */ | ||
219 | x += crtc->x; | ||
220 | y += crtc->y; | ||
221 | DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); | ||
222 | |||
223 | /* XXX: check if evergreen has the same issues as avivo chips */ | ||
224 | WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, | ||
225 | ((xorigin ? 0 : x) << 16) | | ||
226 | (yorigin ? 0 : y)); | ||
227 | WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); | ||
228 | WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, | ||
229 | ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1)); | ||
230 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
231 | int w = radeon_crtc->cursor_width; | ||
232 | int i = 0; | 218 | int i = 0; |
233 | struct drm_crtc *crtc_p; | 219 | struct drm_crtc *crtc_p; |
234 | 220 | ||
@@ -260,7 +246,17 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
260 | if (w <= 0) | 246 | if (w <= 0) |
261 | w = 1; | 247 | w = 1; |
262 | } | 248 | } |
249 | } | ||
263 | 250 | ||
251 | radeon_lock_cursor(crtc, true); | ||
252 | if (ASIC_IS_DCE4(rdev)) { | ||
253 | WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, | ||
254 | ((xorigin ? 0 : x) << 16) | | ||
255 | (yorigin ? 0 : y)); | ||
256 | WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); | ||
257 | WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, | ||
258 | ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); | ||
259 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
264 | WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, | 260 | WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, |
265 | ((xorigin ? 0 : x) << 16) | | 261 | ((xorigin ? 0 : x) << 16) | |
266 | (yorigin ? 0 : y)); | 262 | (yorigin ? 0 : y)); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 0afd1e62347d..b3b5306bb578 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
69 | u32 c = 0; | 69 | u32 c = 0; |
70 | 70 | ||
71 | rbo->placement.fpfn = 0; | 71 | rbo->placement.fpfn = 0; |
72 | rbo->placement.lpfn = 0; | 72 | rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT; |
73 | rbo->placement.placement = rbo->placements; | 73 | rbo->placement.placement = rbo->placements; |
74 | rbo->placement.busy_placement = rbo->placements; | 74 | rbo->placement.busy_placement = rbo->placements; |
75 | if (domain & RADEON_GEM_DOMAIN_VRAM) | 75 | if (domain & RADEON_GEM_DOMAIN_VRAM) |
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 353998dc2c03..3481bc7f6f58 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h | |||
@@ -124,11 +124,8 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, | |||
124 | int r; | 124 | int r; |
125 | 125 | ||
126 | r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); | 126 | r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); |
127 | if (unlikely(r != 0)) { | 127 | if (unlikely(r != 0)) |
128 | if (r != -ERESTARTSYS) | ||
129 | dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); | ||
130 | return r; | 128 | return r; |
131 | } | ||
132 | spin_lock(&bo->tbo.lock); | 129 | spin_lock(&bo->tbo.lock); |
133 | if (mem_type) | 130 | if (mem_type) |
134 | *mem_type = bo->tbo.mem.mem_type; | 131 | *mem_type = bo->tbo.mem.mem_type; |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index cc05b230d7ef..51d5f7b5ab21 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -693,6 +693,7 @@ void rs600_mc_init(struct radeon_device *rdev) | |||
693 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 693 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
694 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | 694 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
695 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 695 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
696 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
696 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); | 697 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); |
697 | base = RREG32_MC(R_000004_MC_FB_LOCATION); | 698 | base = RREG32_MC(R_000004_MC_FB_LOCATION); |
698 | base = G_000004_MC_FB_START(base) << 16; | 699 | base = G_000004_MC_FB_START(base) << 16; |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 3e3f75718be3..4dc2a87ea680 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
@@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev) | |||
157 | rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); | 157 | rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); |
158 | rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); | 158 | rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); |
159 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 159 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
160 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
160 | base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); | 161 | base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); |
161 | base = G_000100_MC_FB_START(base) << 16; | 162 | base = G_000100_MC_FB_START(base) << 16; |
162 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); | 163 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index bfa59db374d2..9490da700749 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -267,6 +267,7 @@ static void rv770_mc_program(struct radeon_device *rdev) | |||
267 | */ | 267 | */ |
268 | void r700_cp_stop(struct radeon_device *rdev) | 268 | void r700_cp_stop(struct radeon_device *rdev) |
269 | { | 269 | { |
270 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
270 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); | 271 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); |
271 | } | 272 | } |
272 | 273 | ||
@@ -992,6 +993,7 @@ int rv770_mc_init(struct radeon_device *rdev) | |||
992 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); | 993 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); |
993 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); | 994 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
994 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 995 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
996 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
995 | r600_vram_gtt_location(rdev, &rdev->mc); | 997 | r600_vram_gtt_location(rdev, &rdev->mc); |
996 | radeon_update_bandwidth_info(rdev); | 998 | radeon_update_bandwidth_info(rdev); |
997 | 999 | ||
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c index 4267a6fdc277..5925bdcd417d 100644 --- a/drivers/hid/hid-cando.c +++ b/drivers/hid/hid-cando.c | |||
@@ -237,6 +237,8 @@ static const struct hid_device_id cando_devices[] = { | |||
237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
240 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
241 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
240 | { } | 242 | { } |
241 | }; | 243 | }; |
242 | MODULE_DEVICE_TABLE(hid, cando_devices); | 244 | MODULE_DEVICE_TABLE(hid, cando_devices); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3f7292486024..a0dea3d1296e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1292,6 +1292,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, |
1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, |
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 765a4f53eb5c..c5ae5f1545bd 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -134,6 +134,7 @@ | |||
134 | #define USB_VENDOR_ID_CANDO 0x2087 | 134 | #define USB_VENDOR_ID_CANDO 0x2087 |
135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
136 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 | 136 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 |
137 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 | ||
137 | 138 | ||
138 | #define USB_VENDOR_ID_CH 0x068e | 139 | #define USB_VENDOR_ID_CH 0x068e |
139 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 | 140 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 |
@@ -503,6 +504,7 @@ | |||
503 | 504 | ||
504 | #define USB_VENDOR_ID_TURBOX 0x062a | 505 | #define USB_VENDOR_ID_TURBOX 0x062a |
505 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 506 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
507 | #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 | ||
506 | 508 | ||
507 | #define USB_VENDOR_ID_TWINHAN 0x6253 | 509 | #define USB_VENDOR_ID_TWINHAN 0x6253 |
508 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 | 510 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 47d70c523d93..a3866b5c0c43 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -109,6 +109,12 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t | |||
109 | int ret = 0; | 109 | int ret = 0; |
110 | 110 | ||
111 | mutex_lock(&minors_lock); | 111 | mutex_lock(&minors_lock); |
112 | |||
113 | if (!hidraw_table[minor]) { | ||
114 | ret = -ENODEV; | ||
115 | goto out; | ||
116 | } | ||
117 | |||
112 | dev = hidraw_table[minor]->hid; | 118 | dev = hidraw_table[minor]->hid; |
113 | 119 | ||
114 | if (!dev->hid_output_raw_report) { | 120 | if (!dev->hid_output_raw_report) { |
@@ -244,6 +250,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
244 | 250 | ||
245 | mutex_lock(&minors_lock); | 251 | mutex_lock(&minors_lock); |
246 | dev = hidraw_table[minor]; | 252 | dev = hidraw_table[minor]; |
253 | if (!dev) { | ||
254 | ret = -ENODEV; | ||
255 | goto out; | ||
256 | } | ||
247 | 257 | ||
248 | switch (cmd) { | 258 | switch (cmd) { |
249 | case HIDIOCGRDESCSIZE: | 259 | case HIDIOCGRDESCSIZE: |
@@ -317,6 +327,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
317 | 327 | ||
318 | ret = -ENOTTY; | 328 | ret = -ENOTTY; |
319 | } | 329 | } |
330 | out: | ||
320 | mutex_unlock(&minors_lock); | 331 | mutex_unlock(&minors_lock); |
321 | return ret; | 332 | return ret; |
322 | } | 333 | } |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 70da3181c8a0..f0260c699adb 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -36,6 +36,7 @@ static const struct hid_blacklist { | |||
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, |
37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, |
38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
39 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, | ||
39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 42 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index b8feac5f2ef4..5795c8398c7c 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c | |||
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
331 | INIT_COMPLETION(dev->cmd_complete); | 331 | INIT_COMPLETION(dev->cmd_complete); |
332 | dev->cmd_err = 0; | 332 | dev->cmd_err = 0; |
333 | 333 | ||
334 | /* Take I2C out of reset, configure it as master and set the | 334 | /* Take I2C out of reset and configure it as master */ |
335 | * start bit */ | 335 | flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; |
336 | flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; | ||
337 | 336 | ||
338 | /* if the slave address is ten bit address, enable XA bit */ | 337 | /* if the slave address is ten bit address, enable XA bit */ |
339 | if (msg->flags & I2C_M_TEN) | 338 | if (msg->flags & I2C_M_TEN) |
340 | flag |= DAVINCI_I2C_MDR_XA; | 339 | flag |= DAVINCI_I2C_MDR_XA; |
341 | if (!(msg->flags & I2C_M_RD)) | 340 | if (!(msg->flags & I2C_M_RD)) |
342 | flag |= DAVINCI_I2C_MDR_TRX; | 341 | flag |= DAVINCI_I2C_MDR_TRX; |
343 | if (stop) | 342 | if (msg->len == 0) |
344 | flag |= DAVINCI_I2C_MDR_STP; | ||
345 | if (msg->len == 0) { | ||
346 | flag |= DAVINCI_I2C_MDR_RM; | 343 | flag |= DAVINCI_I2C_MDR_RM; |
347 | flag &= ~DAVINCI_I2C_MDR_STP; | ||
348 | } | ||
349 | 344 | ||
350 | /* Enable receive or transmit interrupts */ | 345 | /* Enable receive or transmit interrupts */ |
351 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); | 346 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); |
@@ -358,17 +353,28 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
358 | dev->terminate = 0; | 353 | dev->terminate = 0; |
359 | 354 | ||
360 | /* | 355 | /* |
356 | * Write mode register first as needed for correct behaviour | ||
357 | * on OMAP-L138, but don't set STT yet to avoid a race with XRDY | ||
358 | * occuring before we have loaded DXR | ||
359 | */ | ||
360 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | ||
361 | |||
362 | /* | ||
361 | * First byte should be set here, not after interrupt, | 363 | * First byte should be set here, not after interrupt, |
362 | * because transmit-data-ready interrupt can come before | 364 | * because transmit-data-ready interrupt can come before |
363 | * NACK-interrupt during sending of previous message and | 365 | * NACK-interrupt during sending of previous message and |
364 | * ICDXR may have wrong data | 366 | * ICDXR may have wrong data |
367 | * It also saves us one interrupt, slightly faster | ||
365 | */ | 368 | */ |
366 | if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { | 369 | if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { |
367 | davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); | 370 | davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); |
368 | dev->buf_len--; | 371 | dev->buf_len--; |
369 | } | 372 | } |
370 | 373 | ||
371 | /* write the data into mode register; start transmitting */ | 374 | /* Set STT to begin transmit now DXR is loaded */ |
375 | flag |= DAVINCI_I2C_MDR_STT; | ||
376 | if (stop && msg->len != 0) | ||
377 | flag |= DAVINCI_I2C_MDR_STP; | ||
372 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | 378 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); |
373 | 379 | ||
374 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, | 380 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, |
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index d1ff9408dc1f..4c2a62b75b5c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c | |||
@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) | |||
159 | 159 | ||
160 | static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) | 160 | static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) |
161 | { | 161 | { |
162 | int result; | 162 | wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); |
163 | |||
164 | result = wait_event_interruptible_timeout(i2c_imx->queue, | ||
165 | i2c_imx->i2csr & I2SR_IIF, HZ / 10); | ||
166 | 163 | ||
167 | if (unlikely(result < 0)) { | 164 | if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { |
168 | dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); | ||
169 | return result; | ||
170 | } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { | ||
171 | dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); | 165 | dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); |
172 | return -ETIMEDOUT; | 166 | return -ETIMEDOUT; |
173 | } | 167 | } |
@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) | |||
295 | i2c_imx->i2csr = temp; | 289 | i2c_imx->i2csr = temp; |
296 | temp &= ~I2SR_IIF; | 290 | temp &= ~I2SR_IIF; |
297 | writeb(temp, i2c_imx->base + IMX_I2C_I2SR); | 291 | writeb(temp, i2c_imx->base + IMX_I2C_I2SR); |
298 | wake_up_interruptible(&i2c_imx->queue); | 292 | wake_up(&i2c_imx->queue); |
299 | return IRQ_HANDLED; | 293 | return IRQ_HANDLED; |
300 | } | 294 | } |
301 | 295 | ||
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 2a4cb9c18f01..404843e8611b 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
45 | 45 | ||
46 | #include <pcmcia/cs.h> | ||
47 | #include <pcmcia/cistpl.h> | 46 | #include <pcmcia/cistpl.h> |
48 | #include <pcmcia/ds.h> | 47 | #include <pcmcia/ds.h> |
49 | #include <pcmcia/cisreg.h> | 48 | #include <pcmcia/cisreg.h> |
@@ -72,17 +71,6 @@ static int ide_config(struct pcmcia_device *); | |||
72 | 71 | ||
73 | static void ide_detach(struct pcmcia_device *p_dev); | 72 | static void ide_detach(struct pcmcia_device *p_dev); |
74 | 73 | ||
75 | |||
76 | |||
77 | |||
78 | /*====================================================================== | ||
79 | |||
80 | ide_attach() creates an "instance" of the driver, allocating | ||
81 | local data structures for one device. The device is registered | ||
82 | with Card Services. | ||
83 | |||
84 | ======================================================================*/ | ||
85 | |||
86 | static int ide_probe(struct pcmcia_device *link) | 74 | static int ide_probe(struct pcmcia_device *link) |
87 | { | 75 | { |
88 | ide_info_t *info; | 76 | ide_info_t *info; |
@@ -97,23 +85,12 @@ static int ide_probe(struct pcmcia_device *link) | |||
97 | info->p_dev = link; | 85 | info->p_dev = link; |
98 | link->priv = info; | 86 | link->priv = info; |
99 | 87 | ||
100 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 88 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO | |
101 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | 89 | CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; |
102 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
103 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
104 | 90 | ||
105 | return ide_config(link); | 91 | return ide_config(link); |
106 | } /* ide_attach */ | 92 | } /* ide_attach */ |
107 | 93 | ||
108 | /*====================================================================== | ||
109 | |||
110 | This deletes a driver "instance". The device is de-registered | ||
111 | with Card Services. If it has been released, all local data | ||
112 | structures are freed. Otherwise, the structures will be freed | ||
113 | when the device is released. | ||
114 | |||
115 | ======================================================================*/ | ||
116 | |||
117 | static void ide_detach(struct pcmcia_device *link) | 94 | static void ide_detach(struct pcmcia_device *link) |
118 | { | 95 | { |
119 | ide_info_t *info = link->priv; | 96 | ide_info_t *info = link->priv; |
@@ -187,79 +164,31 @@ out_release: | |||
187 | return NULL; | 164 | return NULL; |
188 | } | 165 | } |
189 | 166 | ||
190 | /*====================================================================== | 167 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) |
191 | |||
192 | ide_config() is scheduled to run after a CARD_INSERTION event | ||
193 | is received, to configure the PCMCIA socket, and to make the | ||
194 | ide device available to the system. | ||
195 | |||
196 | ======================================================================*/ | ||
197 | |||
198 | struct pcmcia_config_check { | ||
199 | unsigned long ctl_base; | ||
200 | int skip_vcc; | ||
201 | int is_kme; | ||
202 | }; | ||
203 | |||
204 | static int pcmcia_check_one_config(struct pcmcia_device *pdev, | ||
205 | cistpl_cftable_entry_t *cfg, | ||
206 | cistpl_cftable_entry_t *dflt, | ||
207 | unsigned int vcc, | ||
208 | void *priv_data) | ||
209 | { | 168 | { |
210 | struct pcmcia_config_check *stk = priv_data; | 169 | int *is_kme = priv_data; |
211 | |||
212 | /* Check for matching Vcc, unless we're desperate */ | ||
213 | if (!stk->skip_vcc) { | ||
214 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
215 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
216 | return -ENODEV; | ||
217 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
218 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | } | ||
222 | 170 | ||
223 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 171 | if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { |
224 | pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 172 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
225 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 173 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
226 | pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 174 | } |
227 | 175 | pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | |
228 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | 176 | pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
229 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | 177 | |
230 | pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 178 | if (pdev->resource[1]->end) { |
231 | 179 | pdev->resource[0]->end = 8; | |
232 | pdev->conf.ConfigIndex = cfg->index; | 180 | pdev->resource[1]->end = (*is_kme) ? 2 : 1; |
233 | pdev->resource[0]->start = io->win[0].base; | 181 | } else { |
234 | if (!(io->flags & CISTPL_IO_16BIT)) { | 182 | if (pdev->resource[0]->end < 16) |
235 | pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
236 | pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
237 | } | ||
238 | if (io->nwin == 2) { | ||
239 | pdev->resource[0]->end = 8; | ||
240 | pdev->resource[1]->start = io->win[1].base; | ||
241 | pdev->resource[1]->end = (stk->is_kme) ? 2 : 1; | ||
242 | if (pcmcia_request_io(pdev) != 0) | ||
243 | return -ENODEV; | ||
244 | stk->ctl_base = pdev->resource[1]->start; | ||
245 | } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { | ||
246 | pdev->resource[0]->end = io->win[0].len; | ||
247 | pdev->resource[1]->end = 0; | ||
248 | if (pcmcia_request_io(pdev) != 0) | ||
249 | return -ENODEV; | ||
250 | stk->ctl_base = pdev->resource[0]->start + 0x0e; | ||
251 | } else | ||
252 | return -ENODEV; | 183 | return -ENODEV; |
253 | /* If we've got this far, we're done */ | ||
254 | return 0; | ||
255 | } | 184 | } |
256 | return -ENODEV; | 185 | |
186 | return pcmcia_request_io(pdev); | ||
257 | } | 187 | } |
258 | 188 | ||
259 | static int ide_config(struct pcmcia_device *link) | 189 | static int ide_config(struct pcmcia_device *link) |
260 | { | 190 | { |
261 | ide_info_t *info = link->priv; | 191 | ide_info_t *info = link->priv; |
262 | struct pcmcia_config_check *stk = NULL; | ||
263 | int ret = 0, is_kme = 0; | 192 | int ret = 0, is_kme = 0; |
264 | unsigned long io_base, ctl_base; | 193 | unsigned long io_base, ctl_base; |
265 | struct ide_host *host; | 194 | struct ide_host *host; |
@@ -270,23 +199,21 @@ static int ide_config(struct pcmcia_device *link) | |||
270 | ((link->card_id == PRODID_KME_KXLC005_A) || | 199 | ((link->card_id == PRODID_KME_KXLC005_A) || |
271 | (link->card_id == PRODID_KME_KXLC005_B))); | 200 | (link->card_id == PRODID_KME_KXLC005_B))); |
272 | 201 | ||
273 | stk = kzalloc(sizeof(*stk), GFP_KERNEL); | 202 | if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) { |
274 | if (!stk) | 203 | link->config_flags &= ~CONF_AUTO_CHECK_VCC; |
275 | goto err_mem; | 204 | if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) |
276 | stk->is_kme = is_kme; | ||
277 | stk->skip_vcc = io_base = ctl_base = 0; | ||
278 | |||
279 | if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) { | ||
280 | stk->skip_vcc = 1; | ||
281 | if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) | ||
282 | goto failed; /* No suitable config found */ | 205 | goto failed; /* No suitable config found */ |
283 | } | 206 | } |
284 | io_base = link->resource[0]->start; | 207 | io_base = link->resource[0]->start; |
285 | ctl_base = stk->ctl_base; | 208 | if (link->resource[1]->end) |
209 | ctl_base = link->resource[1]->start; | ||
210 | else | ||
211 | ctl_base = link->resource[0]->start + 0x0e; | ||
286 | 212 | ||
287 | if (!link->irq) | 213 | if (!link->irq) |
288 | goto failed; | 214 | goto failed; |
289 | ret = pcmcia_request_configuration(link, &link->conf); | 215 | |
216 | ret = pcmcia_enable_device(link); | ||
290 | if (ret) | 217 | if (ret) |
291 | goto failed; | 218 | goto failed; |
292 | 219 | ||
@@ -311,29 +238,15 @@ static int ide_config(struct pcmcia_device *link) | |||
311 | info->host = host; | 238 | info->host = host; |
312 | dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n", | 239 | dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n", |
313 | 'a' + host->ports[0]->index * 2, | 240 | 'a' + host->ports[0]->index * 2, |
314 | link->conf.Vpp / 10, link->conf.Vpp % 10); | 241 | link->vpp / 10, link->vpp % 10); |
315 | 242 | ||
316 | kfree(stk); | ||
317 | return 0; | 243 | return 0; |
318 | 244 | ||
319 | err_mem: | ||
320 | printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); | ||
321 | goto failed; | ||
322 | |||
323 | failed: | 245 | failed: |
324 | kfree(stk); | ||
325 | ide_release(link); | 246 | ide_release(link); |
326 | return -ENODEV; | 247 | return -ENODEV; |
327 | } /* ide_config */ | 248 | } /* ide_config */ |
328 | 249 | ||
329 | /*====================================================================== | ||
330 | |||
331 | After a card is removed, ide_release() will unregister the net | ||
332 | device, and release the PCMCIA configuration. If the device is | ||
333 | still open, this will be postponed until it is closed. | ||
334 | |||
335 | ======================================================================*/ | ||
336 | |||
337 | static void ide_release(struct pcmcia_device *link) | 250 | static void ide_release(struct pcmcia_device *link) |
338 | { | 251 | { |
339 | ide_info_t *info = link->priv; | 252 | ide_info_t *info = link->priv; |
@@ -359,15 +272,6 @@ static void ide_release(struct pcmcia_device *link) | |||
359 | } /* ide_release */ | 272 | } /* ide_release */ |
360 | 273 | ||
361 | 274 | ||
362 | /*====================================================================== | ||
363 | |||
364 | The card status event handler. Mostly, this schedules other | ||
365 | stuff to run after an event is received. A CARD_REMOVAL event | ||
366 | also sets some flags to discourage the ide drivers from | ||
367 | talking to the ports. | ||
368 | |||
369 | ======================================================================*/ | ||
370 | |||
371 | static struct pcmcia_device_id ide_ids[] = { | 275 | static struct pcmcia_device_id ide_ids[] = { |
372 | PCMCIA_DEVICE_FUNC_ID(4), | 276 | PCMCIA_DEVICE_FUNC_ID(4), |
373 | PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ | 277 | PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ |
@@ -440,9 +344,7 @@ MODULE_DEVICE_TABLE(pcmcia, ide_ids); | |||
440 | 344 | ||
441 | static struct pcmcia_driver ide_cs_driver = { | 345 | static struct pcmcia_driver ide_cs_driver = { |
442 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
443 | .drv = { | 347 | .name = "ide-cs", |
444 | .name = "ide-cs", | ||
445 | }, | ||
446 | .probe = ide_probe, | 348 | .probe = ide_probe, |
447 | .remove = ide_detach, | 349 | .remove = ide_detach, |
448 | .id_table = ide_ids, | 350 | .id_table = ide_ids, |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 0906fc5b69b9..cb3ccf3ed221 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -59,18 +59,11 @@ | |||
59 | #include <linux/hrtimer.h> /* ktime_get_real() */ | 59 | #include <linux/hrtimer.h> /* ktime_get_real() */ |
60 | #include <trace/events/power.h> | 60 | #include <trace/events/power.h> |
61 | #include <linux/sched.h> | 61 | #include <linux/sched.h> |
62 | #include <asm/mwait.h> | ||
62 | 63 | ||
63 | #define INTEL_IDLE_VERSION "0.4" | 64 | #define INTEL_IDLE_VERSION "0.4" |
64 | #define PREFIX "intel_idle: " | 65 | #define PREFIX "intel_idle: " |
65 | 66 | ||
66 | #define MWAIT_SUBSTATE_MASK (0xf) | ||
67 | #define MWAIT_CSTATE_MASK (0xf) | ||
68 | #define MWAIT_SUBSTATE_SIZE (4) | ||
69 | #define MWAIT_MAX_NUM_CSTATES 8 | ||
70 | #define CPUID_MWAIT_LEAF (5) | ||
71 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | ||
72 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | ||
73 | |||
74 | static struct cpuidle_driver intel_idle_driver = { | 67 | static struct cpuidle_driver intel_idle_driver = { |
75 | .name = "intel_idle", | 68 | .name = "intel_idle", |
76 | .owner = THIS_MODULE, | 69 | .owner = THIS_MODULE, |
@@ -157,13 +150,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { | |||
157 | { /* MWAIT C5 */ }, | 150 | { /* MWAIT C5 */ }, |
158 | { /* MWAIT C6 */ | 151 | { /* MWAIT C6 */ |
159 | .name = "ATM-C6", | 152 | .name = "ATM-C6", |
160 | .desc = "MWAIT 0x40", | 153 | .desc = "MWAIT 0x52", |
161 | .driver_data = (void *) 0x40, | 154 | .driver_data = (void *) 0x52, |
162 | .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | 155 | .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
163 | .exit_latency = 200, | 156 | .exit_latency = 140, |
164 | .power_usage = 150, | 157 | .power_usage = 150, |
165 | .target_residency = 800, | 158 | .target_residency = 560, |
166 | .enter = NULL }, /* disabled */ | 159 | .enter = &intel_idle }, |
167 | }; | 160 | }; |
168 | 161 | ||
169 | /** | 162 | /** |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index c908c5f83645..af9ee313c10b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -28,7 +28,7 @@ struct evdev { | |||
28 | int minor; | 28 | int minor; |
29 | struct input_handle handle; | 29 | struct input_handle handle; |
30 | wait_queue_head_t wait; | 30 | wait_queue_head_t wait; |
31 | struct evdev_client *grab; | 31 | struct evdev_client __rcu *grab; |
32 | struct list_head client_list; | 32 | struct list_head client_list; |
33 | spinlock_t client_lock; /* protects client_list */ | 33 | spinlock_t client_lock; /* protects client_list */ |
34 | struct mutex mutex; | 34 | struct mutex mutex; |
@@ -669,6 +669,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
669 | 669 | ||
670 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 670 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
671 | 671 | ||
672 | if (!dev->absinfo) | ||
673 | return -EINVAL; | ||
674 | |||
672 | t = _IOC_NR(cmd) & ABS_MAX; | 675 | t = _IOC_NR(cmd) & ABS_MAX; |
673 | abs = dev->absinfo[t]; | 676 | abs = dev->absinfo[t]; |
674 | 677 | ||
@@ -680,10 +683,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
680 | } | 683 | } |
681 | } | 684 | } |
682 | 685 | ||
683 | if (_IOC_DIR(cmd) == _IOC_READ) { | 686 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
684 | 687 | ||
685 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 688 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
686 | 689 | ||
690 | if (!dev->absinfo) | ||
691 | return -EINVAL; | ||
692 | |||
687 | t = _IOC_NR(cmd) & ABS_MAX; | 693 | t = _IOC_NR(cmd) & ABS_MAX; |
688 | 694 | ||
689 | if (copy_from_user(&abs, p, min_t(size_t, | 695 | if (copy_from_user(&abs, p, min_t(size_t, |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d21490..aa037fec2f86 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -338,7 +338,7 @@ config KEYBOARD_OPENCORES | |||
338 | 338 | ||
339 | config KEYBOARD_PXA27x | 339 | config KEYBOARD_PXA27x |
340 | tristate "PXA27x/PXA3xx keypad support" | 340 | tristate "PXA27x/PXA3xx keypad support" |
341 | depends on PXA27x || PXA3xx | 341 | depends on PXA27x || PXA3xx || ARCH_MMP |
342 | help | 342 | help |
343 | Enable support for PXA27x/PXA3xx keypad controller. | 343 | Enable support for PXA27x/PXA3xx keypad controller. |
344 | 344 | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index f32404f99189..4b0ec35259a1 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <asm/mach/map.h> | 32 | #include <asm/mach/map.h> |
33 | 33 | ||
34 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
35 | #include <mach/pxa27x_keypad.h> | 35 | #include <plat/pxa27x_keypad.h> |
36 | /* | 36 | /* |
37 | * Keypad Controller registers | 37 | * Keypad Controller registers |
38 | */ | 38 | */ |
@@ -330,11 +330,21 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
330 | keypad->direct_key_state = new_state; | 330 | keypad->direct_key_state = new_state; |
331 | } | 331 | } |
332 | 332 | ||
333 | static void clear_wakeup_event(struct pxa27x_keypad *keypad) | ||
334 | { | ||
335 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
336 | |||
337 | if (pdata->clear_wakeup_event) | ||
338 | (pdata->clear_wakeup_event)(); | ||
339 | } | ||
340 | |||
333 | static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) | 341 | static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) |
334 | { | 342 | { |
335 | struct pxa27x_keypad *keypad = dev_id; | 343 | struct pxa27x_keypad *keypad = dev_id; |
336 | unsigned long kpc = keypad_readl(KPC); | 344 | unsigned long kpc = keypad_readl(KPC); |
337 | 345 | ||
346 | clear_wakeup_event(keypad); | ||
347 | |||
338 | if (kpc & KPC_DI) | 348 | if (kpc & KPC_DI) |
339 | pxa27x_keypad_scan_direct(keypad); | 349 | pxa27x_keypad_scan_direct(keypad); |
340 | 350 | ||
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index c19066479057..7e2c12a5b839 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c | |||
@@ -104,7 +104,7 @@ static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm) | |||
104 | t.endidx = 91; | 104 | t.endidx = 91; |
105 | t.seq = tseq; | 105 | t.seq = tseq; |
106 | t.act.semaphore = &tsem; | 106 | t.act.semaphore = &tsem; |
107 | init_MUTEX_LOCKED(&tsem); | 107 | sema_init(&tsem, 0); |
108 | 108 | ||
109 | if (hp_sdc_enqueue_transaction(&t)) return -1; | 109 | if (hp_sdc_enqueue_transaction(&t)) return -1; |
110 | 110 | ||
@@ -698,7 +698,7 @@ static int __init hp_sdc_rtc_init(void) | |||
698 | return -ENODEV; | 698 | return -ENODEV; |
699 | #endif | 699 | #endif |
700 | 700 | ||
701 | init_MUTEX(&i8042tregs); | 701 | sema_init(&i8042tregs, 1); |
702 | 702 | ||
703 | if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) | 703 | if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) |
704 | return ret; | 704 | return ret; |
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index c92f4edfee7b..e5624d8f1709 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
@@ -915,15 +915,15 @@ int hil_mlc_register(hil_mlc *mlc) | |||
915 | mlc->ostarted = 0; | 915 | mlc->ostarted = 0; |
916 | 916 | ||
917 | rwlock_init(&mlc->lock); | 917 | rwlock_init(&mlc->lock); |
918 | init_MUTEX(&mlc->osem); | 918 | sema_init(&mlc->osem, 1); |
919 | 919 | ||
920 | init_MUTEX(&mlc->isem); | 920 | sema_init(&mlc->isem, 1); |
921 | mlc->icount = -1; | 921 | mlc->icount = -1; |
922 | mlc->imatch = 0; | 922 | mlc->imatch = 0; |
923 | 923 | ||
924 | mlc->opercnt = 0; | 924 | mlc->opercnt = 0; |
925 | 925 | ||
926 | init_MUTEX_LOCKED(&(mlc->csem)); | 926 | sema_init(&(mlc->csem), 0); |
927 | 927 | ||
928 | hil_mlc_clear_di_scratch(mlc); | 928 | hil_mlc_clear_di_scratch(mlc); |
929 | hil_mlc_clear_di_map(mlc, 0); | 929 | hil_mlc_clear_di_map(mlc, 0); |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index bcc2d30ec245..8c0b51c31424 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -905,7 +905,7 @@ static int __init hp_sdc_init(void) | |||
905 | ts_sync[1] = 0x0f; | 905 | ts_sync[1] = 0x0f; |
906 | ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; | 906 | ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; |
907 | t_sync.act.semaphore = &s_sync; | 907 | t_sync.act.semaphore = &s_sync; |
908 | init_MUTEX_LOCKED(&s_sync); | 908 | sema_init(&s_sync, 0); |
909 | hp_sdc_enqueue_transaction(&t_sync); | 909 | hp_sdc_enqueue_transaction(&t_sync); |
910 | down(&s_sync); /* Wait for t_sync to complete */ | 910 | down(&s_sync); /* Wait for t_sync to complete */ |
911 | 911 | ||
@@ -1039,7 +1039,7 @@ static int __init hp_sdc_register(void) | |||
1039 | return hp_sdc.dev_err; | 1039 | return hp_sdc.dev_err; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | init_MUTEX_LOCKED(&tq_init_sem); | 1042 | sema_init(&tq_init_sem, 0); |
1043 | 1043 | ||
1044 | tq_init.actidx = 0; | 1044 | tq_init.actidx = 0; |
1045 | tq_init.idx = 1; | 1045 | tq_init.idx = 1; |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 6e29badb969e..47fd7a041c52 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -442,8 +442,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom) | |||
442 | /* general pen packet */ | 442 | /* general pen packet */ |
443 | if ((data[1] & 0xb8) == 0xa0) { | 443 | if ((data[1] & 0xb8) == 0xa0) { |
444 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 444 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
445 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) | 445 | if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || |
446 | features->type == WACOM_21UX2) { | ||
446 | t = (t << 1) | (data[1] & 1); | 447 | t = (t << 1) | (data[1] & 1); |
448 | } | ||
447 | input_report_abs(input, ABS_PRESSURE, t); | 449 | input_report_abs(input, ABS_PRESSURE, t); |
448 | input_report_abs(input, ABS_TILT_X, | 450 | input_report_abs(input, ABS_TILT_X, |
449 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 451 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h index d4c50512a1ff..88c9423500d8 100644 --- a/drivers/isdn/act2000/act2000.h +++ b/drivers/isdn/act2000/act2000.h | |||
@@ -141,9 +141,9 @@ typedef struct irq_data_isa { | |||
141 | __u8 rcvhdr[8]; | 141 | __u8 rcvhdr[8]; |
142 | } irq_data_isa; | 142 | } irq_data_isa; |
143 | 143 | ||
144 | typedef union irq_data { | 144 | typedef union act2000_irq_data { |
145 | irq_data_isa isa; | 145 | irq_data_isa isa; |
146 | } irq_data; | 146 | } act2000_irq_data; |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * Per card driver data | 149 | * Per card driver data |
@@ -176,7 +176,7 @@ typedef struct act2000_card { | |||
176 | char *status_buf_read; | 176 | char *status_buf_read; |
177 | char *status_buf_write; | 177 | char *status_buf_write; |
178 | char *status_buf_end; | 178 | char *status_buf_end; |
179 | irq_data idat; /* Data used for IRQ handler */ | 179 | act2000_irq_data idat; /* Data used for IRQ handler */ |
180 | isdn_if interface; /* Interface to upper layer */ | 180 | isdn_if interface; /* Interface to upper layer */ |
181 | char regname[35]; /* Name used for request_region */ | 181 | char regname[35]; /* Name used for request_region */ |
182 | } act2000_card; | 182 | } act2000_card; |
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 09b1795516f4..91f06a3ef002 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <asm/system.h> | 21 | #include <asm/system.h> |
22 | 22 | ||
23 | #include <pcmcia/cs.h> | ||
24 | #include <pcmcia/cistpl.h> | 23 | #include <pcmcia/cistpl.h> |
25 | #include <pcmcia/ciscode.h> | 24 | #include <pcmcia/ciscode.h> |
26 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
@@ -39,87 +38,32 @@ MODULE_LICENSE("GPL"); | |||
39 | 38 | ||
40 | /*====================================================================*/ | 39 | /*====================================================================*/ |
41 | 40 | ||
42 | /* | ||
43 | The event() function is this driver's Card Services event handler. | ||
44 | It will be called by Card Services when an appropriate card status | ||
45 | event is received. The config() and release() entry points are | ||
46 | used to configure or release a socket, in response to card insertion | ||
47 | and ejection events. They are invoked from the skeleton event | ||
48 | handler. | ||
49 | */ | ||
50 | |||
51 | static int avmcs_config(struct pcmcia_device *link); | 41 | static int avmcs_config(struct pcmcia_device *link); |
52 | static void avmcs_release(struct pcmcia_device *link); | 42 | static void avmcs_release(struct pcmcia_device *link); |
53 | |||
54 | /* | ||
55 | The attach() and detach() entry points are used to create and destroy | ||
56 | "instances" of the driver, where each instance represents everything | ||
57 | needed to manage one actual PCMCIA card. | ||
58 | */ | ||
59 | |||
60 | static void avmcs_detach(struct pcmcia_device *p_dev); | 43 | static void avmcs_detach(struct pcmcia_device *p_dev); |
61 | 44 | ||
62 | /*====================================================================== | ||
63 | |||
64 | avmcs_attach() creates an "instance" of the driver, allocating | ||
65 | local data structures for one device. The device is registered | ||
66 | with Card Services. | ||
67 | |||
68 | The dev_link structure is initialized, but we don't actually | ||
69 | configure the card at this point -- we wait until we receive a | ||
70 | card insertion event. | ||
71 | |||
72 | ======================================================================*/ | ||
73 | |||
74 | static int avmcs_probe(struct pcmcia_device *p_dev) | 45 | static int avmcs_probe(struct pcmcia_device *p_dev) |
75 | { | 46 | { |
76 | |||
77 | /* The io structure describes IO port mapping */ | ||
78 | p_dev->resource[0]->end = 16; | ||
79 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
80 | |||
81 | /* General socket configuration */ | 47 | /* General socket configuration */ |
82 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 48 | p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
83 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 49 | p_dev->config_index = 1; |
84 | p_dev->conf.ConfigIndex = 1; | 50 | p_dev->config_regs = PRESENT_OPTION; |
85 | p_dev->conf.Present = PRESENT_OPTION; | ||
86 | 51 | ||
87 | return avmcs_config(p_dev); | 52 | return avmcs_config(p_dev); |
88 | } /* avmcs_attach */ | 53 | } /* avmcs_attach */ |
89 | 54 | ||
90 | /*====================================================================== | ||
91 | |||
92 | This deletes a driver "instance". The device is de-registered | ||
93 | with Card Services. If it has been released, all local data | ||
94 | structures are freed. Otherwise, the structures will be freed | ||
95 | when the device is released. | ||
96 | |||
97 | ======================================================================*/ | ||
98 | 55 | ||
99 | static void avmcs_detach(struct pcmcia_device *link) | 56 | static void avmcs_detach(struct pcmcia_device *link) |
100 | { | 57 | { |
101 | avmcs_release(link); | 58 | avmcs_release(link); |
102 | } /* avmcs_detach */ | 59 | } /* avmcs_detach */ |
103 | 60 | ||
104 | /*====================================================================== | 61 | static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
105 | |||
106 | avmcs_config() is scheduled to run after a CARD_INSERTION event | ||
107 | is received, to configure the PCMCIA socket, and to make the | ||
108 | ethernet device available to the system. | ||
109 | |||
110 | ======================================================================*/ | ||
111 | |||
112 | static int avmcs_configcheck(struct pcmcia_device *p_dev, | ||
113 | cistpl_cftable_entry_t *cf, | ||
114 | cistpl_cftable_entry_t *dflt, | ||
115 | unsigned int vcc, | ||
116 | void *priv_data) | ||
117 | { | 62 | { |
118 | if (cf->io.nwin <= 0) | 63 | p_dev->resource[0]->end = 16; |
119 | return -ENODEV; | 64 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
65 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
120 | 66 | ||
121 | p_dev->resource[0]->start = cf->io.win[0].base; | ||
122 | p_dev->resource[0]->end = cf->io.win[0].len; | ||
123 | return pcmcia_request_io(p_dev); | 67 | return pcmcia_request_io(p_dev); |
124 | } | 68 | } |
125 | 69 | ||
@@ -150,7 +94,7 @@ static int avmcs_config(struct pcmcia_device *link) | |||
150 | /* | 94 | /* |
151 | * configure the PCMCIA socket | 95 | * configure the PCMCIA socket |
152 | */ | 96 | */ |
153 | i = pcmcia_request_configuration(link, &link->conf); | 97 | i = pcmcia_enable_device(link); |
154 | if (i != 0) { | 98 | if (i != 0) { |
155 | pcmcia_disable_device(link); | 99 | pcmcia_disable_device(link); |
156 | break; | 100 | break; |
@@ -197,13 +141,6 @@ static int avmcs_config(struct pcmcia_device *link) | |||
197 | 141 | ||
198 | } /* avmcs_config */ | 142 | } /* avmcs_config */ |
199 | 143 | ||
200 | /*====================================================================== | ||
201 | |||
202 | After a card is removed, avmcs_release() will unregister the net | ||
203 | device, and release the PCMCIA configuration. If the device is | ||
204 | still open, this will be postponed until it is closed. | ||
205 | |||
206 | ======================================================================*/ | ||
207 | 144 | ||
208 | static void avmcs_release(struct pcmcia_device *link) | 145 | static void avmcs_release(struct pcmcia_device *link) |
209 | { | 146 | { |
@@ -222,9 +159,7 @@ MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); | |||
222 | 159 | ||
223 | static struct pcmcia_driver avmcs_driver = { | 160 | static struct pcmcia_driver avmcs_driver = { |
224 | .owner = THIS_MODULE, | 161 | .owner = THIS_MODULE, |
225 | .drv = { | 162 | .name = "avm_cs", |
226 | .name = "avm_cs", | ||
227 | }, | ||
228 | .probe = avmcs_probe, | 163 | .probe = avmcs_probe, |
229 | .remove = avmcs_detach, | 164 | .remove = avmcs_detach, |
230 | .id_table = avmcs_ids, | 165 | .id_table = avmcs_ids, |
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 94263c22b874..ac4dd7857cbd 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <asm/system.h> | 21 | #include <asm/system.h> |
22 | 22 | ||
23 | #include <pcmcia/cs.h> | ||
24 | #include <pcmcia/cistpl.h> | 23 | #include <pcmcia/cistpl.h> |
25 | #include <pcmcia/ds.h> | 24 | #include <pcmcia/ds.h> |
26 | #include "hisax_cfg.h" | 25 | #include "hisax_cfg.h" |
@@ -40,67 +39,22 @@ module_param(isdnprot, int, 0); | |||
40 | 39 | ||
41 | /*====================================================================*/ | 40 | /*====================================================================*/ |
42 | 41 | ||
43 | /* | ||
44 | The event() function is this driver's Card Services event handler. | ||
45 | It will be called by Card Services when an appropriate card status | ||
46 | event is received. The config() and release() entry points are | ||
47 | used to configure or release a socket, in response to card insertion | ||
48 | and ejection events. They are invoked from the skeleton event | ||
49 | handler. | ||
50 | */ | ||
51 | |||
52 | static int avma1cs_config(struct pcmcia_device *link) __devinit ; | 42 | static int avma1cs_config(struct pcmcia_device *link) __devinit ; |
53 | static void avma1cs_release(struct pcmcia_device *link); | 43 | static void avma1cs_release(struct pcmcia_device *link); |
54 | |||
55 | /* | ||
56 | The attach() and detach() entry points are used to create and destroy | ||
57 | "instances" of the driver, where each instance represents everything | ||
58 | needed to manage one actual PCMCIA card. | ||
59 | */ | ||
60 | |||
61 | static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ; | 44 | static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ; |
62 | 45 | ||
63 | |||
64 | /*====================================================================== | ||
65 | |||
66 | avma1cs_attach() creates an "instance" of the driver, allocating | ||
67 | local data structures for one device. The device is registered | ||
68 | with Card Services. | ||
69 | |||
70 | The dev_link structure is initialized, but we don't actually | ||
71 | configure the card at this point -- we wait until we receive a | ||
72 | card insertion event. | ||
73 | |||
74 | ======================================================================*/ | ||
75 | |||
76 | static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) | 46 | static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) |
77 | { | 47 | { |
78 | dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); | 48 | dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); |
79 | 49 | ||
80 | /* The io structure describes IO port mapping */ | ||
81 | p_dev->resource[0]->end = 16; | ||
82 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
83 | p_dev->resource[1]->end = 16; | ||
84 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; | ||
85 | |||
86 | /* General socket configuration */ | 50 | /* General socket configuration */ |
87 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 51 | p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
88 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 52 | p_dev->config_index = 1; |
89 | p_dev->conf.ConfigIndex = 1; | 53 | p_dev->config_regs = PRESENT_OPTION; |
90 | p_dev->conf.Present = PRESENT_OPTION; | ||
91 | 54 | ||
92 | return avma1cs_config(p_dev); | 55 | return avma1cs_config(p_dev); |
93 | } /* avma1cs_attach */ | 56 | } /* avma1cs_attach */ |
94 | 57 | ||
95 | /*====================================================================== | ||
96 | |||
97 | This deletes a driver "instance". The device is de-registered | ||
98 | with Card Services. If it has been released, all local data | ||
99 | structures are freed. Otherwise, the structures will be freed | ||
100 | when the device is released. | ||
101 | |||
102 | ======================================================================*/ | ||
103 | |||
104 | static void __devexit avma1cs_detach(struct pcmcia_device *link) | 58 | static void __devexit avma1cs_detach(struct pcmcia_device *link) |
105 | { | 59 | { |
106 | dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); | 60 | dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); |
@@ -108,26 +62,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link) | |||
108 | kfree(link->priv); | 62 | kfree(link->priv); |
109 | } /* avma1cs_detach */ | 63 | } /* avma1cs_detach */ |
110 | 64 | ||
111 | /*====================================================================== | 65 | static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
112 | |||
113 | avma1cs_config() is scheduled to run after a CARD_INSERTION event | ||
114 | is received, to configure the PCMCIA socket, and to make the | ||
115 | ethernet device available to the system. | ||
116 | |||
117 | ======================================================================*/ | ||
118 | |||
119 | static int avma1cs_configcheck(struct pcmcia_device *p_dev, | ||
120 | cistpl_cftable_entry_t *cf, | ||
121 | cistpl_cftable_entry_t *dflt, | ||
122 | unsigned int vcc, | ||
123 | void *priv_data) | ||
124 | { | 66 | { |
125 | if (cf->io.nwin <= 0) | 67 | p_dev->resource[0]->end = 16; |
126 | return -ENODEV; | 68 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
127 | 69 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | |
128 | p_dev->resource[0]->start = cf->io.win[0].base; | ||
129 | p_dev->resource[0]->end = cf->io.win[0].len; | ||
130 | p_dev->io_lines = 5; | 70 | p_dev->io_lines = 5; |
71 | |||
131 | return pcmcia_request_io(p_dev); | 72 | return pcmcia_request_io(p_dev); |
132 | } | 73 | } |
133 | 74 | ||
@@ -161,7 +102,7 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) | |||
161 | /* | 102 | /* |
162 | * configure the PCMCIA socket | 103 | * configure the PCMCIA socket |
163 | */ | 104 | */ |
164 | i = pcmcia_request_configuration(link, &link->conf); | 105 | i = pcmcia_enable_device(link); |
165 | if (i != 0) { | 106 | if (i != 0) { |
166 | pcmcia_disable_device(link); | 107 | pcmcia_disable_device(link); |
167 | break; | 108 | break; |
@@ -175,9 +116,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) | |||
175 | return -ENODEV; | 116 | return -ENODEV; |
176 | } | 117 | } |
177 | 118 | ||
178 | printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", | ||
179 | (unsigned int) link->resource[0]->start, link->irq); | ||
180 | |||
181 | icard.para[0] = link->irq; | 119 | icard.para[0] = link->irq; |
182 | icard.para[1] = link->resource[0]->start; | 120 | icard.para[1] = link->resource[0]->start; |
183 | icard.protocol = isdnprot; | 121 | icard.protocol = isdnprot; |
@@ -196,14 +134,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) | |||
196 | return 0; | 134 | return 0; |
197 | } /* avma1cs_config */ | 135 | } /* avma1cs_config */ |
198 | 136 | ||
199 | /*====================================================================== | ||
200 | |||
201 | After a card is removed, avma1cs_release() will unregister the net | ||
202 | device, and release the PCMCIA configuration. If the device is | ||
203 | still open, this will be postponed until it is closed. | ||
204 | |||
205 | ======================================================================*/ | ||
206 | |||
207 | static void avma1cs_release(struct pcmcia_device *link) | 137 | static void avma1cs_release(struct pcmcia_device *link) |
208 | { | 138 | { |
209 | unsigned long minor = (unsigned long) link->priv; | 139 | unsigned long minor = (unsigned long) link->priv; |
@@ -216,7 +146,6 @@ static void avma1cs_release(struct pcmcia_device *link) | |||
216 | pcmcia_disable_device(link); | 146 | pcmcia_disable_device(link); |
217 | } /* avma1cs_release */ | 147 | } /* avma1cs_release */ |
218 | 148 | ||
219 | |||
220 | static struct pcmcia_device_id avma1cs_ids[] = { | 149 | static struct pcmcia_device_id avma1cs_ids[] = { |
221 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), | 150 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), |
222 | PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b), | 151 | PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b), |
@@ -226,19 +155,15 @@ MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids); | |||
226 | 155 | ||
227 | static struct pcmcia_driver avma1cs_driver = { | 156 | static struct pcmcia_driver avma1cs_driver = { |
228 | .owner = THIS_MODULE, | 157 | .owner = THIS_MODULE, |
229 | .drv = { | 158 | .name = "avma1_cs", |
230 | .name = "avma1_cs", | ||
231 | }, | ||
232 | .probe = avma1cs_probe, | 159 | .probe = avma1cs_probe, |
233 | .remove = __devexit_p(avma1cs_detach), | 160 | .remove = __devexit_p(avma1cs_detach), |
234 | .id_table = avma1cs_ids, | 161 | .id_table = avma1cs_ids, |
235 | }; | 162 | }; |
236 | 163 | ||
237 | /*====================================================================*/ | ||
238 | |||
239 | static int __init init_avma1_cs(void) | 164 | static int __init init_avma1_cs(void) |
240 | { | 165 | { |
241 | return(pcmcia_register_driver(&avma1cs_driver)); | 166 | return pcmcia_register_driver(&avma1cs_driver); |
242 | } | 167 | } |
243 | 168 | ||
244 | static void __exit exit_avma1_cs(void) | 169 | static void __exit exit_avma1_cs(void) |
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 6f9afcd5ca4e..b133378d4dc9 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c | |||
@@ -801,6 +801,16 @@ static void closecard(int cardnr) | |||
801 | ll_unload(csta); | 801 | ll_unload(csta); |
802 | } | 802 | } |
803 | 803 | ||
804 | static irqreturn_t card_irq(int intno, void *dev_id) | ||
805 | { | ||
806 | struct IsdnCardState *cs = dev_id; | ||
807 | irqreturn_t ret = cs->irq_func(intno, cs); | ||
808 | |||
809 | if (ret == IRQ_HANDLED) | ||
810 | cs->irq_cnt++; | ||
811 | return ret; | ||
812 | } | ||
813 | |||
804 | static int init_card(struct IsdnCardState *cs) | 814 | static int init_card(struct IsdnCardState *cs) |
805 | { | 815 | { |
806 | int irq_cnt, cnt = 3, ret; | 816 | int irq_cnt, cnt = 3, ret; |
@@ -809,10 +819,10 @@ static int init_card(struct IsdnCardState *cs) | |||
809 | ret = cs->cardmsg(cs, CARD_INIT, NULL); | 819 | ret = cs->cardmsg(cs, CARD_INIT, NULL); |
810 | return(ret); | 820 | return(ret); |
811 | } | 821 | } |
812 | irq_cnt = kstat_irqs(cs->irq); | 822 | irq_cnt = cs->irq_cnt = 0; |
813 | printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], | 823 | printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], |
814 | cs->irq, irq_cnt); | 824 | cs->irq, irq_cnt); |
815 | if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { | 825 | if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) { |
816 | printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", | 826 | printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", |
817 | cs->irq); | 827 | cs->irq); |
818 | return 1; | 828 | return 1; |
@@ -822,8 +832,8 @@ static int init_card(struct IsdnCardState *cs) | |||
822 | /* Timeout 10ms */ | 832 | /* Timeout 10ms */ |
823 | msleep(10); | 833 | msleep(10); |
824 | printk(KERN_INFO "%s: IRQ %d count %d\n", | 834 | printk(KERN_INFO "%s: IRQ %d count %d\n", |
825 | CardType[cs->typ], cs->irq, kstat_irqs(cs->irq)); | 835 | CardType[cs->typ], cs->irq, cs->irq_cnt); |
826 | if (kstat_irqs(cs->irq) == irq_cnt) { | 836 | if (cs->irq_cnt == irq_cnt) { |
827 | printk(KERN_WARNING | 837 | printk(KERN_WARNING |
828 | "%s: IRQ(%d) getting no interrupts during init %d\n", | 838 | "%s: IRQ(%d) getting no interrupts during init %d\n", |
829 | CardType[cs->typ], cs->irq, 4 - cnt); | 839 | CardType[cs->typ], cs->irq, 4 - cnt); |
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index b3c08aaf41c4..496d477af0f8 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <asm/io.h> | 46 | #include <asm/io.h> |
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | 48 | ||
49 | #include <pcmcia/cs.h> | ||
50 | #include <pcmcia/cistpl.h> | 49 | #include <pcmcia/cistpl.h> |
51 | #include <pcmcia/cisreg.h> | 50 | #include <pcmcia/cisreg.h> |
52 | #include <pcmcia/ds.h> | 51 | #include <pcmcia/ds.h> |
@@ -64,26 +63,8 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
64 | static int protocol = 2; /* EURO-ISDN Default */ | 63 | static int protocol = 2; /* EURO-ISDN Default */ |
65 | module_param(protocol, int, 0); | 64 | module_param(protocol, int, 0); |
66 | 65 | ||
67 | /*====================================================================*/ | ||
68 | |||
69 | /* | ||
70 | The event() function is this driver's Card Services event handler. | ||
71 | It will be called by Card Services when an appropriate card status | ||
72 | event is received. The config() and release() entry points are | ||
73 | used to configure or release a socket, in response to card insertion | ||
74 | and ejection events. They are invoked from the elsa_cs event | ||
75 | handler. | ||
76 | */ | ||
77 | |||
78 | static int elsa_cs_config(struct pcmcia_device *link) __devinit ; | 66 | static int elsa_cs_config(struct pcmcia_device *link) __devinit ; |
79 | static void elsa_cs_release(struct pcmcia_device *link); | 67 | static void elsa_cs_release(struct pcmcia_device *link); |
80 | |||
81 | /* | ||
82 | The attach() and detach() entry points are used to create and destroy | ||
83 | "instances" of the driver, where each instance represents everything | ||
84 | needed to manage one actual PCMCIA card. | ||
85 | */ | ||
86 | |||
87 | static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit; | 68 | static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit; |
88 | 69 | ||
89 | typedef struct local_info_t { | 70 | typedef struct local_info_t { |
@@ -92,18 +73,6 @@ typedef struct local_info_t { | |||
92 | int cardnr; | 73 | int cardnr; |
93 | } local_info_t; | 74 | } local_info_t; |
94 | 75 | ||
95 | /*====================================================================== | ||
96 | |||
97 | elsa_cs_attach() creates an "instance" of the driver, allocatingx | ||
98 | local data structures for one device. The device is registered | ||
99 | with Card Services. | ||
100 | |||
101 | The dev_link structure is initialized, but we don't actually | ||
102 | configure the card at this point -- we wait until we receive a | ||
103 | card insertion event. | ||
104 | |||
105 | ======================================================================*/ | ||
106 | |||
107 | static int __devinit elsa_cs_probe(struct pcmcia_device *link) | 76 | static int __devinit elsa_cs_probe(struct pcmcia_device *link) |
108 | { | 77 | { |
109 | local_info_t *local; | 78 | local_info_t *local; |
@@ -119,31 +88,9 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link) | |||
119 | 88 | ||
120 | local->cardnr = -1; | 89 | local->cardnr = -1; |
121 | 90 | ||
122 | /* | ||
123 | General socket configuration defaults can go here. In this | ||
124 | client, we assume very little, and rely on the CIS for almost | ||
125 | everything. In most clients, many details (i.e., number, sizes, | ||
126 | and attributes of IO windows) are fixed by the nature of the | ||
127 | device, and can be hard-wired here. | ||
128 | */ | ||
129 | link->resource[0]->end = 8; | ||
130 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
131 | |||
132 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
133 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
134 | |||
135 | return elsa_cs_config(link); | 91 | return elsa_cs_config(link); |
136 | } /* elsa_cs_attach */ | 92 | } /* elsa_cs_attach */ |
137 | 93 | ||
138 | /*====================================================================== | ||
139 | |||
140 | This deletes a driver "instance". The device is de-registered | ||
141 | with Card Services. If it has been released, all local data | ||
142 | structures are freed. Otherwise, the structures will be freed | ||
143 | when the device is released. | ||
144 | |||
145 | ======================================================================*/ | ||
146 | |||
147 | static void __devexit elsa_cs_detach(struct pcmcia_device *link) | 94 | static void __devexit elsa_cs_detach(struct pcmcia_device *link) |
148 | { | 95 | { |
149 | local_info_t *info = link->priv; | 96 | local_info_t *info = link->priv; |
@@ -156,27 +103,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link) | |||
156 | kfree(info); | 103 | kfree(info); |
157 | } /* elsa_cs_detach */ | 104 | } /* elsa_cs_detach */ |
158 | 105 | ||
159 | /*====================================================================== | 106 | static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
160 | |||
161 | elsa_cs_config() is scheduled to run after a CARD_INSERTION event | ||
162 | is received, to configure the PCMCIA socket, and to make the | ||
163 | device available to the system. | ||
164 | |||
165 | ======================================================================*/ | ||
166 | |||
167 | static int elsa_cs_configcheck(struct pcmcia_device *p_dev, | ||
168 | cistpl_cftable_entry_t *cf, | ||
169 | cistpl_cftable_entry_t *dflt, | ||
170 | unsigned int vcc, | ||
171 | void *priv_data) | ||
172 | { | 107 | { |
173 | int j; | 108 | int j; |
174 | 109 | ||
175 | p_dev->io_lines = 3; | 110 | p_dev->io_lines = 3; |
111 | p_dev->resource[0]->end = 8; | ||
112 | p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH; | ||
113 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
176 | 114 | ||
177 | if ((cf->io.nwin > 0) && cf->io.win[0].base) { | 115 | if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) { |
178 | printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); | 116 | printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); |
179 | p_dev->resource[0]->start = cf->io.win[0].base; | ||
180 | if (!pcmcia_request_io(p_dev)) | 117 | if (!pcmcia_request_io(p_dev)) |
181 | return 0; | 118 | return 0; |
182 | } else { | 119 | } else { |
@@ -199,6 +136,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link) | |||
199 | dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); | 136 | dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); |
200 | dev = link->priv; | 137 | dev = link->priv; |
201 | 138 | ||
139 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
140 | |||
202 | i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); | 141 | i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); |
203 | if (i != 0) | 142 | if (i != 0) |
204 | goto failed; | 143 | goto failed; |
@@ -206,21 +145,10 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link) | |||
206 | if (!link->irq) | 145 | if (!link->irq) |
207 | goto failed; | 146 | goto failed; |
208 | 147 | ||
209 | i = pcmcia_request_configuration(link, &link->conf); | 148 | i = pcmcia_enable_device(link); |
210 | if (i != 0) | 149 | if (i != 0) |
211 | goto failed; | 150 | goto failed; |
212 | 151 | ||
213 | /* Finally, report what we've done */ | ||
214 | dev_info(&link->dev, "index 0x%02x: ", | ||
215 | link->conf.ConfigIndex); | ||
216 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
217 | printk(", irq %d", link->irq); | ||
218 | if (link->resource[0]) | ||
219 | printk(" & %pR", link->resource[0]); | ||
220 | if (link->resource[1]) | ||
221 | printk(" & %pR", link->resource[1]); | ||
222 | printk("\n"); | ||
223 | |||
224 | icard.para[0] = link->irq; | 152 | icard.para[0] = link->irq; |
225 | icard.para[1] = link->resource[0]->start; | 153 | icard.para[1] = link->resource[0]->start; |
226 | icard.protocol = protocol; | 154 | icard.protocol = protocol; |
@@ -240,14 +168,6 @@ failed: | |||
240 | return -ENODEV; | 168 | return -ENODEV; |
241 | } /* elsa_cs_config */ | 169 | } /* elsa_cs_config */ |
242 | 170 | ||
243 | /*====================================================================== | ||
244 | |||
245 | After a card is removed, elsa_cs_release() will unregister the net | ||
246 | device, and release the PCMCIA configuration. If the device is | ||
247 | still open, this will be postponed until it is closed. | ||
248 | |||
249 | ======================================================================*/ | ||
250 | |||
251 | static void elsa_cs_release(struct pcmcia_device *link) | 171 | static void elsa_cs_release(struct pcmcia_device *link) |
252 | { | 172 | { |
253 | local_info_t *local = link->priv; | 173 | local_info_t *local = link->priv; |
@@ -291,9 +211,7 @@ MODULE_DEVICE_TABLE(pcmcia, elsa_ids); | |||
291 | 211 | ||
292 | static struct pcmcia_driver elsa_cs_driver = { | 212 | static struct pcmcia_driver elsa_cs_driver = { |
293 | .owner = THIS_MODULE, | 213 | .owner = THIS_MODULE, |
294 | .drv = { | 214 | .name = "elsa_cs", |
295 | .name = "elsa_cs", | ||
296 | }, | ||
297 | .probe = elsa_cs_probe, | 215 | .probe = elsa_cs_probe, |
298 | .remove = __devexit_p(elsa_cs_detach), | 216 | .remove = __devexit_p(elsa_cs_detach), |
299 | .id_table = elsa_ids, | 217 | .id_table = elsa_ids, |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 832a87855ffb..32ab3924aa73 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -959,6 +959,7 @@ struct IsdnCardState { | |||
959 | u_long event; | 959 | u_long event; |
960 | struct work_struct tqueue; | 960 | struct work_struct tqueue; |
961 | struct timer_list dbusytimer; | 961 | struct timer_list dbusytimer; |
962 | unsigned int irq_cnt; | ||
962 | #ifdef ERROR_STATISTIC | 963 | #ifdef ERROR_STATISTIC |
963 | int err_crc; | 964 | int err_crc; |
964 | int err_tx; | 965 | int err_tx; |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index a024192b672a..360204bc2777 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <asm/io.h> | 46 | #include <asm/io.h> |
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | 48 | ||
49 | #include <pcmcia/cs.h> | ||
50 | #include <pcmcia/cistpl.h> | 49 | #include <pcmcia/cistpl.h> |
51 | #include <pcmcia/cisreg.h> | 50 | #include <pcmcia/cisreg.h> |
52 | #include <pcmcia/ds.h> | 51 | #include <pcmcia/ds.h> |
@@ -64,26 +63,9 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
64 | static int protocol = 2; /* EURO-ISDN Default */ | 63 | static int protocol = 2; /* EURO-ISDN Default */ |
65 | module_param(protocol, int, 0); | 64 | module_param(protocol, int, 0); |
66 | 65 | ||
67 | /*====================================================================*/ | ||
68 | |||
69 | /* | ||
70 | The event() function is this driver's Card Services event handler. | ||
71 | It will be called by Card Services when an appropriate card status | ||
72 | event is received. The config() and release() entry points are | ||
73 | used to configure or release a socket, in response to card | ||
74 | insertion and ejection events. They are invoked from the sedlbauer | ||
75 | event handler. | ||
76 | */ | ||
77 | |||
78 | static int sedlbauer_config(struct pcmcia_device *link) __devinit ; | 66 | static int sedlbauer_config(struct pcmcia_device *link) __devinit ; |
79 | static void sedlbauer_release(struct pcmcia_device *link); | 67 | static void sedlbauer_release(struct pcmcia_device *link); |
80 | 68 | ||
81 | /* | ||
82 | The attach() and detach() entry points are used to create and destroy | ||
83 | "instances" of the driver, where each instance represents everything | ||
84 | needed to manage one actual PCMCIA card. | ||
85 | */ | ||
86 | |||
87 | static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit; | 69 | static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit; |
88 | 70 | ||
89 | typedef struct local_info_t { | 71 | typedef struct local_info_t { |
@@ -92,18 +74,6 @@ typedef struct local_info_t { | |||
92 | int cardnr; | 74 | int cardnr; |
93 | } local_info_t; | 75 | } local_info_t; |
94 | 76 | ||
95 | /*====================================================================== | ||
96 | |||
97 | sedlbauer_attach() creates an "instance" of the driver, allocating | ||
98 | local data structures for one device. The device is registered | ||
99 | with Card Services. | ||
100 | |||
101 | The dev_link structure is initialized, but we don't actually | ||
102 | configure the card at this point -- we wait until we receive a | ||
103 | card insertion event. | ||
104 | |||
105 | ======================================================================*/ | ||
106 | |||
107 | static int __devinit sedlbauer_probe(struct pcmcia_device *link) | 77 | static int __devinit sedlbauer_probe(struct pcmcia_device *link) |
108 | { | 78 | { |
109 | local_info_t *local; | 79 | local_info_t *local; |
@@ -118,35 +88,9 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link) | |||
118 | local->p_dev = link; | 88 | local->p_dev = link; |
119 | link->priv = local; | 89 | link->priv = local; |
120 | 90 | ||
121 | /* | ||
122 | General socket configuration defaults can go here. In this | ||
123 | client, we assume very little, and rely on the CIS for almost | ||
124 | everything. In most clients, many details (i.e., number, sizes, | ||
125 | and attributes of IO windows) are fixed by the nature of the | ||
126 | device, and can be hard-wired here. | ||
127 | */ | ||
128 | |||
129 | /* from old sedl_cs | ||
130 | */ | ||
131 | /* The io structure describes IO port mapping */ | ||
132 | link->resource[0]->end = 8; | ||
133 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
134 | |||
135 | link->conf.Attributes = 0; | ||
136 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
137 | |||
138 | return sedlbauer_config(link); | 91 | return sedlbauer_config(link); |
139 | } /* sedlbauer_attach */ | 92 | } /* sedlbauer_attach */ |
140 | 93 | ||
141 | /*====================================================================== | ||
142 | |||
143 | This deletes a driver "instance". The device is de-registered | ||
144 | with Card Services. If it has been released, all local data | ||
145 | structures are freed. Otherwise, the structures will be freed | ||
146 | when the device is released. | ||
147 | |||
148 | ======================================================================*/ | ||
149 | |||
150 | static void __devexit sedlbauer_detach(struct pcmcia_device *link) | 94 | static void __devexit sedlbauer_detach(struct pcmcia_device *link) |
151 | { | 95 | { |
152 | dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); | 96 | dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); |
@@ -158,70 +102,15 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link) | |||
158 | kfree(link->priv); | 102 | kfree(link->priv); |
159 | } /* sedlbauer_detach */ | 103 | } /* sedlbauer_detach */ |
160 | 104 | ||
161 | /*====================================================================== | 105 | static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data) |
162 | |||
163 | sedlbauer_config() is scheduled to run after a CARD_INSERTION event | ||
164 | is received, to configure the PCMCIA socket, and to make the | ||
165 | device available to the system. | ||
166 | |||
167 | ======================================================================*/ | ||
168 | static int sedlbauer_config_check(struct pcmcia_device *p_dev, | ||
169 | cistpl_cftable_entry_t *cfg, | ||
170 | cistpl_cftable_entry_t *dflt, | ||
171 | unsigned int vcc, | ||
172 | void *priv_data) | ||
173 | { | 106 | { |
174 | if (cfg->index == 0) | 107 | if (p_dev->config_index == 0) |
175 | return -ENODEV; | 108 | return -EINVAL; |
176 | |||
177 | /* Does this card need audio output? */ | ||
178 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
179 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
180 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
181 | } | ||
182 | 109 | ||
183 | /* Use power settings for Vcc and Vpp if present */ | 110 | p_dev->io_lines = 3; |
184 | /* Note that the CIS values need to be rescaled */ | 111 | return pcmcia_request_io(p_dev); |
185 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
186 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) | ||
187 | return -ENODEV; | ||
188 | } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
189 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000) | ||
190 | return -ENODEV; | ||
191 | } | ||
192 | |||
193 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
194 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
195 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
196 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
197 | |||
198 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
199 | |||
200 | /* IO window settings */ | ||
201 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
202 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
203 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
204 | p_dev->resource[0]->start = io->win[0].base; | ||
205 | p_dev->resource[0]->end = io->win[0].len; | ||
206 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
207 | p_dev->resource[0]->flags |= | ||
208 | pcmcia_io_cfg_data_width(io->flags); | ||
209 | if (io->nwin > 1) { | ||
210 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
211 | p_dev->resource[1]->start = io->win[1].base; | ||
212 | p_dev->resource[1]->end = io->win[1].len; | ||
213 | } | ||
214 | /* This reserves IO space but doesn't actually enable it */ | ||
215 | p_dev->io_lines = 3; | ||
216 | if (pcmcia_request_io(p_dev) != 0) | ||
217 | return -ENODEV; | ||
218 | } | ||
219 | |||
220 | return 0; | ||
221 | } | 112 | } |
222 | 113 | ||
223 | |||
224 | |||
225 | static int __devinit sedlbauer_config(struct pcmcia_device *link) | 114 | static int __devinit sedlbauer_config(struct pcmcia_device *link) |
226 | { | 115 | { |
227 | int ret; | 116 | int ret; |
@@ -229,44 +118,17 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link) | |||
229 | 118 | ||
230 | dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link); | 119 | dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link); |
231 | 120 | ||
232 | /* | 121 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC | |
233 | In this loop, we scan the CIS for configuration table entries, | 122 | CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; |
234 | each of which describes a valid card configuration, including | 123 | |
235 | voltage, IO window, memory window, and interrupt settings. | ||
236 | |||
237 | We make no assumptions about the card to be configured: we use | ||
238 | just the information available in the CIS. In an ideal world, | ||
239 | this would work for any PCMCIA card, but it requires a complete | ||
240 | and accurate CIS. In practice, a driver usually "knows" most of | ||
241 | these things without consulting the CIS, and most client drivers | ||
242 | will only use the CIS to fill in implementation-defined details. | ||
243 | */ | ||
244 | ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL); | 124 | ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL); |
245 | if (ret) | 125 | if (ret) |
246 | goto failed; | 126 | goto failed; |
247 | 127 | ||
248 | /* | 128 | ret = pcmcia_enable_device(link); |
249 | This actually configures the PCMCIA socket -- setting up | ||
250 | the I/O windows and the interrupt mapping, and putting the | ||
251 | card and host interface into "Memory and IO" mode. | ||
252 | */ | ||
253 | ret = pcmcia_request_configuration(link, &link->conf); | ||
254 | if (ret) | 129 | if (ret) |
255 | goto failed; | 130 | goto failed; |
256 | 131 | ||
257 | /* Finally, report what we've done */ | ||
258 | dev_info(&link->dev, "index 0x%02x:", | ||
259 | link->conf.ConfigIndex); | ||
260 | if (link->conf.Vpp) | ||
261 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); | ||
262 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
263 | printk(", irq %d", link->irq); | ||
264 | if (link->resource[0]) | ||
265 | printk(" & %pR", link->resource[0]); | ||
266 | if (link->resource[1]) | ||
267 | printk(" & %pR", link->resource[1]); | ||
268 | printk("\n"); | ||
269 | |||
270 | icard.para[0] = link->irq; | 132 | icard.para[0] = link->irq; |
271 | icard.para[1] = link->resource[0]->start; | 133 | icard.para[1] = link->resource[0]->start; |
272 | icard.protocol = protocol; | 134 | icard.protocol = protocol; |
@@ -290,14 +152,6 @@ failed: | |||
290 | 152 | ||
291 | } /* sedlbauer_config */ | 153 | } /* sedlbauer_config */ |
292 | 154 | ||
293 | /*====================================================================== | ||
294 | |||
295 | After a card is removed, sedlbauer_release() will unregister the | ||
296 | device, and release the PCMCIA configuration. If the device is | ||
297 | still open, this will be postponed until it is closed. | ||
298 | |||
299 | ======================================================================*/ | ||
300 | |||
301 | static void sedlbauer_release(struct pcmcia_device *link) | 155 | static void sedlbauer_release(struct pcmcia_device *link) |
302 | { | 156 | { |
303 | local_info_t *local = link->priv; | 157 | local_info_t *local = link->priv; |
@@ -346,9 +200,7 @@ MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids); | |||
346 | 200 | ||
347 | static struct pcmcia_driver sedlbauer_driver = { | 201 | static struct pcmcia_driver sedlbauer_driver = { |
348 | .owner = THIS_MODULE, | 202 | .owner = THIS_MODULE, |
349 | .drv = { | 203 | .name = "sedlbauer_cs", |
350 | .name = "sedlbauer_cs", | ||
351 | }, | ||
352 | .probe = sedlbauer_probe, | 204 | .probe = sedlbauer_probe, |
353 | .remove = __devexit_p(sedlbauer_detach), | 205 | .remove = __devexit_p(sedlbauer_detach), |
354 | .id_table = sedlbauer_ids, | 206 | .id_table = sedlbauer_ids, |
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 7296102ca255..282a4467ef19 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/system.h> | 28 | #include <asm/system.h> |
29 | 29 | ||
30 | #include <pcmcia/cs.h> | ||
31 | #include <pcmcia/cistpl.h> | 30 | #include <pcmcia/cistpl.h> |
32 | #include <pcmcia/cisreg.h> | 31 | #include <pcmcia/cisreg.h> |
33 | #include <pcmcia/ds.h> | 32 | #include <pcmcia/ds.h> |
@@ -45,26 +44,8 @@ MODULE_LICENSE("GPL"); | |||
45 | static int protocol = 2; /* EURO-ISDN Default */ | 44 | static int protocol = 2; /* EURO-ISDN Default */ |
46 | module_param(protocol, int, 0); | 45 | module_param(protocol, int, 0); |
47 | 46 | ||
48 | /*====================================================================*/ | ||
49 | |||
50 | /* | ||
51 | The event() function is this driver's Card Services event handler. | ||
52 | It will be called by Card Services when an appropriate card status | ||
53 | event is received. The config() and release() entry points are | ||
54 | used to configure or release a socket, in response to card insertion | ||
55 | and ejection events. They are invoked from the teles_cs event | ||
56 | handler. | ||
57 | */ | ||
58 | |||
59 | static int teles_cs_config(struct pcmcia_device *link) __devinit ; | 47 | static int teles_cs_config(struct pcmcia_device *link) __devinit ; |
60 | static void teles_cs_release(struct pcmcia_device *link); | 48 | static void teles_cs_release(struct pcmcia_device *link); |
61 | |||
62 | /* | ||
63 | The attach() and detach() entry points are used to create and destroy | ||
64 | "instances" of the driver, where each instance represents everything | ||
65 | needed to manage one actual PCMCIA card. | ||
66 | */ | ||
67 | |||
68 | static void teles_detach(struct pcmcia_device *p_dev) __devexit ; | 49 | static void teles_detach(struct pcmcia_device *p_dev) __devexit ; |
69 | 50 | ||
70 | typedef struct local_info_t { | 51 | typedef struct local_info_t { |
@@ -73,18 +54,6 @@ typedef struct local_info_t { | |||
73 | int cardnr; | 54 | int cardnr; |
74 | } local_info_t; | 55 | } local_info_t; |
75 | 56 | ||
76 | /*====================================================================== | ||
77 | |||
78 | teles_attach() creates an "instance" of the driver, allocatingx | ||
79 | local data structures for one device. The device is registered | ||
80 | with Card Services. | ||
81 | |||
82 | The dev_link structure is initialized, but we don't actually | ||
83 | configure the card at this point -- we wait until we receive a | ||
84 | card insertion event. | ||
85 | |||
86 | ======================================================================*/ | ||
87 | |||
88 | static int __devinit teles_probe(struct pcmcia_device *link) | 57 | static int __devinit teles_probe(struct pcmcia_device *link) |
89 | { | 58 | { |
90 | local_info_t *local; | 59 | local_info_t *local; |
@@ -99,31 +68,11 @@ static int __devinit teles_probe(struct pcmcia_device *link) | |||
99 | local->p_dev = link; | 68 | local->p_dev = link; |
100 | link->priv = local; | 69 | link->priv = local; |
101 | 70 | ||
102 | /* | 71 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
103 | General socket configuration defaults can go here. In this | ||
104 | client, we assume very little, and rely on the CIS for almost | ||
105 | everything. In most clients, many details (i.e., number, sizes, | ||
106 | and attributes of IO windows) are fixed by the nature of the | ||
107 | device, and can be hard-wired here. | ||
108 | */ | ||
109 | link->resource[0]->end = 96; | ||
110 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
111 | |||
112 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
113 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
114 | 72 | ||
115 | return teles_cs_config(link); | 73 | return teles_cs_config(link); |
116 | } /* teles_attach */ | 74 | } /* teles_attach */ |
117 | 75 | ||
118 | /*====================================================================== | ||
119 | |||
120 | This deletes a driver "instance". The device is de-registered | ||
121 | with Card Services. If it has been released, all local data | ||
122 | structures are freed. Otherwise, the structures will be freed | ||
123 | when the device is released. | ||
124 | |||
125 | ======================================================================*/ | ||
126 | |||
127 | static void __devexit teles_detach(struct pcmcia_device *link) | 76 | static void __devexit teles_detach(struct pcmcia_device *link) |
128 | { | 77 | { |
129 | local_info_t *info = link->priv; | 78 | local_info_t *info = link->priv; |
@@ -136,27 +85,17 @@ static void __devexit teles_detach(struct pcmcia_device *link) | |||
136 | kfree(info); | 85 | kfree(info); |
137 | } /* teles_detach */ | 86 | } /* teles_detach */ |
138 | 87 | ||
139 | /*====================================================================== | 88 | static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
140 | |||
141 | teles_cs_config() is scheduled to run after a CARD_INSERTION event | ||
142 | is received, to configure the PCMCIA socket, and to make the | ||
143 | device available to the system. | ||
144 | |||
145 | ======================================================================*/ | ||
146 | |||
147 | static int teles_cs_configcheck(struct pcmcia_device *p_dev, | ||
148 | cistpl_cftable_entry_t *cf, | ||
149 | cistpl_cftable_entry_t *dflt, | ||
150 | unsigned int vcc, | ||
151 | void *priv_data) | ||
152 | { | 89 | { |
153 | int j; | 90 | int j; |
154 | 91 | ||
155 | p_dev->io_lines = 5; | 92 | p_dev->io_lines = 5; |
93 | p_dev->resource[0]->end = 96; | ||
94 | p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH; | ||
95 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
156 | 96 | ||
157 | if ((cf->io.nwin > 0) && cf->io.win[0].base) { | 97 | if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) { |
158 | printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); | 98 | printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); |
159 | p_dev->resource[0]->start = cf->io.win[0].base; | ||
160 | if (!pcmcia_request_io(p_dev)) | 99 | if (!pcmcia_request_io(p_dev)) |
161 | return 0; | 100 | return 0; |
162 | } else { | 101 | } else { |
@@ -186,21 +125,10 @@ static int __devinit teles_cs_config(struct pcmcia_device *link) | |||
186 | if (!link->irq) | 125 | if (!link->irq) |
187 | goto cs_failed; | 126 | goto cs_failed; |
188 | 127 | ||
189 | i = pcmcia_request_configuration(link, &link->conf); | 128 | i = pcmcia_enable_device(link); |
190 | if (i != 0) | 129 | if (i != 0) |
191 | goto cs_failed; | 130 | goto cs_failed; |
192 | 131 | ||
193 | /* Finally, report what we've done */ | ||
194 | dev_info(&link->dev, "index 0x%02x:", | ||
195 | link->conf.ConfigIndex); | ||
196 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
197 | printk(", irq %d", link->irq); | ||
198 | if (link->resource[0]) | ||
199 | printk(" & %pR", link->resource[0]); | ||
200 | if (link->resource[1]) | ||
201 | printk(" & %pR", link->resource[1]); | ||
202 | printk("\n"); | ||
203 | |||
204 | icard.para[0] = link->irq; | 132 | icard.para[0] = link->irq; |
205 | icard.para[1] = link->resource[0]->start; | 133 | icard.para[1] = link->resource[0]->start; |
206 | icard.protocol = protocol; | 134 | icard.protocol = protocol; |
@@ -222,14 +150,6 @@ cs_failed: | |||
222 | return -ENODEV; | 150 | return -ENODEV; |
223 | } /* teles_cs_config */ | 151 | } /* teles_cs_config */ |
224 | 152 | ||
225 | /*====================================================================== | ||
226 | |||
227 | After a card is removed, teles_cs_release() will unregister the net | ||
228 | device, and release the PCMCIA configuration. If the device is | ||
229 | still open, this will be postponed until it is closed. | ||
230 | |||
231 | ======================================================================*/ | ||
232 | |||
233 | static void teles_cs_release(struct pcmcia_device *link) | 153 | static void teles_cs_release(struct pcmcia_device *link) |
234 | { | 154 | { |
235 | local_info_t *local = link->priv; | 155 | local_info_t *local = link->priv; |
@@ -273,9 +193,7 @@ MODULE_DEVICE_TABLE(pcmcia, teles_ids); | |||
273 | 193 | ||
274 | static struct pcmcia_driver teles_cs_driver = { | 194 | static struct pcmcia_driver teles_cs_driver = { |
275 | .owner = THIS_MODULE, | 195 | .owner = THIS_MODULE, |
276 | .drv = { | 196 | .name = "teles_cs", |
277 | .name = "teles_cs", | ||
278 | }, | ||
279 | .probe = teles_probe, | 197 | .probe = teles_probe, |
280 | .remove = __devexit_p(teles_detach), | 198 | .remove = __devexit_p(teles_detach), |
281 | .id_table = teles_ids, | 199 | .id_table = teles_ids, |
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c index 485be8b1e1b3..f0225bc0f267 100644 --- a/drivers/isdn/sc/interrupt.c +++ b/drivers/isdn/sc/interrupt.c | |||
@@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) | |||
112 | } | 112 | } |
113 | else if(callid>=0x0000 && callid<=0x7FFF) | 113 | else if(callid>=0x0000 && callid<=0x7FFF) |
114 | { | 114 | { |
115 | int len; | ||
116 | |||
115 | pr_debug("%s: Got Incoming Call\n", | 117 | pr_debug("%s: Got Incoming Call\n", |
116 | sc_adapter[card]->devicename); | 118 | sc_adapter[card]->devicename); |
117 | strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); | 119 | len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]), |
118 | strcpy(setup.eazmsn, | 120 | sizeof(setup.phone)); |
119 | sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn); | 121 | if (len >= sizeof(setup.phone)) |
122 | continue; | ||
123 | len = strlcpy(setup.eazmsn, | ||
124 | sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, | ||
125 | sizeof(setup.eazmsn)); | ||
126 | if (len >= sizeof(setup.eazmsn)) | ||
127 | continue; | ||
120 | setup.si1 = 7; | 128 | setup.si1 = 7; |
121 | setup.si2 = 0; | 129 | setup.si2 = 0; |
122 | setup.plan = 0; | 130 | setup.plan = 0; |
@@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) | |||
176 | * Handle a GetMyNumber Rsp | 184 | * Handle a GetMyNumber Rsp |
177 | */ | 185 | */ |
178 | if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ | 186 | if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ |
179 | strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); | 187 | strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, |
188 | rcvmsg.msg_data.byte_array, | ||
189 | sizeof(rcvmsg.msg_data.byte_array)); | ||
180 | continue; | 190 | continue; |
181 | } | 191 | } |
182 | 192 | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index e4112622e5a2..cc2a88d5192f 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -304,13 +304,22 @@ config LEDS_MC13783 | |||
304 | 304 | ||
305 | config LEDS_NS2 | 305 | config LEDS_NS2 |
306 | tristate "LED support for Network Space v2 GPIO LEDs" | 306 | tristate "LED support for Network Space v2 GPIO LEDs" |
307 | depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 | 307 | depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2 |
308 | default y | 308 | default y |
309 | help | 309 | help |
310 | This option enable support for the dual-GPIO LED found on the | 310 | This option enable support for the dual-GPIO LED found on the |
311 | Network Space v2 board (and parents). This include Internet Space v2, | 311 | Network Space v2 board (and parents). This include Internet Space v2, |
312 | Network Space (Max) v2 and d2 Network v2 boards. | 312 | Network Space (Max) v2 and d2 Network v2 boards. |
313 | 313 | ||
314 | config LEDS_NETXBIG | ||
315 | tristate "LED support for Big Network series LEDs" | ||
316 | depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2 | ||
317 | default y | ||
318 | help | ||
319 | This option enable support for LEDs found on the LaCie 2Big | ||
320 | and 5Big Network v2 boards. The LEDs are wired to a CPLD and are | ||
321 | controlled through a GPIO extension bus. | ||
322 | |||
314 | config LEDS_TRIGGERS | 323 | config LEDS_TRIGGERS |
315 | bool "LED Trigger support" | 324 | bool "LED Trigger support" |
316 | help | 325 | help |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 7d6b95831f8e..9c96db40ef6d 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o | |||
38 | obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o | 38 | obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o |
39 | obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o | 39 | obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o |
40 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o | 40 | obj-$(CONFIG_LEDS_NS2) += leds-ns2.o |
41 | obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o | ||
41 | 42 | ||
42 | # LED SPI Drivers | 43 | # LED SPI Drivers |
43 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o | 44 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o |
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c new file mode 100644 index 000000000000..f2e51c134399 --- /dev/null +++ b/drivers/leds/leds-netxbig.c | |||
@@ -0,0 +1,449 @@ | |||
1 | /* | ||
2 | * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs | ||
3 | * | ||
4 | * Copyright (C) 2010 LaCie | ||
5 | * | ||
6 | * Author: Simon Guinot <sguinot@lacie.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/leds.h> | ||
31 | #include <mach/leds-netxbig.h> | ||
32 | |||
33 | /* | ||
34 | * GPIO extension bus. | ||
35 | */ | ||
36 | |||
37 | static DEFINE_SPINLOCK(gpio_ext_lock); | ||
38 | |||
39 | static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr) | ||
40 | { | ||
41 | int pin; | ||
42 | |||
43 | for (pin = 0; pin < gpio_ext->num_addr; pin++) | ||
44 | gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1); | ||
45 | } | ||
46 | |||
47 | static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data) | ||
48 | { | ||
49 | int pin; | ||
50 | |||
51 | for (pin = 0; pin < gpio_ext->num_data; pin++) | ||
52 | gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1); | ||
53 | } | ||
54 | |||
55 | static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext) | ||
56 | { | ||
57 | /* Enable select is done on the raising edge. */ | ||
58 | gpio_set_value(gpio_ext->enable, 0); | ||
59 | gpio_set_value(gpio_ext->enable, 1); | ||
60 | } | ||
61 | |||
62 | static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, | ||
63 | int addr, int value) | ||
64 | { | ||
65 | unsigned long flags; | ||
66 | |||
67 | spin_lock_irqsave(&gpio_ext_lock, flags); | ||
68 | gpio_ext_set_addr(gpio_ext, addr); | ||
69 | gpio_ext_set_data(gpio_ext, value); | ||
70 | gpio_ext_enable_select(gpio_ext); | ||
71 | spin_unlock_irqrestore(&gpio_ext_lock, flags); | ||
72 | } | ||
73 | |||
74 | static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) | ||
75 | { | ||
76 | int err; | ||
77 | int i; | ||
78 | |||
79 | if (unlikely(!gpio_ext)) | ||
80 | return -EINVAL; | ||
81 | |||
82 | /* Configure address GPIOs. */ | ||
83 | for (i = 0; i < gpio_ext->num_addr; i++) { | ||
84 | err = gpio_request(gpio_ext->addr[i], "GPIO extension addr"); | ||
85 | if (err) | ||
86 | goto err_free_addr; | ||
87 | err = gpio_direction_output(gpio_ext->addr[i], 0); | ||
88 | if (err) { | ||
89 | gpio_free(gpio_ext->addr[i]); | ||
90 | goto err_free_addr; | ||
91 | } | ||
92 | } | ||
93 | /* Configure data GPIOs. */ | ||
94 | for (i = 0; i < gpio_ext->num_data; i++) { | ||
95 | err = gpio_request(gpio_ext->data[i], "GPIO extension data"); | ||
96 | if (err) | ||
97 | goto err_free_data; | ||
98 | err = gpio_direction_output(gpio_ext->data[i], 0); | ||
99 | if (err) { | ||
100 | gpio_free(gpio_ext->data[i]); | ||
101 | goto err_free_data; | ||
102 | } | ||
103 | } | ||
104 | /* Configure "enable select" GPIO. */ | ||
105 | err = gpio_request(gpio_ext->enable, "GPIO extension enable"); | ||
106 | if (err) | ||
107 | goto err_free_data; | ||
108 | err = gpio_direction_output(gpio_ext->enable, 0); | ||
109 | if (err) { | ||
110 | gpio_free(gpio_ext->enable); | ||
111 | goto err_free_data; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | |||
116 | err_free_data: | ||
117 | for (i = i - 1; i >= 0; i--) | ||
118 | gpio_free(gpio_ext->data[i]); | ||
119 | i = gpio_ext->num_addr; | ||
120 | err_free_addr: | ||
121 | for (i = i - 1; i >= 0; i--) | ||
122 | gpio_free(gpio_ext->addr[i]); | ||
123 | |||
124 | return err; | ||
125 | } | ||
126 | |||
127 | static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) | ||
128 | { | ||
129 | int i; | ||
130 | |||
131 | gpio_free(gpio_ext->enable); | ||
132 | for (i = gpio_ext->num_addr - 1; i >= 0; i--) | ||
133 | gpio_free(gpio_ext->addr[i]); | ||
134 | for (i = gpio_ext->num_data - 1; i >= 0; i--) | ||
135 | gpio_free(gpio_ext->data[i]); | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Class LED driver. | ||
140 | */ | ||
141 | |||
142 | struct netxbig_led_data { | ||
143 | struct netxbig_gpio_ext *gpio_ext; | ||
144 | struct led_classdev cdev; | ||
145 | int mode_addr; | ||
146 | int *mode_val; | ||
147 | int bright_addr; | ||
148 | int bright_max; | ||
149 | struct netxbig_led_timer *timer; | ||
150 | int num_timer; | ||
151 | enum netxbig_led_mode mode; | ||
152 | int sata; | ||
153 | spinlock_t lock; | ||
154 | }; | ||
155 | |||
156 | static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, | ||
157 | unsigned long delay_on, | ||
158 | unsigned long delay_off, | ||
159 | struct netxbig_led_timer *timer, | ||
160 | int num_timer) | ||
161 | { | ||
162 | int i; | ||
163 | |||
164 | for (i = 0; i < num_timer; i++) { | ||
165 | if (timer[i].delay_on == delay_on && | ||
166 | timer[i].delay_off == delay_off) { | ||
167 | *mode = timer[i].mode; | ||
168 | return 0; | ||
169 | } | ||
170 | } | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | static int netxbig_led_blink_set(struct led_classdev *led_cdev, | ||
175 | unsigned long *delay_on, | ||
176 | unsigned long *delay_off) | ||
177 | { | ||
178 | struct netxbig_led_data *led_dat = | ||
179 | container_of(led_cdev, struct netxbig_led_data, cdev); | ||
180 | enum netxbig_led_mode mode; | ||
181 | int mode_val; | ||
182 | int ret; | ||
183 | |||
184 | /* Look for a LED mode with the requested timer frequency. */ | ||
185 | ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off, | ||
186 | led_dat->timer, led_dat->num_timer); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | mode_val = led_dat->mode_val[mode]; | ||
191 | if (mode_val == NETXBIG_LED_INVALID_MODE) | ||
192 | return -EINVAL; | ||
193 | |||
194 | spin_lock_irq(&led_dat->lock); | ||
195 | |||
196 | gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); | ||
197 | led_dat->mode = mode; | ||
198 | |||
199 | spin_unlock_irq(&led_dat->lock); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void netxbig_led_set(struct led_classdev *led_cdev, | ||
205 | enum led_brightness value) | ||
206 | { | ||
207 | struct netxbig_led_data *led_dat = | ||
208 | container_of(led_cdev, struct netxbig_led_data, cdev); | ||
209 | enum netxbig_led_mode mode; | ||
210 | int mode_val, bright_val; | ||
211 | int set_brightness = 1; | ||
212 | unsigned long flags; | ||
213 | |||
214 | spin_lock_irqsave(&led_dat->lock, flags); | ||
215 | |||
216 | if (value == LED_OFF) { | ||
217 | mode = NETXBIG_LED_OFF; | ||
218 | set_brightness = 0; | ||
219 | } else { | ||
220 | if (led_dat->sata) | ||
221 | mode = NETXBIG_LED_SATA; | ||
222 | else if (led_dat->mode == NETXBIG_LED_OFF) | ||
223 | mode = NETXBIG_LED_ON; | ||
224 | else /* Keep 'timer' mode. */ | ||
225 | mode = led_dat->mode; | ||
226 | } | ||
227 | mode_val = led_dat->mode_val[mode]; | ||
228 | |||
229 | gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); | ||
230 | led_dat->mode = mode; | ||
231 | /* | ||
232 | * Note that the brightness register is shared between all the | ||
233 | * SATA LEDs. So, change the brightness setting for a single | ||
234 | * SATA LED will affect all the others. | ||
235 | */ | ||
236 | if (set_brightness) { | ||
237 | bright_val = DIV_ROUND_UP(value * led_dat->bright_max, | ||
238 | LED_FULL); | ||
239 | gpio_ext_set_value(led_dat->gpio_ext, | ||
240 | led_dat->bright_addr, bright_val); | ||
241 | } | ||
242 | |||
243 | spin_unlock_irqrestore(&led_dat->lock, flags); | ||
244 | } | ||
245 | |||
246 | static ssize_t netxbig_led_sata_store(struct device *dev, | ||
247 | struct device_attribute *attr, | ||
248 | const char *buff, size_t count) | ||
249 | { | ||
250 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
251 | struct netxbig_led_data *led_dat = | ||
252 | container_of(led_cdev, struct netxbig_led_data, cdev); | ||
253 | unsigned long enable; | ||
254 | enum netxbig_led_mode mode; | ||
255 | int mode_val; | ||
256 | int ret; | ||
257 | |||
258 | ret = strict_strtoul(buff, 10, &enable); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | |||
262 | enable = !!enable; | ||
263 | |||
264 | spin_lock_irq(&led_dat->lock); | ||
265 | |||
266 | if (led_dat->sata == enable) { | ||
267 | ret = count; | ||
268 | goto exit_unlock; | ||
269 | } | ||
270 | |||
271 | if (led_dat->mode != NETXBIG_LED_ON && | ||
272 | led_dat->mode != NETXBIG_LED_SATA) | ||
273 | mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */ | ||
274 | else if (enable) | ||
275 | mode = NETXBIG_LED_SATA; | ||
276 | else | ||
277 | mode = NETXBIG_LED_ON; | ||
278 | |||
279 | mode_val = led_dat->mode_val[mode]; | ||
280 | if (mode_val == NETXBIG_LED_INVALID_MODE) { | ||
281 | ret = -EINVAL; | ||
282 | goto exit_unlock; | ||
283 | } | ||
284 | |||
285 | gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); | ||
286 | led_dat->mode = mode; | ||
287 | led_dat->sata = enable; | ||
288 | |||
289 | ret = count; | ||
290 | |||
291 | exit_unlock: | ||
292 | spin_unlock_irq(&led_dat->lock); | ||
293 | |||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static ssize_t netxbig_led_sata_show(struct device *dev, | ||
298 | struct device_attribute *attr, char *buf) | ||
299 | { | ||
300 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
301 | struct netxbig_led_data *led_dat = | ||
302 | container_of(led_cdev, struct netxbig_led_data, cdev); | ||
303 | |||
304 | return sprintf(buf, "%d\n", led_dat->sata); | ||
305 | } | ||
306 | |||
307 | static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); | ||
308 | |||
309 | static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat) | ||
310 | { | ||
311 | if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) | ||
312 | device_remove_file(led_dat->cdev.dev, &dev_attr_sata); | ||
313 | led_classdev_unregister(&led_dat->cdev); | ||
314 | } | ||
315 | |||
316 | static int __devinit | ||
317 | create_netxbig_led(struct platform_device *pdev, | ||
318 | struct netxbig_led_data *led_dat, | ||
319 | const struct netxbig_led *template) | ||
320 | { | ||
321 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | ||
322 | int ret; | ||
323 | |||
324 | spin_lock_init(&led_dat->lock); | ||
325 | led_dat->gpio_ext = pdata->gpio_ext; | ||
326 | led_dat->cdev.name = template->name; | ||
327 | led_dat->cdev.default_trigger = template->default_trigger; | ||
328 | led_dat->cdev.blink_set = netxbig_led_blink_set; | ||
329 | led_dat->cdev.brightness_set = netxbig_led_set; | ||
330 | /* | ||
331 | * Because the GPIO extension bus don't allow to read registers | ||
332 | * value, there is no way to probe the LED initial state. | ||
333 | * So, the initial sysfs LED value for the "brightness" and "sata" | ||
334 | * attributes are inconsistent. | ||
335 | * | ||
336 | * Note that the initial LED state can't be reconfigured. | ||
337 | * The reason is that the LED behaviour must stay uniform during | ||
338 | * the whole boot process (bootloader+linux). | ||
339 | */ | ||
340 | led_dat->sata = 0; | ||
341 | led_dat->cdev.brightness = LED_OFF; | ||
342 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | ||
343 | led_dat->mode_addr = template->mode_addr; | ||
344 | led_dat->mode_val = template->mode_val; | ||
345 | led_dat->bright_addr = template->bright_addr; | ||
346 | led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1; | ||
347 | led_dat->timer = pdata->timer; | ||
348 | led_dat->num_timer = pdata->num_timer; | ||
349 | |||
350 | ret = led_classdev_register(&pdev->dev, &led_dat->cdev); | ||
351 | if (ret < 0) | ||
352 | return ret; | ||
353 | |||
354 | /* | ||
355 | * If available, expose the SATA activity blink capability through | ||
356 | * a "sata" sysfs attribute. | ||
357 | */ | ||
358 | if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) { | ||
359 | ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); | ||
360 | if (ret) | ||
361 | led_classdev_unregister(&led_dat->cdev); | ||
362 | } | ||
363 | |||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | static int __devinit netxbig_led_probe(struct platform_device *pdev) | ||
368 | { | ||
369 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | ||
370 | struct netxbig_led_data *leds_data; | ||
371 | int i; | ||
372 | int ret; | ||
373 | |||
374 | if (!pdata) | ||
375 | return -EINVAL; | ||
376 | |||
377 | leds_data = kzalloc(sizeof(struct netxbig_led_data) * pdata->num_leds, | ||
378 | GFP_KERNEL); | ||
379 | if (!leds_data) | ||
380 | return -ENOMEM; | ||
381 | |||
382 | ret = gpio_ext_init(pdata->gpio_ext); | ||
383 | if (ret < 0) | ||
384 | goto err_free_data; | ||
385 | |||
386 | for (i = 0; i < pdata->num_leds; i++) { | ||
387 | ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); | ||
388 | if (ret < 0) | ||
389 | goto err_free_leds; | ||
390 | } | ||
391 | |||
392 | platform_set_drvdata(pdev, leds_data); | ||
393 | |||
394 | return 0; | ||
395 | |||
396 | err_free_leds: | ||
397 | for (i = i - 1; i >= 0; i--) | ||
398 | delete_netxbig_led(&leds_data[i]); | ||
399 | |||
400 | gpio_ext_free(pdata->gpio_ext); | ||
401 | err_free_data: | ||
402 | kfree(leds_data); | ||
403 | |||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | static int __devexit netxbig_led_remove(struct platform_device *pdev) | ||
408 | { | ||
409 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | ||
410 | struct netxbig_led_data *leds_data; | ||
411 | int i; | ||
412 | |||
413 | leds_data = platform_get_drvdata(pdev); | ||
414 | |||
415 | for (i = 0; i < pdata->num_leds; i++) | ||
416 | delete_netxbig_led(&leds_data[i]); | ||
417 | |||
418 | gpio_ext_free(pdata->gpio_ext); | ||
419 | kfree(leds_data); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static struct platform_driver netxbig_led_driver = { | ||
425 | .probe = netxbig_led_probe, | ||
426 | .remove = __devexit_p(netxbig_led_remove), | ||
427 | .driver = { | ||
428 | .name = "leds-netxbig", | ||
429 | .owner = THIS_MODULE, | ||
430 | }, | ||
431 | }; | ||
432 | MODULE_ALIAS("platform:leds-netxbig"); | ||
433 | |||
434 | static int __init netxbig_led_init(void) | ||
435 | { | ||
436 | return platform_driver_register(&netxbig_led_driver); | ||
437 | } | ||
438 | |||
439 | static void __exit netxbig_led_exit(void) | ||
440 | { | ||
441 | platform_driver_unregister(&netxbig_led_driver); | ||
442 | } | ||
443 | |||
444 | module_init(netxbig_led_init); | ||
445 | module_exit(netxbig_led_exit); | ||
446 | |||
447 | MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); | ||
448 | MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); | ||
449 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 350eb34f049c..f77d48d0b3e4 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c | |||
@@ -141,10 +141,12 @@ static ssize_t ns2_led_sata_store(struct device *dev, | |||
141 | struct device_attribute *attr, | 141 | struct device_attribute *attr, |
142 | const char *buff, size_t count) | 142 | const char *buff, size_t count) |
143 | { | 143 | { |
144 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
145 | struct ns2_led_data *led_dat = | ||
146 | container_of(led_cdev, struct ns2_led_data, cdev); | ||
144 | int ret; | 147 | int ret; |
145 | unsigned long enable; | 148 | unsigned long enable; |
146 | enum ns2_led_modes mode; | 149 | enum ns2_led_modes mode; |
147 | struct ns2_led_data *led_dat = dev_get_drvdata(dev); | ||
148 | 150 | ||
149 | ret = strict_strtoul(buff, 10, &enable); | 151 | ret = strict_strtoul(buff, 10, &enable); |
150 | if (ret < 0) | 152 | if (ret < 0) |
@@ -172,7 +174,9 @@ static ssize_t ns2_led_sata_store(struct device *dev, | |||
172 | static ssize_t ns2_led_sata_show(struct device *dev, | 174 | static ssize_t ns2_led_sata_show(struct device *dev, |
173 | struct device_attribute *attr, char *buf) | 175 | struct device_attribute *attr, char *buf) |
174 | { | 176 | { |
175 | struct ns2_led_data *led_dat = dev_get_drvdata(dev); | 177 | struct led_classdev *led_cdev = dev_get_drvdata(dev); |
178 | struct ns2_led_data *led_dat = | ||
179 | container_of(led_cdev, struct ns2_led_data, cdev); | ||
176 | 180 | ||
177 | return sprintf(buf, "%d\n", led_dat->sata); | 181 | return sprintf(buf, "%d\n", led_dat->sata); |
178 | } | 182 | } |
@@ -234,7 +238,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, | |||
234 | if (ret < 0) | 238 | if (ret < 0) |
235 | goto err_free_slow; | 239 | goto err_free_slow; |
236 | 240 | ||
237 | dev_set_drvdata(led_dat->cdev.dev, led_dat); | ||
238 | ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); | 241 | ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); |
239 | if (ret < 0) | 242 | if (ret < 0) |
240 | goto err_free_cdev; | 243 | goto err_free_cdev; |
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 1c4ee6e77937..bf64e49d996a 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -83,7 +83,7 @@ static struct adb_driver *adb_controller; | |||
83 | BLOCKING_NOTIFIER_HEAD(adb_client_list); | 83 | BLOCKING_NOTIFIER_HEAD(adb_client_list); |
84 | static int adb_got_sleep; | 84 | static int adb_got_sleep; |
85 | static int adb_inited; | 85 | static int adb_inited; |
86 | static DECLARE_MUTEX(adb_probe_mutex); | 86 | static DEFINE_SEMAPHORE(adb_probe_mutex); |
87 | static int sleepy_trackpad; | 87 | static int sleepy_trackpad; |
88 | static int autopoll_devs; | 88 | static int autopoll_devs; |
89 | int __adb_probe_sync; | 89 | int __adb_probe_sync; |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 073f01390cdd..86294ed35c9b 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u | |||
193 | struct video_code32 { | 193 | struct video_code32 { |
194 | char loadwhat[16]; /* name or tag of file being passed */ | 194 | char loadwhat[16]; /* name or tag of file being passed */ |
195 | compat_int_t datasize; | 195 | compat_int_t datasize; |
196 | unsigned char *data; | 196 | compat_uptr_t data; |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) | 199 | static struct video_code __user *get_microcode32(struct video_code32 *kp) |
200 | { | 200 | { |
201 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || | 201 | struct video_code __user *up; |
202 | copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || | 202 | |
203 | get_user(kp->datasize, &up->datasize) || | 203 | up = compat_alloc_user_space(sizeof(*up)); |
204 | copy_from_user(kp->data, up->data, up->datasize)) | 204 | |
205 | return -EFAULT; | 205 | /* |
206 | return 0; | 206 | * NOTE! We don't actually care if these fail. If the |
207 | * user address is invalid, the native ioctl will do | ||
208 | * the error handling for us | ||
209 | */ | ||
210 | (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); | ||
211 | (void) put_user(kp->datasize, &up->datasize); | ||
212 | (void) put_user(compat_ptr(kp->data), &up->data); | ||
213 | return up; | ||
207 | } | 214 | } |
208 | 215 | ||
209 | #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) | 216 | #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) |
@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
739 | struct video_tuner vt; | 746 | struct video_tuner vt; |
740 | struct video_buffer vb; | 747 | struct video_buffer vb; |
741 | struct video_window vw; | 748 | struct video_window vw; |
742 | struct video_code vc; | 749 | struct video_code32 vc; |
743 | struct video_audio va; | 750 | struct video_audio va; |
744 | #endif | 751 | #endif |
745 | struct v4l2_format v2f; | 752 | struct v4l2_format v2f; |
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
818 | break; | 825 | break; |
819 | 826 | ||
820 | case VIDIOCSMICROCODE: | 827 | case VIDIOCSMICROCODE: |
821 | err = get_microcode32(&karg.vc, up); | 828 | /* Copy the 32-bit "video_code32" to kernel space */ |
822 | compatible_arg = 0; | 829 | if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) |
830 | return -EFAULT; | ||
831 | /* Convert the 32-bit version to a 64-bit version in user space */ | ||
832 | up = get_microcode32(&karg.vc); | ||
823 | break; | 833 | break; |
824 | 834 | ||
825 | case VIDIOCSFREQ: | 835 | case VIDIOCSFREQ: |
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c index e1c8b62b086d..01b6d584442c 100644 --- a/drivers/mfd/ab8500-spi.c +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -83,6 +83,11 @@ static int __devinit ab8500_spi_probe(struct spi_device *spi) | |||
83 | struct ab8500 *ab8500; | 83 | struct ab8500 *ab8500; |
84 | int ret; | 84 | int ret; |
85 | 85 | ||
86 | spi->bits_per_word = 24; | ||
87 | ret = spi_setup(spi); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
86 | ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL); | 91 | ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL); |
87 | if (!ab8500) | 92 | if (!ab8500) |
88 | return -ENOMEM; | 93 | return -ENOMEM; |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 097f24d8bceb..b9fda7018cef 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -78,7 +78,7 @@ struct sih { | |||
78 | u8 irq_lines; /* number of supported irq lines */ | 78 | u8 irq_lines; /* number of supported irq lines */ |
79 | 79 | ||
80 | /* SIR ignored -- set interrupt, for testing only */ | 80 | /* SIR ignored -- set interrupt, for testing only */ |
81 | struct irq_data { | 81 | struct sih_irq_data { |
82 | u8 isr_offset; | 82 | u8 isr_offset; |
83 | u8 imr_offset; | 83 | u8 imr_offset; |
84 | } mask[2]; | 84 | } mask[2]; |
@@ -810,7 +810,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
810 | twl4030_irq_chip = dummy_irq_chip; | 810 | twl4030_irq_chip = dummy_irq_chip; |
811 | twl4030_irq_chip.name = "twl4030"; | 811 | twl4030_irq_chip.name = "twl4030"; |
812 | 812 | ||
813 | twl4030_sih_irq_chip.ack = dummy_irq_chip.ack; | 813 | twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack; |
814 | 814 | ||
815 | for (i = irq_base; i < irq_end; i++) { | 815 | for (i = irq_base; i < irq_end; i++) { |
816 | set_irq_chip_and_handler(i, &twl4030_irq_chip, | 816 | set_irq_chip_and_handler(i, &twl4030_irq_chip, |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5db49b124ffa..09eee6df0653 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1631,6 +1631,19 @@ int mmc_suspend_host(struct mmc_host *host) | |||
1631 | if (host->bus_ops && !host->bus_dead) { | 1631 | if (host->bus_ops && !host->bus_dead) { |
1632 | if (host->bus_ops->suspend) | 1632 | if (host->bus_ops->suspend) |
1633 | err = host->bus_ops->suspend(host); | 1633 | err = host->bus_ops->suspend(host); |
1634 | if (err == -ENOSYS || !host->bus_ops->resume) { | ||
1635 | /* | ||
1636 | * We simply "remove" the card in this case. | ||
1637 | * It will be redetected on resume. | ||
1638 | */ | ||
1639 | if (host->bus_ops->remove) | ||
1640 | host->bus_ops->remove(host); | ||
1641 | mmc_claim_host(host); | ||
1642 | mmc_detach_bus(host); | ||
1643 | mmc_release_host(host); | ||
1644 | host->pm_flags = 0; | ||
1645 | err = 0; | ||
1646 | } | ||
1634 | } | 1647 | } |
1635 | mmc_bus_put(host); | 1648 | mmc_bus_put(host); |
1636 | 1649 | ||
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 840b301b5671..f2e02d7d9f3d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -41,23 +41,35 @@ static unsigned int fmax = 515633; | |||
41 | * @clkreg: default value for MCICLOCK register | 41 | * @clkreg: default value for MCICLOCK register |
42 | * @clkreg_enable: enable value for MMCICLOCK register | 42 | * @clkreg_enable: enable value for MMCICLOCK register |
43 | * @datalength_bits: number of bits in the MMCIDATALENGTH register | 43 | * @datalength_bits: number of bits in the MMCIDATALENGTH register |
44 | * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY | ||
45 | * is asserted (likewise for RX) | ||
46 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY | ||
47 | * is asserted (likewise for RX) | ||
44 | */ | 48 | */ |
45 | struct variant_data { | 49 | struct variant_data { |
46 | unsigned int clkreg; | 50 | unsigned int clkreg; |
47 | unsigned int clkreg_enable; | 51 | unsigned int clkreg_enable; |
48 | unsigned int datalength_bits; | 52 | unsigned int datalength_bits; |
53 | unsigned int fifosize; | ||
54 | unsigned int fifohalfsize; | ||
49 | }; | 55 | }; |
50 | 56 | ||
51 | static struct variant_data variant_arm = { | 57 | static struct variant_data variant_arm = { |
58 | .fifosize = 16 * 4, | ||
59 | .fifohalfsize = 8 * 4, | ||
52 | .datalength_bits = 16, | 60 | .datalength_bits = 16, |
53 | }; | 61 | }; |
54 | 62 | ||
55 | static struct variant_data variant_u300 = { | 63 | static struct variant_data variant_u300 = { |
64 | .fifosize = 16 * 4, | ||
65 | .fifohalfsize = 8 * 4, | ||
56 | .clkreg_enable = 1 << 13, /* HWFCEN */ | 66 | .clkreg_enable = 1 << 13, /* HWFCEN */ |
57 | .datalength_bits = 16, | 67 | .datalength_bits = 16, |
58 | }; | 68 | }; |
59 | 69 | ||
60 | static struct variant_data variant_ux500 = { | 70 | static struct variant_data variant_ux500 = { |
71 | .fifosize = 30 * 4, | ||
72 | .fifohalfsize = 8 * 4, | ||
61 | .clkreg = MCI_CLK_ENABLE, | 73 | .clkreg = MCI_CLK_ENABLE, |
62 | .clkreg_enable = 1 << 14, /* HWFCEN */ | 74 | .clkreg_enable = 1 << 14, /* HWFCEN */ |
63 | .datalength_bits = 24, | 75 | .datalength_bits = 24, |
@@ -138,6 +150,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) | |||
138 | 150 | ||
139 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | 151 | static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) |
140 | { | 152 | { |
153 | struct variant_data *variant = host->variant; | ||
141 | unsigned int datactrl, timeout, irqmask; | 154 | unsigned int datactrl, timeout, irqmask; |
142 | unsigned long long clks; | 155 | unsigned long long clks; |
143 | void __iomem *base; | 156 | void __iomem *base; |
@@ -173,7 +186,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
173 | * If we have less than a FIFOSIZE of bytes to transfer, | 186 | * If we have less than a FIFOSIZE of bytes to transfer, |
174 | * trigger a PIO interrupt as soon as any data is available. | 187 | * trigger a PIO interrupt as soon as any data is available. |
175 | */ | 188 | */ |
176 | if (host->size < MCI_FIFOSIZE) | 189 | if (host->size < variant->fifosize) |
177 | irqmask |= MCI_RXDATAAVLBLMASK; | 190 | irqmask |= MCI_RXDATAAVLBLMASK; |
178 | } else { | 191 | } else { |
179 | /* | 192 | /* |
@@ -332,13 +345,15 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema | |||
332 | 345 | ||
333 | static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) | 346 | static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) |
334 | { | 347 | { |
348 | struct variant_data *variant = host->variant; | ||
335 | void __iomem *base = host->base; | 349 | void __iomem *base = host->base; |
336 | char *ptr = buffer; | 350 | char *ptr = buffer; |
337 | 351 | ||
338 | do { | 352 | do { |
339 | unsigned int count, maxcnt; | 353 | unsigned int count, maxcnt; |
340 | 354 | ||
341 | maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE; | 355 | maxcnt = status & MCI_TXFIFOEMPTY ? |
356 | variant->fifosize : variant->fifohalfsize; | ||
342 | count = min(remain, maxcnt); | 357 | count = min(remain, maxcnt); |
343 | 358 | ||
344 | writesl(base + MMCIFIFO, ptr, count >> 2); | 359 | writesl(base + MMCIFIFO, ptr, count >> 2); |
@@ -362,6 +377,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
362 | { | 377 | { |
363 | struct mmci_host *host = dev_id; | 378 | struct mmci_host *host = dev_id; |
364 | struct sg_mapping_iter *sg_miter = &host->sg_miter; | 379 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
380 | struct variant_data *variant = host->variant; | ||
365 | void __iomem *base = host->base; | 381 | void __iomem *base = host->base; |
366 | unsigned long flags; | 382 | unsigned long flags; |
367 | u32 status; | 383 | u32 status; |
@@ -420,7 +436,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) | |||
420 | * If we're nearing the end of the read, switch to | 436 | * If we're nearing the end of the read, switch to |
421 | * "any data available" mode. | 437 | * "any data available" mode. |
422 | */ | 438 | */ |
423 | if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE) | 439 | if (status & MCI_RXACTIVE && host->size < variant->fifosize) |
424 | writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); | 440 | writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); |
425 | 441 | ||
426 | /* | 442 | /* |
@@ -564,18 +580,23 @@ static int mmci_get_ro(struct mmc_host *mmc) | |||
564 | if (host->gpio_wp == -ENOSYS) | 580 | if (host->gpio_wp == -ENOSYS) |
565 | return -ENOSYS; | 581 | return -ENOSYS; |
566 | 582 | ||
567 | return gpio_get_value(host->gpio_wp); | 583 | return gpio_get_value_cansleep(host->gpio_wp); |
568 | } | 584 | } |
569 | 585 | ||
570 | static int mmci_get_cd(struct mmc_host *mmc) | 586 | static int mmci_get_cd(struct mmc_host *mmc) |
571 | { | 587 | { |
572 | struct mmci_host *host = mmc_priv(mmc); | 588 | struct mmci_host *host = mmc_priv(mmc); |
589 | struct mmci_platform_data *plat = host->plat; | ||
573 | unsigned int status; | 590 | unsigned int status; |
574 | 591 | ||
575 | if (host->gpio_cd == -ENOSYS) | 592 | if (host->gpio_cd == -ENOSYS) { |
576 | status = host->plat->status(mmc_dev(host->mmc)); | 593 | if (!plat->status) |
577 | else | 594 | return 1; /* Assume always present */ |
578 | status = !gpio_get_value(host->gpio_cd); | 595 | |
596 | status = plat->status(mmc_dev(host->mmc)); | ||
597 | } else | ||
598 | status = !!gpio_get_value_cansleep(host->gpio_cd) | ||
599 | ^ plat->cd_invert; | ||
579 | 600 | ||
580 | /* | 601 | /* |
581 | * Use positive logic throughout - status is zero for no card, | 602 | * Use positive logic throughout - status is zero for no card, |
@@ -584,6 +605,15 @@ static int mmci_get_cd(struct mmc_host *mmc) | |||
584 | return status; | 605 | return status; |
585 | } | 606 | } |
586 | 607 | ||
608 | static irqreturn_t mmci_cd_irq(int irq, void *dev_id) | ||
609 | { | ||
610 | struct mmci_host *host = dev_id; | ||
611 | |||
612 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | ||
613 | |||
614 | return IRQ_HANDLED; | ||
615 | } | ||
616 | |||
587 | static const struct mmc_host_ops mmci_ops = { | 617 | static const struct mmc_host_ops mmci_ops = { |
588 | .request = mmci_request, | 618 | .request = mmci_request, |
589 | .set_ios = mmci_set_ios, | 619 | .set_ios = mmci_set_ios, |
@@ -620,6 +650,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
620 | 650 | ||
621 | host->gpio_wp = -ENOSYS; | 651 | host->gpio_wp = -ENOSYS; |
622 | host->gpio_cd = -ENOSYS; | 652 | host->gpio_cd = -ENOSYS; |
653 | host->gpio_cd_irq = -1; | ||
623 | 654 | ||
624 | host->hw_designer = amba_manf(dev); | 655 | host->hw_designer = amba_manf(dev); |
625 | host->hw_revision = amba_rev(dev); | 656 | host->hw_revision = amba_rev(dev); |
@@ -699,7 +730,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
699 | if (host->vcc == NULL) | 730 | if (host->vcc == NULL) |
700 | mmc->ocr_avail = plat->ocr_mask; | 731 | mmc->ocr_avail = plat->ocr_mask; |
701 | mmc->caps = plat->capabilities; | 732 | mmc->caps = plat->capabilities; |
702 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
703 | 733 | ||
704 | /* | 734 | /* |
705 | * We can do SGIO | 735 | * We can do SGIO |
@@ -744,6 +774,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
744 | host->gpio_cd = plat->gpio_cd; | 774 | host->gpio_cd = plat->gpio_cd; |
745 | else if (ret != -ENOSYS) | 775 | else if (ret != -ENOSYS) |
746 | goto err_gpio_cd; | 776 | goto err_gpio_cd; |
777 | |||
778 | ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), | ||
779 | mmci_cd_irq, 0, | ||
780 | DRIVER_NAME " (cd)", host); | ||
781 | if (ret >= 0) | ||
782 | host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); | ||
747 | } | 783 | } |
748 | if (gpio_is_valid(plat->gpio_wp)) { | 784 | if (gpio_is_valid(plat->gpio_wp)) { |
749 | ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); | 785 | ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); |
@@ -755,6 +791,10 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
755 | goto err_gpio_wp; | 791 | goto err_gpio_wp; |
756 | } | 792 | } |
757 | 793 | ||
794 | if ((host->plat->status || host->gpio_cd != -ENOSYS) | ||
795 | && host->gpio_cd_irq < 0) | ||
796 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
797 | |||
758 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); | 798 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); |
759 | if (ret) | 799 | if (ret) |
760 | goto unmap; | 800 | goto unmap; |
@@ -781,6 +821,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
781 | if (host->gpio_wp != -ENOSYS) | 821 | if (host->gpio_wp != -ENOSYS) |
782 | gpio_free(host->gpio_wp); | 822 | gpio_free(host->gpio_wp); |
783 | err_gpio_wp: | 823 | err_gpio_wp: |
824 | if (host->gpio_cd_irq >= 0) | ||
825 | free_irq(host->gpio_cd_irq, host); | ||
784 | if (host->gpio_cd != -ENOSYS) | 826 | if (host->gpio_cd != -ENOSYS) |
785 | gpio_free(host->gpio_cd); | 827 | gpio_free(host->gpio_cd); |
786 | err_gpio_cd: | 828 | err_gpio_cd: |
@@ -819,6 +861,8 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
819 | 861 | ||
820 | if (host->gpio_wp != -ENOSYS) | 862 | if (host->gpio_wp != -ENOSYS) |
821 | gpio_free(host->gpio_wp); | 863 | gpio_free(host->gpio_wp); |
864 | if (host->gpio_cd_irq >= 0) | ||
865 | free_irq(host->gpio_cd_irq, host); | ||
822 | if (host->gpio_cd != -ENOSYS) | 866 | if (host->gpio_cd != -ENOSYS) |
823 | gpio_free(host->gpio_cd); | 867 | gpio_free(host->gpio_cd); |
824 | 868 | ||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 68970cfb81e1..4ae887fc0189 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
@@ -54,10 +54,16 @@ | |||
54 | #define MCI_DPSM_MODE (1 << 2) | 54 | #define MCI_DPSM_MODE (1 << 2) |
55 | #define MCI_DPSM_DMAENABLE (1 << 3) | 55 | #define MCI_DPSM_DMAENABLE (1 << 3) |
56 | #define MCI_DPSM_BLOCKSIZE (1 << 4) | 56 | #define MCI_DPSM_BLOCKSIZE (1 << 4) |
57 | #define MCI_DPSM_RWSTART (1 << 8) | 57 | /* Control register extensions in the ST Micro U300 and Ux500 versions */ |
58 | #define MCI_DPSM_RWSTOP (1 << 9) | 58 | #define MCI_ST_DPSM_RWSTART (1 << 8) |
59 | #define MCI_DPSM_RWMOD (1 << 10) | 59 | #define MCI_ST_DPSM_RWSTOP (1 << 9) |
60 | #define MCI_DPSM_SDIOEN (1 << 11) | 60 | #define MCI_ST_DPSM_RWMOD (1 << 10) |
61 | #define MCI_ST_DPSM_SDIOEN (1 << 11) | ||
62 | /* Control register extensions in the ST Micro Ux500 versions */ | ||
63 | #define MCI_ST_DPSM_DMAREQCTL (1 << 12) | ||
64 | #define MCI_ST_DPSM_DBOOTMODEEN (1 << 13) | ||
65 | #define MCI_ST_DPSM_BUSYMODE (1 << 14) | ||
66 | #define MCI_ST_DPSM_DDRMODE (1 << 15) | ||
61 | 67 | ||
62 | #define MMCIDATACNT 0x030 | 68 | #define MMCIDATACNT 0x030 |
63 | #define MMCISTATUS 0x034 | 69 | #define MMCISTATUS 0x034 |
@@ -133,13 +139,6 @@ | |||
133 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ | 139 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ |
134 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) | 140 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) |
135 | 141 | ||
136 | /* | ||
137 | * The size of the FIFO in bytes. | ||
138 | */ | ||
139 | #define MCI_FIFOSIZE (16*4) | ||
140 | |||
141 | #define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2) | ||
142 | |||
143 | #define NR_SG 16 | 142 | #define NR_SG 16 |
144 | 143 | ||
145 | struct clk; | 144 | struct clk; |
@@ -154,6 +153,7 @@ struct mmci_host { | |||
154 | struct clk *clk; | 153 | struct clk *clk; |
155 | int gpio_cd; | 154 | int gpio_cd; |
156 | int gpio_wp; | 155 | int gpio_wp; |
156 | int gpio_cd_irq; | ||
157 | 157 | ||
158 | unsigned int data_xfered; | 158 | unsigned int data_xfered; |
159 | 159 | ||
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index 7aa65bb2af4a..f472c2714eb8 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
31 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
32 | 32 | ||
33 | #include <pcmcia/cs.h> | ||
34 | #include <pcmcia/cistpl.h> | 33 | #include <pcmcia/cistpl.h> |
35 | #include <pcmcia/ds.h> | 34 | #include <pcmcia/ds.h> |
36 | #include <linux/io.h> | 35 | #include <linux/io.h> |
@@ -536,9 +535,7 @@ static int sdricoh_pcmcia_resume(struct pcmcia_device *link) | |||
536 | #endif | 535 | #endif |
537 | 536 | ||
538 | static struct pcmcia_driver sdricoh_driver = { | 537 | static struct pcmcia_driver sdricoh_driver = { |
539 | .drv = { | 538 | .name = DRIVER_NAME, |
540 | .name = DRIVER_NAME, | ||
541 | }, | ||
542 | .probe = sdricoh_pcmcia_probe, | 539 | .probe = sdricoh_pcmcia_probe, |
543 | .remove = sdricoh_pcmcia_detach, | 540 | .remove = sdricoh_pcmcia_detach, |
544 | .id_table = pcmcia_ids, | 541 | .id_table = pcmcia_ids, |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index e9ca5ba7d9d2..57a1acfe22c4 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/system.h> | 17 | #include <asm/system.h> |
18 | 18 | ||
19 | #include <pcmcia/cs.h> | ||
20 | #include <pcmcia/cistpl.h> | 19 | #include <pcmcia/cistpl.h> |
21 | #include <pcmcia/ds.h> | 20 | #include <pcmcia/ds.h> |
22 | 21 | ||
@@ -101,7 +100,7 @@ MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)") | |||
101 | static caddr_t remap_window(struct map_info *map, unsigned long to) | 100 | static caddr_t remap_window(struct map_info *map, unsigned long to) |
102 | { | 101 | { |
103 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 102 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
104 | window_handle_t win = (window_handle_t)map->map_priv_2; | 103 | struct resource *win = (struct resource *) map->map_priv_2; |
105 | unsigned int offset; | 104 | unsigned int offset; |
106 | int ret; | 105 | int ret; |
107 | 106 | ||
@@ -316,30 +315,19 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
316 | { | 315 | { |
317 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 316 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
318 | struct pcmcia_device *link = dev->p_dev; | 317 | struct pcmcia_device *link = dev->p_dev; |
319 | modconf_t mod; | ||
320 | int ret; | ||
321 | |||
322 | mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID; | ||
323 | mod.Vcc = 0; | ||
324 | mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; | ||
325 | 318 | ||
326 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); | 319 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); |
327 | ret = pcmcia_modify_configuration(link, &mod); | 320 | pcmcia_fixup_vpp(link, on ? dev->vpp : 0); |
328 | } | 321 | } |
329 | 322 | ||
330 | 323 | ||
331 | /* After a card is removed, pcmciamtd_release() will unregister the | ||
332 | * device, and release the PCMCIA configuration. If the device is | ||
333 | * still open, this will be postponed until it is closed. | ||
334 | */ | ||
335 | |||
336 | static void pcmciamtd_release(struct pcmcia_device *link) | 324 | static void pcmciamtd_release(struct pcmcia_device *link) |
337 | { | 325 | { |
338 | struct pcmciamtd_dev *dev = link->priv; | 326 | struct pcmciamtd_dev *dev = link->priv; |
339 | 327 | ||
340 | DEBUG(3, "link = 0x%p", link); | 328 | DEBUG(3, "link = 0x%p", link); |
341 | 329 | ||
342 | if (link->win) { | 330 | if (link->resource[2]->end) { |
343 | if(dev->win_base) { | 331 | if(dev->win_base) { |
344 | iounmap(dev->win_base); | 332 | iounmap(dev->win_base); |
345 | dev->win_base = NULL; | 333 | dev->win_base = NULL; |
@@ -482,18 +470,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev | |||
482 | } | 470 | } |
483 | 471 | ||
484 | 472 | ||
485 | /* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event | ||
486 | * is received, to configure the PCMCIA socket, and to make the | ||
487 | * MTD device available to the system. | ||
488 | */ | ||
489 | |||
490 | static int pcmciamtd_config(struct pcmcia_device *link) | 473 | static int pcmciamtd_config(struct pcmcia_device *link) |
491 | { | 474 | { |
492 | struct pcmciamtd_dev *dev = link->priv; | 475 | struct pcmciamtd_dev *dev = link->priv; |
493 | struct mtd_info *mtd = NULL; | 476 | struct mtd_info *mtd = NULL; |
494 | win_req_t req; | ||
495 | int ret; | 477 | int ret; |
496 | int i; | 478 | int i, j = 0; |
497 | static char *probes[] = { "jedec_probe", "cfi_probe" }; | 479 | static char *probes[] = { "jedec_probe", "cfi_probe" }; |
498 | int new_name = 0; | 480 | int new_name = 0; |
499 | 481 | ||
@@ -520,28 +502,34 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
520 | * smaller windows until we succeed | 502 | * smaller windows until we succeed |
521 | */ | 503 | */ |
522 | 504 | ||
523 | req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; | 505 | link->resource[2]->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
524 | req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; | 506 | link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ? |
525 | req.Base = 0; | 507 | WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; |
526 | req.AccessSpeed = mem_speed; | 508 | link->resource[2]->start = 0; |
527 | link->win = (window_handle_t)link; | 509 | link->resource[2]->end = (force_size) ? force_size << 20 : |
528 | req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; | 510 | MAX_PCMCIA_ADDR; |
529 | dev->win_size = 0; | 511 | dev->win_size = 0; |
530 | 512 | ||
531 | do { | 513 | do { |
532 | int ret; | 514 | int ret; |
533 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", | 515 | DEBUG(2, "requesting window with size = %luKiB memspeed = %d", |
534 | req.Size >> 10, req.AccessSpeed); | 516 | (unsigned long) resource_size(link->resource[2]) >> 10, |
535 | ret = pcmcia_request_window(link, &req, &link->win); | 517 | mem_speed); |
518 | ret = pcmcia_request_window(link, link->resource[2], mem_speed); | ||
536 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); | 519 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); |
537 | if(ret) { | 520 | if(ret) { |
538 | req.Size >>= 1; | 521 | j++; |
522 | link->resource[2]->start = 0; | ||
523 | link->resource[2]->end = (force_size) ? | ||
524 | force_size << 20 : MAX_PCMCIA_ADDR; | ||
525 | link->resource[2]->end >>= j; | ||
539 | } else { | 526 | } else { |
540 | DEBUG(2, "Got window of size %dKiB", req.Size >> 10); | 527 | DEBUG(2, "Got window of size %luKiB", (unsigned long) |
541 | dev->win_size = req.Size; | 528 | resource_size(link->resource[2]) >> 10); |
529 | dev->win_size = resource_size(link->resource[2]); | ||
542 | break; | 530 | break; |
543 | } | 531 | } |
544 | } while(req.Size >= 0x1000); | 532 | } while (link->resource[2]->end >= 0x1000); |
545 | 533 | ||
546 | DEBUG(2, "dev->win_size = %d", dev->win_size); | 534 | DEBUG(2, "dev->win_size = %d", dev->win_size); |
547 | 535 | ||
@@ -553,33 +541,31 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
553 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); | 541 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); |
554 | 542 | ||
555 | /* Get write protect status */ | 543 | /* Get write protect status */ |
556 | DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win); | 544 | dev->win_base = ioremap(link->resource[2]->start, |
557 | dev->win_base = ioremap(req.Base, req.Size); | 545 | resource_size(link->resource[2])); |
558 | if(!dev->win_base) { | 546 | if(!dev->win_base) { |
559 | dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n", | 547 | dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n", |
560 | req.Base, req.Size); | 548 | link->resource[2]); |
561 | pcmciamtd_release(link); | 549 | pcmciamtd_release(link); |
562 | return -ENODEV; | 550 | return -ENODEV; |
563 | } | 551 | } |
564 | DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", | 552 | DEBUG(1, "mapped window dev = %p @ %pR, base = %p", |
565 | dev, req.Base, dev->win_base, req.Size); | 553 | dev, link->resource[2], dev->win_base); |
566 | 554 | ||
567 | dev->offset = 0; | 555 | dev->offset = 0; |
568 | dev->pcmcia_map.map_priv_1 = (unsigned long)dev; | 556 | dev->pcmcia_map.map_priv_1 = (unsigned long)dev; |
569 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; | 557 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2]; |
570 | 558 | ||
571 | dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp; | 559 | dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp; |
572 | link->conf.Attributes = 0; | ||
573 | if(setvpp == 2) { | 560 | if(setvpp == 2) { |
574 | link->conf.Vpp = dev->vpp; | 561 | link->vpp = dev->vpp; |
575 | } else { | 562 | } else { |
576 | link->conf.Vpp = 0; | 563 | link->vpp = 0; |
577 | } | 564 | } |
578 | 565 | ||
579 | link->conf.IntType = INT_MEMORY; | 566 | link->config_index = 0; |
580 | link->conf.ConfigIndex = 0; | ||
581 | DEBUG(2, "Setting Configuration"); | 567 | DEBUG(2, "Setting Configuration"); |
582 | ret = pcmcia_request_configuration(link, &link->conf); | 568 | ret = pcmcia_enable_device(link); |
583 | if (ret != 0) { | 569 | if (ret != 0) { |
584 | if (dev->win_base) { | 570 | if (dev->win_base) { |
585 | iounmap(dev->win_base); | 571 | iounmap(dev->win_base); |
@@ -680,12 +666,6 @@ static int pcmciamtd_resume(struct pcmcia_device *dev) | |||
680 | } | 666 | } |
681 | 667 | ||
682 | 668 | ||
683 | /* This deletes a driver "instance". The device is de-registered | ||
684 | * with Card Services. If it has been released, all local data | ||
685 | * structures are freed. Otherwise, the structures will be freed | ||
686 | * when the device is released. | ||
687 | */ | ||
688 | |||
689 | static void pcmciamtd_detach(struct pcmcia_device *link) | 669 | static void pcmciamtd_detach(struct pcmcia_device *link) |
690 | { | 670 | { |
691 | struct pcmciamtd_dev *dev = link->priv; | 671 | struct pcmciamtd_dev *dev = link->priv; |
@@ -703,11 +683,6 @@ static void pcmciamtd_detach(struct pcmcia_device *link) | |||
703 | } | 683 | } |
704 | 684 | ||
705 | 685 | ||
706 | /* pcmciamtd_attach() creates an "instance" of the driver, allocating | ||
707 | * local data structures for one device. The device is registered | ||
708 | * with Card Services. | ||
709 | */ | ||
710 | |||
711 | static int pcmciamtd_probe(struct pcmcia_device *link) | 686 | static int pcmciamtd_probe(struct pcmcia_device *link) |
712 | { | 687 | { |
713 | struct pcmciamtd_dev *dev; | 688 | struct pcmciamtd_dev *dev; |
@@ -720,9 +695,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link) | |||
720 | dev->p_dev = link; | 695 | dev->p_dev = link; |
721 | link->priv = dev; | 696 | link->priv = dev; |
722 | 697 | ||
723 | link->conf.Attributes = 0; | ||
724 | link->conf.IntType = INT_MEMORY; | ||
725 | |||
726 | return pcmciamtd_config(link); | 698 | return pcmciamtd_config(link); |
727 | } | 699 | } |
728 | 700 | ||
@@ -757,9 +729,7 @@ static struct pcmcia_device_id pcmciamtd_ids[] = { | |||
757 | MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); | 729 | MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); |
758 | 730 | ||
759 | static struct pcmcia_driver pcmciamtd_driver = { | 731 | static struct pcmcia_driver pcmciamtd_driver = { |
760 | .drv = { | 732 | .name = "pcmciamtd", |
761 | .name = "pcmciamtd" | ||
762 | }, | ||
763 | .probe = pcmciamtd_probe, | 733 | .probe = pcmciamtd_probe, |
764 | .remove = pcmciamtd_detach, | 734 | .remove = pcmciamtd_detach, |
765 | .owner = THIS_MODULE, | 735 | .owner = THIS_MODULE, |
@@ -771,8 +741,6 @@ static struct pcmcia_driver pcmciamtd_driver = { | |||
771 | 741 | ||
772 | static int __init init_pcmciamtd(void) | 742 | static int __init init_pcmciamtd(void) |
773 | { | 743 | { |
774 | info(DRIVER_DESC); | ||
775 | |||
776 | if(bankwidth && bankwidth != 1 && bankwidth != 2) { | 744 | if(bankwidth && bankwidth != 1 && bankwidth != 2) { |
777 | info("bad bankwidth (%d), using default", bankwidth); | 745 | info("bad bankwidth (%d), using default", bankwidth); |
778 | bankwidth = 2; | 746 | bankwidth = 2; |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2828e84d243..214b03afdd48 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/irq.h> | ||
34 | #include <linux/completion.h> | ||
33 | 35 | ||
34 | #include <asm/mach/flash.h> | 36 | #include <asm/mach/flash.h> |
35 | #include <mach/mxc_nand.h> | 37 | #include <mach/mxc_nand.h> |
@@ -151,7 +153,7 @@ struct mxc_nand_host { | |||
151 | int irq; | 153 | int irq; |
152 | int eccsize; | 154 | int eccsize; |
153 | 155 | ||
154 | wait_queue_head_t irq_waitq; | 156 | struct completion op_completion; |
155 | 157 | ||
156 | uint8_t *data_buf; | 158 | uint8_t *data_buf; |
157 | unsigned int buf_start; | 159 | unsigned int buf_start; |
@@ -164,6 +166,7 @@ struct mxc_nand_host { | |||
164 | void (*send_read_id)(struct mxc_nand_host *); | 166 | void (*send_read_id)(struct mxc_nand_host *); |
165 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | 167 | uint16_t (*get_dev_status)(struct mxc_nand_host *); |
166 | int (*check_int)(struct mxc_nand_host *); | 168 | int (*check_int)(struct mxc_nand_host *); |
169 | void (*irq_control)(struct mxc_nand_host *, int); | ||
167 | }; | 170 | }; |
168 | 171 | ||
169 | /* OOB placement block for use with hardware ecc generation */ | 172 | /* OOB placement block for use with hardware ecc generation */ |
@@ -216,9 +219,12 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
216 | { | 219 | { |
217 | struct mxc_nand_host *host = dev_id; | 220 | struct mxc_nand_host *host = dev_id; |
218 | 221 | ||
219 | disable_irq_nosync(irq); | 222 | if (!host->check_int(host)) |
223 | return IRQ_NONE; | ||
220 | 224 | ||
221 | wake_up(&host->irq_waitq); | 225 | host->irq_control(host, 0); |
226 | |||
227 | complete(&host->op_completion); | ||
222 | 228 | ||
223 | return IRQ_HANDLED; | 229 | return IRQ_HANDLED; |
224 | } | 230 | } |
@@ -245,11 +251,54 @@ static int check_int_v1_v2(struct mxc_nand_host *host) | |||
245 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | 251 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) |
246 | return 0; | 252 | return 0; |
247 | 253 | ||
248 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | 254 | if (!cpu_is_mx21()) |
255 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | ||
249 | 256 | ||
250 | return 1; | 257 | return 1; |
251 | } | 258 | } |
252 | 259 | ||
260 | /* | ||
261 | * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit | ||
262 | * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the | ||
263 | * driver can enable/disable the irq line rather than simply masking the | ||
264 | * interrupts. | ||
265 | */ | ||
266 | static void irq_control_mx21(struct mxc_nand_host *host, int activate) | ||
267 | { | ||
268 | if (activate) | ||
269 | enable_irq(host->irq); | ||
270 | else | ||
271 | disable_irq_nosync(host->irq); | ||
272 | } | ||
273 | |||
274 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) | ||
275 | { | ||
276 | uint16_t tmp; | ||
277 | |||
278 | tmp = readw(NFC_V1_V2_CONFIG1); | ||
279 | |||
280 | if (activate) | ||
281 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; | ||
282 | else | ||
283 | tmp |= NFC_V1_V2_CONFIG1_INT_MSK; | ||
284 | |||
285 | writew(tmp, NFC_V1_V2_CONFIG1); | ||
286 | } | ||
287 | |||
288 | static void irq_control_v3(struct mxc_nand_host *host, int activate) | ||
289 | { | ||
290 | uint32_t tmp; | ||
291 | |||
292 | tmp = readl(NFC_V3_CONFIG2); | ||
293 | |||
294 | if (activate) | ||
295 | tmp &= ~NFC_V3_CONFIG2_INT_MSK; | ||
296 | else | ||
297 | tmp |= NFC_V3_CONFIG2_INT_MSK; | ||
298 | |||
299 | writel(tmp, NFC_V3_CONFIG2); | ||
300 | } | ||
301 | |||
253 | /* This function polls the NANDFC to wait for the basic operation to | 302 | /* This function polls the NANDFC to wait for the basic operation to |
254 | * complete by checking the INT bit of config2 register. | 303 | * complete by checking the INT bit of config2 register. |
255 | */ | 304 | */ |
@@ -259,10 +308,9 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
259 | 308 | ||
260 | if (useirq) { | 309 | if (useirq) { |
261 | if (!host->check_int(host)) { | 310 | if (!host->check_int(host)) { |
262 | 311 | INIT_COMPLETION(host->op_completion); | |
263 | enable_irq(host->irq); | 312 | host->irq_control(host, 1); |
264 | 313 | wait_for_completion(&host->op_completion); | |
265 | wait_event(host->irq_waitq, host->check_int(host)); | ||
266 | } | 314 | } |
267 | } else { | 315 | } else { |
268 | while (max_retries-- > 0) { | 316 | while (max_retries-- > 0) { |
@@ -799,6 +847,7 @@ static void preset_v3(struct mtd_info *mtd) | |||
799 | NFC_V3_CONFIG2_2CMD_PHASES | | 847 | NFC_V3_CONFIG2_2CMD_PHASES | |
800 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | | 848 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | |
801 | NFC_V3_CONFIG2_ST_CMD(0x70) | | 849 | NFC_V3_CONFIG2_ST_CMD(0x70) | |
850 | NFC_V3_CONFIG2_INT_MSK | | ||
802 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | 851 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; |
803 | 852 | ||
804 | if (chip->ecc.mode == NAND_ECC_HW) | 853 | if (chip->ecc.mode == NAND_ECC_HW) |
@@ -1024,6 +1073,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1024 | host->send_read_id = send_read_id_v1_v2; | 1073 | host->send_read_id = send_read_id_v1_v2; |
1025 | host->get_dev_status = get_dev_status_v1_v2; | 1074 | host->get_dev_status = get_dev_status_v1_v2; |
1026 | host->check_int = check_int_v1_v2; | 1075 | host->check_int = check_int_v1_v2; |
1076 | if (cpu_is_mx21()) | ||
1077 | host->irq_control = irq_control_mx21; | ||
1078 | else | ||
1079 | host->irq_control = irq_control_v1_v2; | ||
1027 | } | 1080 | } |
1028 | 1081 | ||
1029 | if (nfc_is_v21()) { | 1082 | if (nfc_is_v21()) { |
@@ -1062,6 +1115,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1062 | host->send_read_id = send_read_id_v3; | 1115 | host->send_read_id = send_read_id_v3; |
1063 | host->check_int = check_int_v3; | 1116 | host->check_int = check_int_v3; |
1064 | host->get_dev_status = get_dev_status_v3; | 1117 | host->get_dev_status = get_dev_status_v3; |
1118 | host->irq_control = irq_control_v3; | ||
1065 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1119 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
1066 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1120 | oob_largepage = &nandv2_hw_eccoob_largepage; |
1067 | } else | 1121 | } else |
@@ -1093,14 +1147,34 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1093 | this->options |= NAND_USE_FLASH_BBT; | 1147 | this->options |= NAND_USE_FLASH_BBT; |
1094 | } | 1148 | } |
1095 | 1149 | ||
1096 | init_waitqueue_head(&host->irq_waitq); | 1150 | init_completion(&host->op_completion); |
1097 | 1151 | ||
1098 | host->irq = platform_get_irq(pdev, 0); | 1152 | host->irq = platform_get_irq(pdev, 0); |
1099 | 1153 | ||
1154 | /* | ||
1155 | * mask the interrupt. For i.MX21 explicitely call | ||
1156 | * irq_control_v1_v2 to use the mask bit. We can't call | ||
1157 | * disable_irq_nosync() for an interrupt we do not own yet. | ||
1158 | */ | ||
1159 | if (cpu_is_mx21()) | ||
1160 | irq_control_v1_v2(host, 0); | ||
1161 | else | ||
1162 | host->irq_control(host, 0); | ||
1163 | |||
1100 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); | 1164 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); |
1101 | if (err) | 1165 | if (err) |
1102 | goto eirq; | 1166 | goto eirq; |
1103 | 1167 | ||
1168 | host->irq_control(host, 0); | ||
1169 | |||
1170 | /* | ||
1171 | * Now that the interrupt is disabled make sure the interrupt | ||
1172 | * mask bit is cleared on i.MX21. Otherwise we can't read | ||
1173 | * the interrupt status bit on this machine. | ||
1174 | */ | ||
1175 | if (cpu_is_mx21()) | ||
1176 | irq_control_v1_v2(host, 1); | ||
1177 | |||
1104 | /* first scan to find the device and get the page size */ | 1178 | /* first scan to find the device and get the page size */ |
1105 | if (nand_scan_ident(mtd, 1, NULL)) { | 1179 | if (nand_scan_ident(mtd, 1, NULL)) { |
1106 | err = -ENXIO; | 1180 | err = -ENXIO; |
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 70705d1306b9..eca55c52bdfd 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c | |||
@@ -522,7 +522,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) | |||
522 | lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */ | 522 | lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */ |
523 | lp->rx_len = lp->exec_box->data[11]; /* Receive list count */ | 523 | lp->rx_len = lp->exec_box->data[11]; /* Receive list count */ |
524 | 524 | ||
525 | init_MUTEX_LOCKED(&lp->cmd_mutex); | 525 | sema_init(&lp->cmd_mutex, 0); |
526 | init_completion(&lp->execution_cmd); | 526 | init_completion(&lp->execution_cmd); |
527 | init_completion(&lp->xceiver_cmd); | 527 | init_completion(&lp->xceiver_cmd); |
528 | 528 | ||
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a54cbf3..77efe462b921 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2,6 +2,9 @@ | |||
2 | # Network device configuration | 2 | # Network device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | config HAVE_NET_MACB | ||
6 | bool | ||
7 | |||
5 | menuconfig NETDEVICES | 8 | menuconfig NETDEVICES |
6 | default y if UML | 9 | default y if UML |
7 | depends on NET | 10 | depends on NET |
@@ -221,7 +224,7 @@ config MII | |||
221 | 224 | ||
222 | config MACB | 225 | config MACB |
223 | tristate "Atmel MACB support" | 226 | tristate "Atmel MACB support" |
224 | depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 | 227 | depends on HAVE_NET_MACB |
225 | select PHYLIB | 228 | select PHYLIB |
226 | help | 229 | help |
227 | The Atmel MACB ethernet interface is found on many AT32 and AT91 | 230 | The Atmel MACB ethernet interface is found on many AT32 and AT91 |
@@ -2428,7 +2431,7 @@ config UGETH_TX_ON_DEMAND | |||
2428 | 2431 | ||
2429 | config MV643XX_ETH | 2432 | config MV643XX_ETH |
2430 | tristate "Marvell Discovery (643XX) and Orion ethernet support" | 2433 | tristate "Marvell Discovery (643XX) and Orion ethernet support" |
2431 | depends on MV64X60 || PPC32 || PLAT_ORION | 2434 | depends on (MV64X60 || PPC32 || PLAT_ORION) && INET |
2432 | select INET_LRO | 2435 | select INET_LRO |
2433 | select PHYLIB | 2436 | select PHYLIB |
2434 | help | 2437 | help |
@@ -2803,7 +2806,7 @@ config NIU | |||
2803 | 2806 | ||
2804 | config PASEMI_MAC | 2807 | config PASEMI_MAC |
2805 | tristate "PA Semi 1/10Gbit MAC" | 2808 | tristate "PA Semi 1/10Gbit MAC" |
2806 | depends on PPC_PASEMI && PCI | 2809 | depends on PPC_PASEMI && PCI && INET |
2807 | select PHYLIB | 2810 | select PHYLIB |
2808 | select INET_LRO | 2811 | select INET_LRO |
2809 | help | 2812 | help |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 1e620e287ae0..efeffdf9e5fa 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -2170,8 +2170,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev, | |||
2170 | dev->irq = sdev->irq; | 2170 | dev->irq = sdev->irq; |
2171 | SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); | 2171 | SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); |
2172 | 2172 | ||
2173 | netif_carrier_off(dev); | ||
2174 | |||
2175 | err = ssb_bus_powerup(sdev->bus, 0); | 2173 | err = ssb_bus_powerup(sdev->bus, 0); |
2176 | if (err) { | 2174 | if (err) { |
2177 | dev_err(sdev->dev, | 2175 | dev_err(sdev->dev, |
@@ -2213,6 +2211,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev, | |||
2213 | goto err_out_powerdown; | 2211 | goto err_out_powerdown; |
2214 | } | 2212 | } |
2215 | 2213 | ||
2214 | netif_carrier_off(dev); | ||
2215 | |||
2216 | ssb_set_drvdata(sdev, dev); | 2216 | ssb_set_drvdata(sdev, dev); |
2217 | 2217 | ||
2218 | /* Chip reset provides power to the b44 MAC & PCI cores, which | 2218 | /* Chip reset provides power to the b44 MAC & PCI cores, which |
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 012613fde3f4..03d063554b7f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/blackfin.h> | 38 | #include <asm/blackfin.h> |
39 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
40 | #include <asm/portmux.h> | 40 | #include <asm/portmux.h> |
41 | #include <mach/pll.h> | ||
41 | 42 | ||
42 | #include "bfin_mac.h" | 43 | #include "bfin_mac.h" |
43 | 44 | ||
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3b16f62d5606..e953c6ad6e6d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -5164,6 +5164,15 @@ int bond_create(struct net *net, const char *name) | |||
5164 | res = dev_alloc_name(bond_dev, "bond%d"); | 5164 | res = dev_alloc_name(bond_dev, "bond%d"); |
5165 | if (res < 0) | 5165 | if (res < 0) |
5166 | goto out; | 5166 | goto out; |
5167 | } else { | ||
5168 | /* | ||
5169 | * If we're given a name to register | ||
5170 | * we need to ensure that its not already | ||
5171 | * registered | ||
5172 | */ | ||
5173 | res = -EEXIST; | ||
5174 | if (__dev_get_by_name(net, name) != NULL) | ||
5175 | goto out; | ||
5167 | } | 5176 | } |
5168 | 5177 | ||
5169 | res = register_netdevice(bond_dev); | 5178 | res = register_netdevice(bond_dev); |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index a333b42111b8..6372610ed240 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -533,8 +533,15 @@ static inline void ehea_fill_skb(struct net_device *dev, | |||
533 | int length = cqe->num_bytes_transfered - 4; /*remove CRC */ | 533 | int length = cqe->num_bytes_transfered - 4; /*remove CRC */ |
534 | 534 | ||
535 | skb_put(skb, length); | 535 | skb_put(skb, length); |
536 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
537 | skb->protocol = eth_type_trans(skb, dev); | 536 | skb->protocol = eth_type_trans(skb, dev); |
537 | |||
538 | /* The packet was not an IPV4 packet so a complemented checksum was | ||
539 | calculated. The value is found in the Internet Checksum field. */ | ||
540 | if (cqe->status & EHEA_CQE_BLIND_CKSUM) { | ||
541 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
542 | skb->csum = csum_unfold(~cqe->inet_checksum_value); | ||
543 | } else | ||
544 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
538 | } | 545 | } |
539 | 546 | ||
540 | static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, | 547 | static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, |
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index f608a6c54af5..38104734a3be 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h | |||
@@ -150,6 +150,7 @@ struct ehea_rwqe { | |||
150 | #define EHEA_CQE_TYPE_RQ 0x60 | 150 | #define EHEA_CQE_TYPE_RQ 0x60 |
151 | #define EHEA_CQE_STAT_ERR_MASK 0x700F | 151 | #define EHEA_CQE_STAT_ERR_MASK 0x700F |
152 | #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF | 152 | #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF |
153 | #define EHEA_CQE_BLIND_CKSUM 0x8000 | ||
153 | #define EHEA_CQE_STAT_ERR_TCP 0x4000 | 154 | #define EHEA_CQE_STAT_ERR_TCP 0x4000 |
154 | #define EHEA_CQE_STAT_ERR_IP 0x2000 | 155 | #define EHEA_CQE_STAT_ERR_IP 0x2000 |
155 | #define EHEA_CQE_STAT_ERR_CRC 0x1000 | 156 | #define EHEA_CQE_STAT_ERR_CRC 0x1000 |
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 768b840aeb6b..cce32d43175f 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -678,24 +678,37 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
678 | { | 678 | { |
679 | struct fec_enet_private *fep = netdev_priv(dev); | 679 | struct fec_enet_private *fep = netdev_priv(dev); |
680 | struct phy_device *phy_dev = NULL; | 680 | struct phy_device *phy_dev = NULL; |
681 | int ret; | 681 | char mdio_bus_id[MII_BUS_ID_SIZE]; |
682 | char phy_name[MII_BUS_ID_SIZE + 3]; | ||
683 | int phy_id; | ||
682 | 684 | ||
683 | fep->phy_dev = NULL; | 685 | fep->phy_dev = NULL; |
684 | 686 | ||
685 | /* find the first phy */ | 687 | /* check for attached phy */ |
686 | phy_dev = phy_find_first(fep->mii_bus); | 688 | for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { |
687 | if (!phy_dev) { | 689 | if ((fep->mii_bus->phy_mask & (1 << phy_id))) |
688 | printk(KERN_ERR "%s: no PHY found\n", dev->name); | 690 | continue; |
689 | return -ENODEV; | 691 | if (fep->mii_bus->phy_map[phy_id] == NULL) |
692 | continue; | ||
693 | if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) | ||
694 | continue; | ||
695 | strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); | ||
696 | break; | ||
690 | } | 697 | } |
691 | 698 | ||
692 | /* attach the mac to the phy */ | 699 | if (phy_id >= PHY_MAX_ADDR) { |
693 | ret = phy_connect_direct(dev, phy_dev, | 700 | printk(KERN_INFO "%s: no PHY, assuming direct connection " |
694 | &fec_enet_adjust_link, 0, | 701 | "to switch\n", dev->name); |
695 | PHY_INTERFACE_MODE_MII); | 702 | strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); |
696 | if (ret) { | 703 | phy_id = 0; |
697 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | 704 | } |
698 | return ret; | 705 | |
706 | snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); | ||
707 | phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0, | ||
708 | PHY_INTERFACE_MODE_MII); | ||
709 | if (IS_ERR(phy_dev)) { | ||
710 | printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); | ||
711 | return PTR_ERR(phy_dev); | ||
699 | } | 712 | } |
700 | 713 | ||
701 | /* mask with MAC supported features */ | 714 | /* mask with MAC supported features */ |
@@ -738,7 +751,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
738 | fep->mii_bus->read = fec_enet_mdio_read; | 751 | fep->mii_bus->read = fec_enet_mdio_read; |
739 | fep->mii_bus->write = fec_enet_mdio_write; | 752 | fep->mii_bus->write = fec_enet_mdio_write; |
740 | fep->mii_bus->reset = fec_enet_mdio_reset; | 753 | fep->mii_bus->reset = fec_enet_mdio_reset; |
741 | snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); | 754 | snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); |
742 | fep->mii_bus->priv = fep; | 755 | fep->mii_bus->priv = fep; |
743 | fep->mii_bus->parent = &pdev->dev; | 756 | fep->mii_bus->parent = &pdev->dev; |
744 | 757 | ||
@@ -1311,6 +1324,9 @@ fec_probe(struct platform_device *pdev) | |||
1311 | if (ret) | 1324 | if (ret) |
1312 | goto failed_mii_init; | 1325 | goto failed_mii_init; |
1313 | 1326 | ||
1327 | /* Carrier starts down, phylib will bring it up */ | ||
1328 | netif_carrier_off(ndev); | ||
1329 | |||
1314 | ret = register_netdev(ndev); | 1330 | ret = register_netdev(ndev); |
1315 | if (ret) | 1331 | if (ret) |
1316 | goto failed_register; | 1332 | goto failed_register; |
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 4b52c767ad05..3e5d0b6b6516 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -608,7 +608,7 @@ static int sixpack_open(struct tty_struct *tty) | |||
608 | 608 | ||
609 | spin_lock_init(&sp->lock); | 609 | spin_lock_init(&sp->lock); |
610 | atomic_set(&sp->refcnt, 1); | 610 | atomic_set(&sp->refcnt, 1); |
611 | init_MUTEX_LOCKED(&sp->dead_sem); | 611 | sema_init(&sp->dead_sem, 0); |
612 | 612 | ||
613 | /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */ | 613 | /* !!! length of the buffers. MTU is IP MTU, not PACLEN! */ |
614 | 614 | ||
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 66e88bd59caa..4c628393c8b1 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c | |||
@@ -747,7 +747,7 @@ static int mkiss_open(struct tty_struct *tty) | |||
747 | 747 | ||
748 | spin_lock_init(&ax->buflock); | 748 | spin_lock_init(&ax->buflock); |
749 | atomic_set(&ax->refcnt, 1); | 749 | atomic_set(&ax->refcnt, 1); |
750 | init_MUTEX_LOCKED(&ax->dead_sem); | 750 | sema_init(&ax->dead_sem, 0); |
751 | 751 | ||
752 | ax->tty = tty; | 752 | ax->tty = tty; |
753 | tty->disc_data = ax; | 753 | tty->disc_data = ax; |
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 1b051dab7b29..51d74447f8f8 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c | |||
@@ -909,7 +909,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n | |||
909 | dev->tx_skb = NULL; | 909 | dev->tx_skb = NULL; |
910 | 910 | ||
911 | spin_lock_init(&dev->tx_lock); | 911 | spin_lock_init(&dev->tx_lock); |
912 | init_MUTEX(&dev->fsm.sem); | 912 | sema_init(&dev->fsm.sem, 1); |
913 | 913 | ||
914 | dev->drv = drv; | 914 | dev->drv = drv; |
915 | dev->netdev = ndev; | 915 | dev->netdev = ndev; |
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index c683f77c6f42..ff824e11f0b6 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -87,7 +87,6 @@ earlier 3Com products. | |||
87 | #include <linux/bitops.h> | 87 | #include <linux/bitops.h> |
88 | #include <linux/mii.h> | 88 | #include <linux/mii.h> |
89 | 89 | ||
90 | #include <pcmcia/cs.h> | ||
91 | #include <pcmcia/cistpl.h> | 90 | #include <pcmcia/cistpl.h> |
92 | #include <pcmcia/cisreg.h> | 91 | #include <pcmcia/cisreg.h> |
93 | #include <pcmcia/ciscode.h> | 92 | #include <pcmcia/ciscode.h> |
@@ -280,25 +279,15 @@ static int tc574_probe(struct pcmcia_device *link) | |||
280 | spin_lock_init(&lp->window_lock); | 279 | spin_lock_init(&lp->window_lock); |
281 | link->resource[0]->end = 32; | 280 | link->resource[0]->end = 32; |
282 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | 281 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; |
283 | link->conf.Attributes = CONF_ENABLE_IRQ; | 282 | link->config_flags |= CONF_ENABLE_IRQ; |
284 | link->conf.IntType = INT_MEMORY_AND_IO; | 283 | link->config_index = 1; |
285 | link->conf.ConfigIndex = 1; | ||
286 | 284 | ||
287 | dev->netdev_ops = &el3_netdev_ops; | 285 | dev->netdev_ops = &el3_netdev_ops; |
288 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 286 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
289 | dev->watchdog_timeo = TX_TIMEOUT; | 287 | dev->watchdog_timeo = TX_TIMEOUT; |
290 | 288 | ||
291 | return tc574_config(link); | 289 | return tc574_config(link); |
292 | } /* tc574_attach */ | 290 | } |
293 | |||
294 | /* | ||
295 | |||
296 | This deletes a driver "instance". The device is de-registered | ||
297 | with Card Services. If it has been released, all local data | ||
298 | structures are freed. Otherwise, the structures will be freed | ||
299 | when the device is released. | ||
300 | |||
301 | */ | ||
302 | 291 | ||
303 | static void tc574_detach(struct pcmcia_device *link) | 292 | static void tc574_detach(struct pcmcia_device *link) |
304 | { | 293 | { |
@@ -313,12 +302,6 @@ static void tc574_detach(struct pcmcia_device *link) | |||
313 | free_netdev(dev); | 302 | free_netdev(dev); |
314 | } /* tc574_detach */ | 303 | } /* tc574_detach */ |
315 | 304 | ||
316 | /* | ||
317 | tc574_config() is scheduled to run after a CARD_INSERTION event | ||
318 | is received, to configure the PCMCIA socket, and to make the | ||
319 | ethernet device available to the system. | ||
320 | */ | ||
321 | |||
322 | static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | 305 | static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; |
323 | 306 | ||
324 | static int tc574_config(struct pcmcia_device *link) | 307 | static int tc574_config(struct pcmcia_device *link) |
@@ -352,7 +335,7 @@ static int tc574_config(struct pcmcia_device *link) | |||
352 | if (ret) | 335 | if (ret) |
353 | goto failed; | 336 | goto failed; |
354 | 337 | ||
355 | ret = pcmcia_request_configuration(link, &link->conf); | 338 | ret = pcmcia_enable_device(link); |
356 | if (ret) | 339 | if (ret) |
357 | goto failed; | 340 | goto failed; |
358 | 341 | ||
@@ -465,12 +448,6 @@ failed: | |||
465 | 448 | ||
466 | } /* tc574_config */ | 449 | } /* tc574_config */ |
467 | 450 | ||
468 | /* | ||
469 | After a card is removed, tc574_release() will unregister the net | ||
470 | device, and release the PCMCIA configuration. If the device is | ||
471 | still open, this will be postponed until it is closed. | ||
472 | */ | ||
473 | |||
474 | static void tc574_release(struct pcmcia_device *link) | 451 | static void tc574_release(struct pcmcia_device *link) |
475 | { | 452 | { |
476 | pcmcia_disable_device(link); | 453 | pcmcia_disable_device(link); |
@@ -1198,9 +1175,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc574_ids); | |||
1198 | 1175 | ||
1199 | static struct pcmcia_driver tc574_driver = { | 1176 | static struct pcmcia_driver tc574_driver = { |
1200 | .owner = THIS_MODULE, | 1177 | .owner = THIS_MODULE, |
1201 | .drv = { | 1178 | .name = "3c574_cs", |
1202 | .name = "3c574_cs", | ||
1203 | }, | ||
1204 | .probe = tc574_probe, | 1179 | .probe = tc574_probe, |
1205 | .remove = tc574_detach, | 1180 | .remove = tc574_detach, |
1206 | .id_table = tc574_ids, | 1181 | .id_table = tc574_ids, |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 61f9cf2100ff..a07e22295330 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/bitops.h> | 41 | #include <linux/bitops.h> |
42 | #include <linux/jiffies.h> | 42 | #include <linux/jiffies.h> |
43 | 43 | ||
44 | #include <pcmcia/cs.h> | ||
45 | #include <pcmcia/cistpl.h> | 44 | #include <pcmcia/cistpl.h> |
46 | #include <pcmcia/cisreg.h> | 45 | #include <pcmcia/cisreg.h> |
47 | #include <pcmcia/ciscode.h> | 46 | #include <pcmcia/ciscode.h> |
@@ -176,14 +175,6 @@ static const struct ethtool_ops netdev_ethtool_ops; | |||
176 | 175 | ||
177 | static void tc589_detach(struct pcmcia_device *p_dev); | 176 | static void tc589_detach(struct pcmcia_device *p_dev); |
178 | 177 | ||
179 | /*====================================================================== | ||
180 | |||
181 | tc589_attach() creates an "instance" of the driver, allocating | ||
182 | local data structures for one device. The device is registered | ||
183 | with Card Services. | ||
184 | |||
185 | ======================================================================*/ | ||
186 | |||
187 | static const struct net_device_ops el3_netdev_ops = { | 178 | static const struct net_device_ops el3_netdev_ops = { |
188 | .ndo_open = el3_open, | 179 | .ndo_open = el3_open, |
189 | .ndo_stop = el3_close, | 180 | .ndo_stop = el3_close, |
@@ -216,9 +207,8 @@ static int tc589_probe(struct pcmcia_device *link) | |||
216 | link->resource[0]->end = 16; | 207 | link->resource[0]->end = 16; |
217 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | 208 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; |
218 | 209 | ||
219 | link->conf.Attributes = CONF_ENABLE_IRQ; | 210 | link->config_flags |= CONF_ENABLE_IRQ; |
220 | link->conf.IntType = INT_MEMORY_AND_IO; | 211 | link->config_index = 1; |
221 | link->conf.ConfigIndex = 1; | ||
222 | 212 | ||
223 | dev->netdev_ops = &el3_netdev_ops; | 213 | dev->netdev_ops = &el3_netdev_ops; |
224 | dev->watchdog_timeo = TX_TIMEOUT; | 214 | dev->watchdog_timeo = TX_TIMEOUT; |
@@ -226,16 +216,7 @@ static int tc589_probe(struct pcmcia_device *link) | |||
226 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 216 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
227 | 217 | ||
228 | return tc589_config(link); | 218 | return tc589_config(link); |
229 | } /* tc589_attach */ | 219 | } |
230 | |||
231 | /*====================================================================== | ||
232 | |||
233 | This deletes a driver "instance". The device is de-registered | ||
234 | with Card Services. If it has been released, all local data | ||
235 | structures are freed. Otherwise, the structures will be freed | ||
236 | when the device is released. | ||
237 | |||
238 | ======================================================================*/ | ||
239 | 220 | ||
240 | static void tc589_detach(struct pcmcia_device *link) | 221 | static void tc589_detach(struct pcmcia_device *link) |
241 | { | 222 | { |
@@ -250,14 +231,6 @@ static void tc589_detach(struct pcmcia_device *link) | |||
250 | free_netdev(dev); | 231 | free_netdev(dev); |
251 | } /* tc589_detach */ | 232 | } /* tc589_detach */ |
252 | 233 | ||
253 | /*====================================================================== | ||
254 | |||
255 | tc589_config() is scheduled to run after a CARD_INSERTION event | ||
256 | is received, to configure the PCMCIA socket, and to make the | ||
257 | ethernet device available to the system. | ||
258 | |||
259 | ======================================================================*/ | ||
260 | |||
261 | static int tc589_config(struct pcmcia_device *link) | 234 | static int tc589_config(struct pcmcia_device *link) |
262 | { | 235 | { |
263 | struct net_device *dev = link->priv; | 236 | struct net_device *dev = link->priv; |
@@ -294,7 +267,7 @@ static int tc589_config(struct pcmcia_device *link) | |||
294 | if (ret) | 267 | if (ret) |
295 | goto failed; | 268 | goto failed; |
296 | 269 | ||
297 | ret = pcmcia_request_configuration(link, &link->conf); | 270 | ret = pcmcia_enable_device(link); |
298 | if (ret) | 271 | if (ret) |
299 | goto failed; | 272 | goto failed; |
300 | 273 | ||
@@ -352,14 +325,6 @@ failed: | |||
352 | return -ENODEV; | 325 | return -ENODEV; |
353 | } /* tc589_config */ | 326 | } /* tc589_config */ |
354 | 327 | ||
355 | /*====================================================================== | ||
356 | |||
357 | After a card is removed, tc589_release() will unregister the net | ||
358 | device, and release the PCMCIA configuration. If the device is | ||
359 | still open, this will be postponed until it is closed. | ||
360 | |||
361 | ======================================================================*/ | ||
362 | |||
363 | static void tc589_release(struct pcmcia_device *link) | 328 | static void tc589_release(struct pcmcia_device *link) |
364 | { | 329 | { |
365 | pcmcia_disable_device(link); | 330 | pcmcia_disable_device(link); |
@@ -955,9 +920,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc589_ids); | |||
955 | 920 | ||
956 | static struct pcmcia_driver tc589_driver = { | 921 | static struct pcmcia_driver tc589_driver = { |
957 | .owner = THIS_MODULE, | 922 | .owner = THIS_MODULE, |
958 | .drv = { | 923 | .name = "3c589_cs", |
959 | .name = "3c589_cs", | ||
960 | }, | ||
961 | .probe = tc589_probe, | 924 | .probe = tc589_probe, |
962 | .remove = tc589_detach, | 925 | .remove = tc589_detach, |
963 | .id_table = tc589_ids, | 926 | .id_table = tc589_ids, |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 5f05ffb240cc..9e8b28b271ae 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/mii.h> | 39 | #include <linux/mii.h> |
40 | #include "../8390.h" | 40 | #include "../8390.h" |
41 | 41 | ||
42 | #include <pcmcia/cs.h> | ||
43 | #include <pcmcia/cistpl.h> | 42 | #include <pcmcia/cistpl.h> |
44 | #include <pcmcia/ciscode.h> | 43 | #include <pcmcia/ciscode.h> |
45 | #include <pcmcia/ds.h> | 44 | #include <pcmcia/ds.h> |
@@ -140,14 +139,6 @@ static const struct net_device_ops axnet_netdev_ops = { | |||
140 | .ndo_validate_addr = eth_validate_addr, | 139 | .ndo_validate_addr = eth_validate_addr, |
141 | }; | 140 | }; |
142 | 141 | ||
143 | /*====================================================================== | ||
144 | |||
145 | axnet_attach() creates an "instance" of the driver, allocating | ||
146 | local data structures for one device. The device is registered | ||
147 | with Card Services. | ||
148 | |||
149 | ======================================================================*/ | ||
150 | |||
151 | static int axnet_probe(struct pcmcia_device *link) | 142 | static int axnet_probe(struct pcmcia_device *link) |
152 | { | 143 | { |
153 | axnet_dev_t *info; | 144 | axnet_dev_t *info; |
@@ -166,8 +157,7 @@ static int axnet_probe(struct pcmcia_device *link) | |||
166 | info = PRIV(dev); | 157 | info = PRIV(dev); |
167 | info->p_dev = link; | 158 | info->p_dev = link; |
168 | link->priv = dev; | 159 | link->priv = dev; |
169 | link->conf.Attributes = CONF_ENABLE_IRQ; | 160 | link->config_flags |= CONF_ENABLE_IRQ; |
170 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
171 | 161 | ||
172 | dev->netdev_ops = &axnet_netdev_ops; | 162 | dev->netdev_ops = &axnet_netdev_ops; |
173 | 163 | ||
@@ -177,15 +167,6 @@ static int axnet_probe(struct pcmcia_device *link) | |||
177 | return axnet_config(link); | 167 | return axnet_config(link); |
178 | } /* axnet_attach */ | 168 | } /* axnet_attach */ |
179 | 169 | ||
180 | /*====================================================================== | ||
181 | |||
182 | This deletes a driver "instance". The device is de-registered | ||
183 | with Card Services. If it has been released, all local data | ||
184 | structures are freed. Otherwise, the structures will be freed | ||
185 | when the device is released. | ||
186 | |||
187 | ======================================================================*/ | ||
188 | |||
189 | static void axnet_detach(struct pcmcia_device *link) | 170 | static void axnet_detach(struct pcmcia_device *link) |
190 | { | 171 | { |
191 | struct net_device *dev = link->priv; | 172 | struct net_device *dev = link->priv; |
@@ -231,7 +212,7 @@ static int get_prom(struct pcmcia_device *link) | |||
231 | }; | 212 | }; |
232 | 213 | ||
233 | /* Not much of a test, but the alternatives are messy */ | 214 | /* Not much of a test, but the alternatives are messy */ |
234 | if (link->conf.ConfigBase != 0x03c0) | 215 | if (link->config_base != 0x03c0) |
235 | return 0; | 216 | return 0; |
236 | 217 | ||
237 | axnet_reset_8390(dev); | 218 | axnet_reset_8390(dev); |
@@ -248,14 +229,6 @@ static int get_prom(struct pcmcia_device *link) | |||
248 | return 1; | 229 | return 1; |
249 | } /* get_prom */ | 230 | } /* get_prom */ |
250 | 231 | ||
251 | /*====================================================================== | ||
252 | |||
253 | axnet_config() is scheduled to run after a CARD_INSERTION event | ||
254 | is received, to configure the PCMCIA socket, and to make the | ||
255 | ethernet device available to the system. | ||
256 | |||
257 | ======================================================================*/ | ||
258 | |||
259 | static int try_io_port(struct pcmcia_device *link) | 232 | static int try_io_port(struct pcmcia_device *link) |
260 | { | 233 | { |
261 | int j, ret; | 234 | int j, ret; |
@@ -286,35 +259,16 @@ static int try_io_port(struct pcmcia_device *link) | |||
286 | } | 259 | } |
287 | } | 260 | } |
288 | 261 | ||
289 | static int axnet_configcheck(struct pcmcia_device *p_dev, | 262 | static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
290 | cistpl_cftable_entry_t *cfg, | ||
291 | cistpl_cftable_entry_t *dflt, | ||
292 | unsigned int vcc, | ||
293 | void *priv_data) | ||
294 | { | 263 | { |
295 | int i; | 264 | if (p_dev->config_index == 0) |
296 | cistpl_io_t *io = &cfg->io; | 265 | return -EINVAL; |
297 | 266 | ||
298 | if (cfg->index == 0 || cfg->io.nwin == 0) | 267 | p_dev->config_index = 0x05; |
268 | if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32) | ||
299 | return -ENODEV; | 269 | return -ENODEV; |
300 | 270 | ||
301 | p_dev->conf.ConfigIndex = 0x05; | 271 | return try_io_port(p_dev); |
302 | /* For multifunction cards, by convention, we configure the | ||
303 | network function with window 0, and serial with window 1 */ | ||
304 | if (io->nwin > 1) { | ||
305 | i = (io->win[1].len > io->win[0].len); | ||
306 | p_dev->resource[1]->start = io->win[1-i].base; | ||
307 | p_dev->resource[1]->end = io->win[1-i].len; | ||
308 | } else { | ||
309 | i = p_dev->resource[1]->end = 0; | ||
310 | } | ||
311 | p_dev->resource[0]->start = io->win[i].base; | ||
312 | p_dev->resource[0]->end = io->win[i].len; | ||
313 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
314 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) | ||
315 | return try_io_port(p_dev); | ||
316 | |||
317 | return -ENODEV; | ||
318 | } | 272 | } |
319 | 273 | ||
320 | static int axnet_config(struct pcmcia_device *link) | 274 | static int axnet_config(struct pcmcia_device *link) |
@@ -326,20 +280,19 @@ static int axnet_config(struct pcmcia_device *link) | |||
326 | dev_dbg(&link->dev, "axnet_config(0x%p)\n", link); | 280 | dev_dbg(&link->dev, "axnet_config(0x%p)\n", link); |
327 | 281 | ||
328 | /* don't trust the CIS on this; Linksys got it wrong */ | 282 | /* don't trust the CIS on this; Linksys got it wrong */ |
329 | link->conf.Present = 0x63; | 283 | link->config_regs = 0x63; |
284 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
330 | ret = pcmcia_loop_config(link, axnet_configcheck, NULL); | 285 | ret = pcmcia_loop_config(link, axnet_configcheck, NULL); |
331 | if (ret != 0) | 286 | if (ret != 0) |
332 | goto failed; | 287 | goto failed; |
333 | 288 | ||
334 | if (!link->irq) | 289 | if (!link->irq) |
335 | goto failed; | 290 | goto failed; |
291 | |||
292 | if (resource_size(link->resource[1]) == 8) | ||
293 | link->config_flags |= CONF_ENABLE_SPKR; | ||
336 | 294 | ||
337 | if (resource_size(link->resource[1]) == 8) { | 295 | ret = pcmcia_enable_device(link); |
338 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
339 | link->conf.Status = CCSR_AUDIO_ENA; | ||
340 | } | ||
341 | |||
342 | ret = pcmcia_request_configuration(link, &link->conf); | ||
343 | if (ret) | 296 | if (ret) |
344 | goto failed; | 297 | goto failed; |
345 | 298 | ||
@@ -414,14 +367,6 @@ failed: | |||
414 | return -ENODEV; | 367 | return -ENODEV; |
415 | } /* axnet_config */ | 368 | } /* axnet_config */ |
416 | 369 | ||
417 | /*====================================================================== | ||
418 | |||
419 | After a card is removed, axnet_release() will unregister the net | ||
420 | device, and release the PCMCIA configuration. If the device is | ||
421 | still open, this will be postponed until it is closed. | ||
422 | |||
423 | ======================================================================*/ | ||
424 | |||
425 | static void axnet_release(struct pcmcia_device *link) | 370 | static void axnet_release(struct pcmcia_device *link) |
426 | { | 371 | { |
427 | pcmcia_disable_device(link); | 372 | pcmcia_disable_device(link); |
@@ -783,9 +728,7 @@ MODULE_DEVICE_TABLE(pcmcia, axnet_ids); | |||
783 | 728 | ||
784 | static struct pcmcia_driver axnet_cs_driver = { | 729 | static struct pcmcia_driver axnet_cs_driver = { |
785 | .owner = THIS_MODULE, | 730 | .owner = THIS_MODULE, |
786 | .drv = { | 731 | .name = "axnet_cs", |
787 | .name = "axnet_cs", | ||
788 | }, | ||
789 | .probe = axnet_probe, | 732 | .probe = axnet_probe, |
790 | .remove = axnet_detach, | 733 | .remove = axnet_detach, |
791 | .id_table = axnet_ids, | 734 | .id_table = axnet_ids, |
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 3c400cfa82ae..b706a7249477 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/arcdevice.h> | 43 | #include <linux/arcdevice.h> |
44 | #include <linux/com20020.h> | 44 | #include <linux/com20020.h> |
45 | 45 | ||
46 | #include <pcmcia/cs.h> | ||
47 | #include <pcmcia/cistpl.h> | 46 | #include <pcmcia/cistpl.h> |
48 | #include <pcmcia/ds.h> | 47 | #include <pcmcia/ds.h> |
49 | 48 | ||
@@ -123,14 +122,6 @@ typedef struct com20020_dev_t { | |||
123 | struct net_device *dev; | 122 | struct net_device *dev; |
124 | } com20020_dev_t; | 123 | } com20020_dev_t; |
125 | 124 | ||
126 | /*====================================================================== | ||
127 | |||
128 | com20020_attach() creates an "instance" of the driver, allocating | ||
129 | local data structures for one device. The device is registered | ||
130 | with Card Services. | ||
131 | |||
132 | ======================================================================*/ | ||
133 | |||
134 | static int com20020_probe(struct pcmcia_device *p_dev) | 125 | static int com20020_probe(struct pcmcia_device *p_dev) |
135 | { | 126 | { |
136 | com20020_dev_t *info; | 127 | com20020_dev_t *info; |
@@ -160,8 +151,7 @@ static int com20020_probe(struct pcmcia_device *p_dev) | |||
160 | 151 | ||
161 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 152 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
162 | p_dev->resource[0]->end = 16; | 153 | p_dev->resource[0]->end = 16; |
163 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 154 | p_dev->config_flags |= CONF_ENABLE_IRQ; |
164 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
165 | 155 | ||
166 | info->dev = dev; | 156 | info->dev = dev; |
167 | p_dev->priv = info; | 157 | p_dev->priv = info; |
@@ -174,15 +164,6 @@ fail_alloc_info: | |||
174 | return -ENOMEM; | 164 | return -ENOMEM; |
175 | } /* com20020_attach */ | 165 | } /* com20020_attach */ |
176 | 166 | ||
177 | /*====================================================================== | ||
178 | |||
179 | This deletes a driver "instance". The device is de-registered | ||
180 | with Card Services. If it has been released, all local data | ||
181 | structures are freed. Otherwise, the structures will be freed | ||
182 | when the device is released. | ||
183 | |||
184 | ======================================================================*/ | ||
185 | |||
186 | static void com20020_detach(struct pcmcia_device *link) | 167 | static void com20020_detach(struct pcmcia_device *link) |
187 | { | 168 | { |
188 | struct com20020_dev_t *info = link->priv; | 169 | struct com20020_dev_t *info = link->priv; |
@@ -221,14 +202,6 @@ static void com20020_detach(struct pcmcia_device *link) | |||
221 | 202 | ||
222 | } /* com20020_detach */ | 203 | } /* com20020_detach */ |
223 | 204 | ||
224 | /*====================================================================== | ||
225 | |||
226 | com20020_config() is scheduled to run after a CARD_INSERTION event | ||
227 | is received, to configure the PCMCIA socket, and to make the | ||
228 | device available to the system. | ||
229 | |||
230 | ======================================================================*/ | ||
231 | |||
232 | static int com20020_config(struct pcmcia_device *link) | 205 | static int com20020_config(struct pcmcia_device *link) |
233 | { | 206 | { |
234 | struct arcnet_local *lp; | 207 | struct arcnet_local *lp; |
@@ -282,7 +255,7 @@ static int com20020_config(struct pcmcia_device *link) | |||
282 | 255 | ||
283 | dev->irq = link->irq; | 256 | dev->irq = link->irq; |
284 | 257 | ||
285 | ret = pcmcia_request_configuration(link, &link->conf); | 258 | ret = pcmcia_enable_device(link); |
286 | if (ret) | 259 | if (ret) |
287 | goto failed; | 260 | goto failed; |
288 | 261 | ||
@@ -316,14 +289,6 @@ failed: | |||
316 | return -ENODEV; | 289 | return -ENODEV; |
317 | } /* com20020_config */ | 290 | } /* com20020_config */ |
318 | 291 | ||
319 | /*====================================================================== | ||
320 | |||
321 | After a card is removed, com20020_release() will unregister the net | ||
322 | device, and release the PCMCIA configuration. If the device is | ||
323 | still open, this will be postponed until it is closed. | ||
324 | |||
325 | ======================================================================*/ | ||
326 | |||
327 | static void com20020_release(struct pcmcia_device *link) | 292 | static void com20020_release(struct pcmcia_device *link) |
328 | { | 293 | { |
329 | dev_dbg(&link->dev, "com20020_release\n"); | 294 | dev_dbg(&link->dev, "com20020_release\n"); |
@@ -366,9 +331,7 @@ MODULE_DEVICE_TABLE(pcmcia, com20020_ids); | |||
366 | 331 | ||
367 | static struct pcmcia_driver com20020_cs_driver = { | 332 | static struct pcmcia_driver com20020_cs_driver = { |
368 | .owner = THIS_MODULE, | 333 | .owner = THIS_MODULE, |
369 | .drv = { | 334 | .name = "com20020_cs", |
370 | .name = "com20020_cs", | ||
371 | }, | ||
372 | .probe = com20020_probe, | 335 | .probe = com20020_probe, |
373 | .remove = com20020_detach, | 336 | .remove = com20020_detach, |
374 | .id_table = com20020_ids, | 337 | .id_table = com20020_ids, |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 98fffb03ecd7..1c327598bbe8 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/ioport.h> | 49 | #include <linux/ioport.h> |
50 | #include <linux/crc32.h> | 50 | #include <linux/crc32.h> |
51 | 51 | ||
52 | #include <pcmcia/cs.h> | ||
53 | #include <pcmcia/cistpl.h> | 52 | #include <pcmcia/cistpl.h> |
54 | #include <pcmcia/ciscode.h> | 53 | #include <pcmcia/ciscode.h> |
55 | #include <pcmcia/ds.h> | 54 | #include <pcmcia/ds.h> |
@@ -252,8 +251,7 @@ static int fmvj18x_probe(struct pcmcia_device *link) | |||
252 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 251 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
253 | 252 | ||
254 | /* General socket configuration */ | 253 | /* General socket configuration */ |
255 | link->conf.Attributes = CONF_ENABLE_IRQ; | 254 | link->config_flags |= CONF_ENABLE_IRQ; |
256 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
257 | 255 | ||
258 | dev->netdev_ops = &fjn_netdev_ops; | 256 | dev->netdev_ops = &fjn_netdev_ops; |
259 | dev->watchdog_timeo = TX_TIMEOUT; | 257 | dev->watchdog_timeo = TX_TIMEOUT; |
@@ -313,7 +311,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link) | |||
313 | ret = pcmcia_request_io(link); | 311 | ret = pcmcia_request_io(link); |
314 | if (ret == 0) { | 312 | if (ret == 0) { |
315 | /* calculate ConfigIndex value */ | 313 | /* calculate ConfigIndex value */ |
316 | link->conf.ConfigIndex = | 314 | link->config_index = |
317 | ((link->resource[0]->start & 0x0f0) >> 3) | 0x22; | 315 | ((link->resource[0]->start & 0x0f0) >> 3) | 0x22; |
318 | return ret; | 316 | return ret; |
319 | } | 317 | } |
@@ -321,11 +319,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link) | |||
321 | return ret; /* RequestIO failed */ | 319 | return ret; /* RequestIO failed */ |
322 | } | 320 | } |
323 | 321 | ||
324 | static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, | 322 | static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data) |
325 | cistpl_cftable_entry_t *cfg, | ||
326 | cistpl_cftable_entry_t *dflt, | ||
327 | unsigned int vcc, | ||
328 | void *priv_data) | ||
329 | { | 323 | { |
330 | return 0; /* strange, but that's what the code did already before... */ | 324 | return 0; /* strange, but that's what the code did already before... */ |
331 | } | 325 | } |
@@ -362,28 +356,28 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
362 | link->card_id == PRODID_TDK_NP9610 || | 356 | link->card_id == PRODID_TDK_NP9610 || |
363 | link->card_id == PRODID_TDK_MN3200) { | 357 | link->card_id == PRODID_TDK_MN3200) { |
364 | /* MultiFunction Card */ | 358 | /* MultiFunction Card */ |
365 | link->conf.ConfigBase = 0x800; | 359 | link->config_base = 0x800; |
366 | link->conf.ConfigIndex = 0x47; | 360 | link->config_index = 0x47; |
367 | link->resource[1]->end = 8; | 361 | link->resource[1]->end = 8; |
368 | } | 362 | } |
369 | break; | 363 | break; |
370 | case MANFID_NEC: | 364 | case MANFID_NEC: |
371 | cardtype = NEC; /* MultiFunction Card */ | 365 | cardtype = NEC; /* MultiFunction Card */ |
372 | link->conf.ConfigBase = 0x800; | 366 | link->config_base = 0x800; |
373 | link->conf.ConfigIndex = 0x47; | 367 | link->config_index = 0x47; |
374 | link->resource[1]->end = 8; | 368 | link->resource[1]->end = 8; |
375 | break; | 369 | break; |
376 | case MANFID_KME: | 370 | case MANFID_KME: |
377 | cardtype = KME; /* MultiFunction Card */ | 371 | cardtype = KME; /* MultiFunction Card */ |
378 | link->conf.ConfigBase = 0x800; | 372 | link->config_base = 0x800; |
379 | link->conf.ConfigIndex = 0x47; | 373 | link->config_index = 0x47; |
380 | link->resource[1]->end = 8; | 374 | link->resource[1]->end = 8; |
381 | break; | 375 | break; |
382 | case MANFID_CONTEC: | 376 | case MANFID_CONTEC: |
383 | cardtype = CONTEC; | 377 | cardtype = CONTEC; |
384 | break; | 378 | break; |
385 | case MANFID_FUJITSU: | 379 | case MANFID_FUJITSU: |
386 | if (link->conf.ConfigBase == 0x0fe0) | 380 | if (link->config_base == 0x0fe0) |
387 | cardtype = MBH10302; | 381 | cardtype = MBH10302; |
388 | else if (link->card_id == PRODID_FUJITSU_MBH10302) | 382 | else if (link->card_id == PRODID_FUJITSU_MBH10302) |
389 | /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), | 383 | /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), |
@@ -403,10 +397,10 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
403 | case MANFID_FUJITSU: | 397 | case MANFID_FUJITSU: |
404 | if (link->card_id == PRODID_FUJITSU_MBH10304) { | 398 | if (link->card_id == PRODID_FUJITSU_MBH10304) { |
405 | cardtype = XXX10304; /* MBH10304 with buggy CIS */ | 399 | cardtype = XXX10304; /* MBH10304 with buggy CIS */ |
406 | link->conf.ConfigIndex = 0x20; | 400 | link->config_index = 0x20; |
407 | } else { | 401 | } else { |
408 | cardtype = MBH10302; /* NextCom NC5310, etc. */ | 402 | cardtype = MBH10302; /* NextCom NC5310, etc. */ |
409 | link->conf.ConfigIndex = 1; | 403 | link->config_index = 1; |
410 | } | 404 | } |
411 | break; | 405 | break; |
412 | case MANFID_UNGERMANN: | 406 | case MANFID_UNGERMANN: |
@@ -414,7 +408,7 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
414 | break; | 408 | break; |
415 | default: | 409 | default: |
416 | cardtype = MBH10302; | 410 | cardtype = MBH10302; |
417 | link->conf.ConfigIndex = 1; | 411 | link->config_index = 1; |
418 | } | 412 | } |
419 | } | 413 | } |
420 | 414 | ||
@@ -432,7 +426,7 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
432 | ret = pcmcia_request_irq(link, fjn_interrupt); | 426 | ret = pcmcia_request_irq(link, fjn_interrupt); |
433 | if (ret) | 427 | if (ret) |
434 | goto failed; | 428 | goto failed; |
435 | ret = pcmcia_request_configuration(link, &link->conf); | 429 | ret = pcmcia_enable_device(link); |
436 | if (ret) | 430 | if (ret) |
437 | goto failed; | 431 | goto failed; |
438 | 432 | ||
@@ -544,20 +538,18 @@ failed: | |||
544 | 538 | ||
545 | static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) | 539 | static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) |
546 | { | 540 | { |
547 | win_req_t req; | ||
548 | u_char __iomem *base; | 541 | u_char __iomem *base; |
549 | int i, j; | 542 | int i, j; |
550 | 543 | ||
551 | /* Allocate a small memory window */ | 544 | /* Allocate a small memory window */ |
552 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 545 | link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
553 | req.Base = 0; req.Size = 0; | 546 | link->resource[2]->start = 0; link->resource[2]->end = 0; |
554 | req.AccessSpeed = 0; | 547 | i = pcmcia_request_window(link, link->resource[2], 0); |
555 | i = pcmcia_request_window(link, &req, &link->win); | ||
556 | if (i != 0) | 548 | if (i != 0) |
557 | return -1; | 549 | return -1; |
558 | 550 | ||
559 | base = ioremap(req.Base, req.Size); | 551 | base = ioremap(link->resource[2]->start, resource_size(link->resource[2])); |
560 | pcmcia_map_mem_page(link, link->win, 0); | 552 | pcmcia_map_mem_page(link, link->resource[2], 0); |
561 | 553 | ||
562 | /* | 554 | /* |
563 | * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format | 555 | * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format |
@@ -582,7 +574,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) | |||
582 | } | 574 | } |
583 | 575 | ||
584 | iounmap(base); | 576 | iounmap(base); |
585 | j = pcmcia_release_window(link, link->win); | 577 | j = pcmcia_release_window(link, link->resource[2]); |
586 | return (i != 0x200) ? 0 : -1; | 578 | return (i != 0x200) ? 0 : -1; |
587 | 579 | ||
588 | } /* fmvj18x_get_hwinfo */ | 580 | } /* fmvj18x_get_hwinfo */ |
@@ -590,27 +582,26 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) | |||
590 | 582 | ||
591 | static int fmvj18x_setup_mfc(struct pcmcia_device *link) | 583 | static int fmvj18x_setup_mfc(struct pcmcia_device *link) |
592 | { | 584 | { |
593 | win_req_t req; | ||
594 | int i; | 585 | int i; |
595 | struct net_device *dev = link->priv; | 586 | struct net_device *dev = link->priv; |
596 | unsigned int ioaddr; | 587 | unsigned int ioaddr; |
597 | local_info_t *lp = netdev_priv(dev); | 588 | local_info_t *lp = netdev_priv(dev); |
598 | 589 | ||
599 | /* Allocate a small memory window */ | 590 | /* Allocate a small memory window */ |
600 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 591 | link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
601 | req.Base = 0; req.Size = 0; | 592 | link->resource[3]->start = link->resource[3]->end = 0; |
602 | req.AccessSpeed = 0; | 593 | i = pcmcia_request_window(link, link->resource[3], 0); |
603 | i = pcmcia_request_window(link, &req, &link->win); | ||
604 | if (i != 0) | 594 | if (i != 0) |
605 | return -1; | 595 | return -1; |
606 | 596 | ||
607 | lp->base = ioremap(req.Base, req.Size); | 597 | lp->base = ioremap(link->resource[3]->start, |
598 | resource_size(link->resource[3])); | ||
608 | if (lp->base == NULL) { | 599 | if (lp->base == NULL) { |
609 | printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n"); | 600 | printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n"); |
610 | return -1; | 601 | return -1; |
611 | } | 602 | } |
612 | 603 | ||
613 | i = pcmcia_map_mem_page(link, link->win, 0); | 604 | i = pcmcia_map_mem_page(link, link->resource[3], 0); |
614 | if (i != 0) { | 605 | if (i != 0) { |
615 | iounmap(lp->base); | 606 | iounmap(lp->base); |
616 | lp->base = NULL; | 607 | lp->base = NULL; |
@@ -638,7 +629,6 @@ static void fmvj18x_release(struct pcmcia_device *link) | |||
638 | struct net_device *dev = link->priv; | 629 | struct net_device *dev = link->priv; |
639 | local_info_t *lp = netdev_priv(dev); | 630 | local_info_t *lp = netdev_priv(dev); |
640 | u_char __iomem *tmp; | 631 | u_char __iomem *tmp; |
641 | int j; | ||
642 | 632 | ||
643 | dev_dbg(&link->dev, "fmvj18x_release\n"); | 633 | dev_dbg(&link->dev, "fmvj18x_release\n"); |
644 | 634 | ||
@@ -646,7 +636,6 @@ static void fmvj18x_release(struct pcmcia_device *link) | |||
646 | tmp = lp->base; | 636 | tmp = lp->base; |
647 | lp->base = NULL; /* set NULL before iounmap */ | 637 | lp->base = NULL; /* set NULL before iounmap */ |
648 | iounmap(tmp); | 638 | iounmap(tmp); |
649 | j = pcmcia_release_window(link, link->win); | ||
650 | } | 639 | } |
651 | 640 | ||
652 | pcmcia_disable_device(link); | 641 | pcmcia_disable_device(link); |
@@ -708,9 +697,7 @@ MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); | |||
708 | 697 | ||
709 | static struct pcmcia_driver fmvj18x_cs_driver = { | 698 | static struct pcmcia_driver fmvj18x_cs_driver = { |
710 | .owner = THIS_MODULE, | 699 | .owner = THIS_MODULE, |
711 | .drv = { | 700 | .name = "fmvj18x_cs", |
712 | .name = "fmvj18x_cs", | ||
713 | }, | ||
714 | .probe = fmvj18x_probe, | 701 | .probe = fmvj18x_probe, |
715 | .remove = fmvj18x_detach, | 702 | .remove = fmvj18x_detach, |
716 | .id_table = fmvj18x_ids, | 703 | .id_table = fmvj18x_ids, |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b0d06a3d962f..bf7dff96d881 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -57,7 +57,6 @@ | |||
57 | #include <linux/trdevice.h> | 57 | #include <linux/trdevice.h> |
58 | #include <linux/ibmtr.h> | 58 | #include <linux/ibmtr.h> |
59 | 59 | ||
60 | #include <pcmcia/cs.h> | ||
61 | #include <pcmcia/cistpl.h> | 60 | #include <pcmcia/cistpl.h> |
62 | #include <pcmcia/ds.h> | 61 | #include <pcmcia/ds.h> |
63 | 62 | ||
@@ -102,9 +101,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev); | |||
102 | 101 | ||
103 | typedef struct ibmtr_dev_t { | 102 | typedef struct ibmtr_dev_t { |
104 | struct pcmcia_device *p_dev; | 103 | struct pcmcia_device *p_dev; |
105 | struct net_device *dev; | 104 | struct net_device *dev; |
106 | window_handle_t sram_win_handle; | 105 | struct tok_info *ti; |
107 | struct tok_info *ti; | ||
108 | } ibmtr_dev_t; | 106 | } ibmtr_dev_t; |
109 | 107 | ||
110 | static void netdev_get_drvinfo(struct net_device *dev, | 108 | static void netdev_get_drvinfo(struct net_device *dev, |
@@ -123,14 +121,6 @@ static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) { | |||
123 | return tok_interrupt(irq, dev); | 121 | return tok_interrupt(irq, dev); |
124 | }; | 122 | }; |
125 | 123 | ||
126 | /*====================================================================== | ||
127 | |||
128 | ibmtr_attach() creates an "instance" of the driver, allocating | ||
129 | local data structures for one device. The device is registered | ||
130 | with Card Services. | ||
131 | |||
132 | ======================================================================*/ | ||
133 | |||
134 | static int __devinit ibmtr_attach(struct pcmcia_device *link) | 124 | static int __devinit ibmtr_attach(struct pcmcia_device *link) |
135 | { | 125 | { |
136 | ibmtr_dev_t *info; | 126 | ibmtr_dev_t *info; |
@@ -153,9 +143,8 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link) | |||
153 | 143 | ||
154 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 144 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
155 | link->resource[0]->end = 4; | 145 | link->resource[0]->end = 4; |
156 | link->conf.Attributes = CONF_ENABLE_IRQ; | 146 | link->config_flags |= CONF_ENABLE_IRQ; |
157 | link->conf.IntType = INT_MEMORY_AND_IO; | 147 | link->config_regs = PRESENT_OPTION; |
158 | link->conf.Present = PRESENT_OPTION; | ||
159 | 148 | ||
160 | info->dev = dev; | 149 | info->dev = dev; |
161 | 150 | ||
@@ -164,15 +153,6 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link) | |||
164 | return ibmtr_config(link); | 153 | return ibmtr_config(link); |
165 | } /* ibmtr_attach */ | 154 | } /* ibmtr_attach */ |
166 | 155 | ||
167 | /*====================================================================== | ||
168 | |||
169 | This deletes a driver "instance". The device is de-registered | ||
170 | with Card Services. If it has been released, all local data | ||
171 | structures are freed. Otherwise, the structures will be freed | ||
172 | when the device is released. | ||
173 | |||
174 | ======================================================================*/ | ||
175 | |||
176 | static void ibmtr_detach(struct pcmcia_device *link) | 156 | static void ibmtr_detach(struct pcmcia_device *link) |
177 | { | 157 | { |
178 | struct ibmtr_dev_t *info = link->priv; | 158 | struct ibmtr_dev_t *info = link->priv; |
@@ -197,26 +177,17 @@ static void ibmtr_detach(struct pcmcia_device *link) | |||
197 | kfree(info); | 177 | kfree(info); |
198 | } /* ibmtr_detach */ | 178 | } /* ibmtr_detach */ |
199 | 179 | ||
200 | /*====================================================================== | ||
201 | |||
202 | ibmtr_config() is scheduled to run after a CARD_INSERTION event | ||
203 | is received, to configure the PCMCIA socket, and to make the | ||
204 | token-ring device available to the system. | ||
205 | |||
206 | ======================================================================*/ | ||
207 | |||
208 | static int __devinit ibmtr_config(struct pcmcia_device *link) | 180 | static int __devinit ibmtr_config(struct pcmcia_device *link) |
209 | { | 181 | { |
210 | ibmtr_dev_t *info = link->priv; | 182 | ibmtr_dev_t *info = link->priv; |
211 | struct net_device *dev = info->dev; | 183 | struct net_device *dev = info->dev; |
212 | struct tok_info *ti = netdev_priv(dev); | 184 | struct tok_info *ti = netdev_priv(dev); |
213 | win_req_t req; | ||
214 | int i, ret; | 185 | int i, ret; |
215 | 186 | ||
216 | dev_dbg(&link->dev, "ibmtr_config\n"); | 187 | dev_dbg(&link->dev, "ibmtr_config\n"); |
217 | 188 | ||
218 | link->conf.ConfigIndex = 0x61; | ||
219 | link->io_lines = 16; | 189 | link->io_lines = 16; |
190 | link->config_index = 0x61; | ||
220 | 191 | ||
221 | /* Determine if this is PRIMARY or ALTERNATE. */ | 192 | /* Determine if this is PRIMARY or ALTERNATE. */ |
222 | 193 | ||
@@ -240,39 +211,39 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) | |||
240 | ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); | 211 | ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); |
241 | 212 | ||
242 | /* Allocate the MMIO memory window */ | 213 | /* Allocate the MMIO memory window */ |
243 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | 214 | link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; |
244 | req.Attributes |= WIN_USE_WAIT; | 215 | link->resource[2]->flags |= WIN_USE_WAIT; |
245 | req.Base = 0; | 216 | link->resource[2]->start = 0; |
246 | req.Size = 0x2000; | 217 | link->resource[2]->end = 0x2000; |
247 | req.AccessSpeed = 250; | 218 | ret = pcmcia_request_window(link, link->resource[2], 250); |
248 | ret = pcmcia_request_window(link, &req, &link->win); | ||
249 | if (ret) | 219 | if (ret) |
250 | goto failed; | 220 | goto failed; |
251 | 221 | ||
252 | ret = pcmcia_map_mem_page(link, link->win, mmiobase); | 222 | ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase); |
253 | if (ret) | 223 | if (ret) |
254 | goto failed; | 224 | goto failed; |
255 | ti->mmio = ioremap(req.Base, req.Size); | 225 | ti->mmio = ioremap(link->resource[2]->start, |
226 | resource_size(link->resource[2])); | ||
256 | 227 | ||
257 | /* Allocate the SRAM memory window */ | 228 | /* Allocate the SRAM memory window */ |
258 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | 229 | link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; |
259 | req.Attributes |= WIN_USE_WAIT; | 230 | link->resource[3]->flags |= WIN_USE_WAIT; |
260 | req.Base = 0; | 231 | link->resource[3]->start = 0; |
261 | req.Size = sramsize * 1024; | 232 | link->resource[3]->end = sramsize * 1024; |
262 | req.AccessSpeed = 250; | 233 | ret = pcmcia_request_window(link, link->resource[3], 250); |
263 | ret = pcmcia_request_window(link, &req, &info->sram_win_handle); | ||
264 | if (ret) | 234 | if (ret) |
265 | goto failed; | 235 | goto failed; |
266 | 236 | ||
267 | ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase); | 237 | ret = pcmcia_map_mem_page(link, link->resource[3], srambase); |
268 | if (ret) | 238 | if (ret) |
269 | goto failed; | 239 | goto failed; |
270 | 240 | ||
271 | ti->sram_base = srambase >> 12; | 241 | ti->sram_base = srambase >> 12; |
272 | ti->sram_virt = ioremap(req.Base, req.Size); | 242 | ti->sram_virt = ioremap(link->resource[3]->start, |
273 | ti->sram_phys = req.Base; | 243 | resource_size(link->resource[3])); |
244 | ti->sram_phys = link->resource[3]->start; | ||
274 | 245 | ||
275 | ret = pcmcia_request_configuration(link, &link->conf); | 246 | ret = pcmcia_enable_device(link); |
276 | if (ret) | 247 | if (ret) |
277 | goto failed; | 248 | goto failed; |
278 | 249 | ||
@@ -301,14 +272,6 @@ failed: | |||
301 | return -ENODEV; | 272 | return -ENODEV; |
302 | } /* ibmtr_config */ | 273 | } /* ibmtr_config */ |
303 | 274 | ||
304 | /*====================================================================== | ||
305 | |||
306 | After a card is removed, ibmtr_release() will unregister the net | ||
307 | device, and release the PCMCIA configuration. If the device is | ||
308 | still open, this will be postponed until it is closed. | ||
309 | |||
310 | ======================================================================*/ | ||
311 | |||
312 | static void ibmtr_release(struct pcmcia_device *link) | 275 | static void ibmtr_release(struct pcmcia_device *link) |
313 | { | 276 | { |
314 | ibmtr_dev_t *info = link->priv; | 277 | ibmtr_dev_t *info = link->priv; |
@@ -316,7 +279,7 @@ static void ibmtr_release(struct pcmcia_device *link) | |||
316 | 279 | ||
317 | dev_dbg(&link->dev, "ibmtr_release\n"); | 280 | dev_dbg(&link->dev, "ibmtr_release\n"); |
318 | 281 | ||
319 | if (link->win) { | 282 | if (link->resource[2]->end) { |
320 | struct tok_info *ti = netdev_priv(dev); | 283 | struct tok_info *ti = netdev_priv(dev); |
321 | iounmap(ti->mmio); | 284 | iounmap(ti->mmio); |
322 | } | 285 | } |
@@ -398,9 +361,7 @@ MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); | |||
398 | 361 | ||
399 | static struct pcmcia_driver ibmtr_cs_driver = { | 362 | static struct pcmcia_driver ibmtr_cs_driver = { |
400 | .owner = THIS_MODULE, | 363 | .owner = THIS_MODULE, |
401 | .drv = { | 364 | .name = "ibmtr_cs", |
402 | .name = "ibmtr_cs", | ||
403 | }, | ||
404 | .probe = ibmtr_attach, | 365 | .probe = ibmtr_attach, |
405 | .remove = ibmtr_detach, | 366 | .remove = ibmtr_detach, |
406 | .id_table = ibmtr_ids, | 367 | .id_table = ibmtr_ids, |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 68f2deeb3ade..1eca4f5a6e78 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -146,7 +146,6 @@ Include Files | |||
146 | #include <linux/ioport.h> | 146 | #include <linux/ioport.h> |
147 | #include <linux/bitops.h> | 147 | #include <linux/bitops.h> |
148 | 148 | ||
149 | #include <pcmcia/cs.h> | ||
150 | #include <pcmcia/cisreg.h> | 149 | #include <pcmcia/cisreg.h> |
151 | #include <pcmcia/cistpl.h> | 150 | #include <pcmcia/cistpl.h> |
152 | #include <pcmcia/ds.h> | 151 | #include <pcmcia/ds.h> |
@@ -435,13 +434,6 @@ static const struct net_device_ops mace_netdev_ops = { | |||
435 | .ndo_validate_addr = eth_validate_addr, | 434 | .ndo_validate_addr = eth_validate_addr, |
436 | }; | 435 | }; |
437 | 436 | ||
438 | /* ---------------------------------------------------------------------------- | ||
439 | nmclan_attach | ||
440 | Creates an "instance" of the driver, allocating local data | ||
441 | structures for one device. The device is registered with Card | ||
442 | Services. | ||
443 | ---------------------------------------------------------------------------- */ | ||
444 | |||
445 | static int nmclan_probe(struct pcmcia_device *link) | 437 | static int nmclan_probe(struct pcmcia_device *link) |
446 | { | 438 | { |
447 | mace_private *lp; | 439 | mace_private *lp; |
@@ -460,10 +452,9 @@ static int nmclan_probe(struct pcmcia_device *link) | |||
460 | spin_lock_init(&lp->bank_lock); | 452 | spin_lock_init(&lp->bank_lock); |
461 | link->resource[0]->end = 32; | 453 | link->resource[0]->end = 32; |
462 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 454 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
463 | link->conf.Attributes = CONF_ENABLE_IRQ; | 455 | link->config_flags |= CONF_ENABLE_IRQ; |
464 | link->conf.IntType = INT_MEMORY_AND_IO; | 456 | link->config_index = 1; |
465 | link->conf.ConfigIndex = 1; | 457 | link->config_regs = PRESENT_OPTION; |
466 | link->conf.Present = PRESENT_OPTION; | ||
467 | 458 | ||
468 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; | 459 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; |
469 | 460 | ||
@@ -474,14 +465,6 @@ static int nmclan_probe(struct pcmcia_device *link) | |||
474 | return nmclan_config(link); | 465 | return nmclan_config(link); |
475 | } /* nmclan_attach */ | 466 | } /* nmclan_attach */ |
476 | 467 | ||
477 | /* ---------------------------------------------------------------------------- | ||
478 | nmclan_detach | ||
479 | This deletes a driver "instance". The device is de-registered | ||
480 | with Card Services. If it has been released, all local data | ||
481 | structures are freed. Otherwise, the structures will be freed | ||
482 | when the device is released. | ||
483 | ---------------------------------------------------------------------------- */ | ||
484 | |||
485 | static void nmclan_detach(struct pcmcia_device *link) | 468 | static void nmclan_detach(struct pcmcia_device *link) |
486 | { | 469 | { |
487 | struct net_device *dev = link->priv; | 470 | struct net_device *dev = link->priv; |
@@ -625,13 +608,6 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) | |||
625 | return 0; | 608 | return 0; |
626 | } /* mace_init */ | 609 | } /* mace_init */ |
627 | 610 | ||
628 | /* ---------------------------------------------------------------------------- | ||
629 | nmclan_config | ||
630 | This routine is scheduled to run after a CARD_INSERTION event | ||
631 | is received, to configure the PCMCIA socket, and to make the | ||
632 | ethernet device available to the system. | ||
633 | ---------------------------------------------------------------------------- */ | ||
634 | |||
635 | static int nmclan_config(struct pcmcia_device *link) | 611 | static int nmclan_config(struct pcmcia_device *link) |
636 | { | 612 | { |
637 | struct net_device *dev = link->priv; | 613 | struct net_device *dev = link->priv; |
@@ -650,7 +626,7 @@ static int nmclan_config(struct pcmcia_device *link) | |||
650 | ret = pcmcia_request_exclusive_irq(link, mace_interrupt); | 626 | ret = pcmcia_request_exclusive_irq(link, mace_interrupt); |
651 | if (ret) | 627 | if (ret) |
652 | goto failed; | 628 | goto failed; |
653 | ret = pcmcia_request_configuration(link, &link->conf); | 629 | ret = pcmcia_enable_device(link); |
654 | if (ret) | 630 | if (ret) |
655 | goto failed; | 631 | goto failed; |
656 | 632 | ||
@@ -712,12 +688,6 @@ failed: | |||
712 | return -ENODEV; | 688 | return -ENODEV; |
713 | } /* nmclan_config */ | 689 | } /* nmclan_config */ |
714 | 690 | ||
715 | /* ---------------------------------------------------------------------------- | ||
716 | nmclan_release | ||
717 | After a card is removed, nmclan_release() will unregister the | ||
718 | net device, and release the PCMCIA configuration. If the device | ||
719 | is still open, this will be postponed until it is closed. | ||
720 | ---------------------------------------------------------------------------- */ | ||
721 | static void nmclan_release(struct pcmcia_device *link) | 691 | static void nmclan_release(struct pcmcia_device *link) |
722 | { | 692 | { |
723 | dev_dbg(&link->dev, "nmclan_release\n"); | 693 | dev_dbg(&link->dev, "nmclan_release\n"); |
@@ -1535,9 +1505,7 @@ MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); | |||
1535 | 1505 | ||
1536 | static struct pcmcia_driver nmclan_cs_driver = { | 1506 | static struct pcmcia_driver nmclan_cs_driver = { |
1537 | .owner = THIS_MODULE, | 1507 | .owner = THIS_MODULE, |
1538 | .drv = { | 1508 | .name = "nmclan_cs", |
1539 | .name = "nmclan_cs", | ||
1540 | }, | ||
1541 | .probe = nmclan_probe, | 1509 | .probe = nmclan_probe, |
1542 | .remove = nmclan_detach, | 1510 | .remove = nmclan_detach, |
1543 | .id_table = nmclan_ids, | 1511 | .id_table = nmclan_ids, |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index f9b509a6b09a..5d7d1d3088ae 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/mii.h> | 42 | #include <linux/mii.h> |
43 | #include "../8390.h" | 43 | #include "../8390.h" |
44 | 44 | ||
45 | #include <pcmcia/cs.h> | ||
46 | #include <pcmcia/cistpl.h> | 45 | #include <pcmcia/cistpl.h> |
47 | #include <pcmcia/ciscode.h> | 46 | #include <pcmcia/ciscode.h> |
48 | #include <pcmcia/ds.h> | 47 | #include <pcmcia/ds.h> |
@@ -238,14 +237,6 @@ static const struct net_device_ops pcnet_netdev_ops = { | |||
238 | #endif | 237 | #endif |
239 | }; | 238 | }; |
240 | 239 | ||
241 | /*====================================================================== | ||
242 | |||
243 | pcnet_attach() creates an "instance" of the driver, allocating | ||
244 | local data structures for one device. The device is registered | ||
245 | with Card Services. | ||
246 | |||
247 | ======================================================================*/ | ||
248 | |||
249 | static int pcnet_probe(struct pcmcia_device *link) | 240 | static int pcnet_probe(struct pcmcia_device *link) |
250 | { | 241 | { |
251 | pcnet_dev_t *info; | 242 | pcnet_dev_t *info; |
@@ -260,23 +251,13 @@ static int pcnet_probe(struct pcmcia_device *link) | |||
260 | info->p_dev = link; | 251 | info->p_dev = link; |
261 | link->priv = dev; | 252 | link->priv = dev; |
262 | 253 | ||
263 | link->conf.Attributes = CONF_ENABLE_IRQ; | 254 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
264 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
265 | 255 | ||
266 | dev->netdev_ops = &pcnet_netdev_ops; | 256 | dev->netdev_ops = &pcnet_netdev_ops; |
267 | 257 | ||
268 | return pcnet_config(link); | 258 | return pcnet_config(link); |
269 | } /* pcnet_attach */ | 259 | } /* pcnet_attach */ |
270 | 260 | ||
271 | /*====================================================================== | ||
272 | |||
273 | This deletes a driver "instance". The device is de-registered | ||
274 | with Card Services. If it has been released, all local data | ||
275 | structures are freed. Otherwise, the structures will be freed | ||
276 | when the device is released. | ||
277 | |||
278 | ======================================================================*/ | ||
279 | |||
280 | static void pcnet_detach(struct pcmcia_device *link) | 261 | static void pcnet_detach(struct pcmcia_device *link) |
281 | { | 262 | { |
282 | struct net_device *dev = link->priv; | 263 | struct net_device *dev = link->priv; |
@@ -300,22 +281,22 @@ static void pcnet_detach(struct pcmcia_device *link) | |||
300 | static hw_info_t *get_hwinfo(struct pcmcia_device *link) | 281 | static hw_info_t *get_hwinfo(struct pcmcia_device *link) |
301 | { | 282 | { |
302 | struct net_device *dev = link->priv; | 283 | struct net_device *dev = link->priv; |
303 | win_req_t req; | ||
304 | u_char __iomem *base, *virt; | 284 | u_char __iomem *base, *virt; |
305 | int i, j; | 285 | int i, j; |
306 | 286 | ||
307 | /* Allocate a small memory window */ | 287 | /* Allocate a small memory window */ |
308 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 288 | link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
309 | req.Base = 0; req.Size = 0; | 289 | link->resource[2]->start = 0; link->resource[2]->end = 0; |
310 | req.AccessSpeed = 0; | 290 | i = pcmcia_request_window(link, link->resource[2], 0); |
311 | i = pcmcia_request_window(link, &req, &link->win); | ||
312 | if (i != 0) | 291 | if (i != 0) |
313 | return NULL; | 292 | return NULL; |
314 | 293 | ||
315 | virt = ioremap(req.Base, req.Size); | 294 | virt = ioremap(link->resource[2]->start, |
295 | resource_size(link->resource[2])); | ||
316 | for (i = 0; i < NR_INFO; i++) { | 296 | for (i = 0; i < NR_INFO; i++) { |
317 | pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1)); | 297 | pcmcia_map_mem_page(link, link->resource[2], |
318 | base = &virt[hw_info[i].offset & (req.Size-1)]; | 298 | hw_info[i].offset & ~(resource_size(link->resource[2])-1)); |
299 | base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)]; | ||
319 | if ((readb(base+0) == hw_info[i].a0) && | 300 | if ((readb(base+0) == hw_info[i].a0) && |
320 | (readb(base+2) == hw_info[i].a1) && | 301 | (readb(base+2) == hw_info[i].a1) && |
321 | (readb(base+4) == hw_info[i].a2)) { | 302 | (readb(base+4) == hw_info[i].a2)) { |
@@ -326,7 +307,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) | |||
326 | } | 307 | } |
327 | 308 | ||
328 | iounmap(virt); | 309 | iounmap(virt); |
329 | j = pcmcia_release_window(link, link->win); | 310 | j = pcmcia_release_window(link, link->resource[2]); |
330 | return (i < NR_INFO) ? hw_info+i : NULL; | 311 | return (i < NR_INFO) ? hw_info+i : NULL; |
331 | } /* get_hwinfo */ | 312 | } /* get_hwinfo */ |
332 | 313 | ||
@@ -421,7 +402,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link) | |||
421 | int i, j; | 402 | int i, j; |
422 | 403 | ||
423 | /* Not much of a test, but the alternatives are messy */ | 404 | /* Not much of a test, but the alternatives are messy */ |
424 | if (link->conf.ConfigBase != 0x03c0) | 405 | if (link->config_base != 0x03c0) |
425 | return NULL; | 406 | return NULL; |
426 | 407 | ||
427 | outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */ | 408 | outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */ |
@@ -463,14 +444,6 @@ static hw_info_t *get_hwired(struct pcmcia_device *link) | |||
463 | return &default_info; | 444 | return &default_info; |
464 | } /* get_hwired */ | 445 | } /* get_hwired */ |
465 | 446 | ||
466 | /*====================================================================== | ||
467 | |||
468 | pcnet_config() is scheduled to run after a CARD_INSERTION event | ||
469 | is received, to configure the PCMCIA socket, and to make the | ||
470 | ethernet device available to the system. | ||
471 | |||
472 | ======================================================================*/ | ||
473 | |||
474 | static int try_io_port(struct pcmcia_device *link) | 447 | static int try_io_port(struct pcmcia_device *link) |
475 | { | 448 | { |
476 | int j, ret; | 449 | int j, ret; |
@@ -502,43 +475,22 @@ static int try_io_port(struct pcmcia_device *link) | |||
502 | } | 475 | } |
503 | } | 476 | } |
504 | 477 | ||
505 | static int pcnet_confcheck(struct pcmcia_device *p_dev, | 478 | static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data) |
506 | cistpl_cftable_entry_t *cfg, | ||
507 | cistpl_cftable_entry_t *dflt, | ||
508 | unsigned int vcc, | ||
509 | void *priv_data) | ||
510 | { | 479 | { |
511 | int *priv = priv_data; | 480 | int *priv = priv_data; |
512 | int try = (*priv & 0x1); | 481 | int try = (*priv & 0x1); |
513 | int i; | ||
514 | cistpl_io_t *io = &cfg->io; | ||
515 | 482 | ||
516 | if (cfg->index == 0 || cfg->io.nwin == 0) | 483 | *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10; |
517 | return -EINVAL; | ||
518 | 484 | ||
519 | /* For multifunction cards, by convention, we configure the | 485 | if (p_dev->config_index == 0) |
520 | network function with window 0, and serial with window 1 */ | 486 | return -EINVAL; |
521 | if (io->nwin > 1) { | ||
522 | i = (io->win[1].len > io->win[0].len); | ||
523 | p_dev->resource[1]->start = io->win[1-i].base; | ||
524 | p_dev->resource[1]->end = io->win[1-i].len; | ||
525 | } else { | ||
526 | i = p_dev->resource[1]->end = 0; | ||
527 | } | ||
528 | 487 | ||
529 | *priv &= ((cfg->mem.nwin == 1) && | 488 | if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32) |
530 | (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; | 489 | return -EINVAL; |
531 | 490 | ||
532 | p_dev->resource[0]->start = io->win[i].base; | 491 | if (try) |
533 | p_dev->resource[0]->end = io->win[i].len; | ||
534 | if (!try) | ||
535 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
536 | else | ||
537 | p_dev->io_lines = 16; | 492 | p_dev->io_lines = 16; |
538 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) | 493 | return try_io_port(p_dev); |
539 | return try_io_port(p_dev); | ||
540 | |||
541 | return -EINVAL; | ||
542 | } | 494 | } |
543 | 495 | ||
544 | static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | 496 | static hw_info_t *pcnet_try_config(struct pcmcia_device *link, |
@@ -560,15 +512,14 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | |||
560 | if (!link->irq) | 512 | if (!link->irq) |
561 | return NULL; | 513 | return NULL; |
562 | 514 | ||
563 | if (resource_size(link->resource[1]) == 8) { | 515 | if (resource_size(link->resource[1]) == 8) |
564 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 516 | link->config_flags |= CONF_ENABLE_SPKR; |
565 | link->conf.Status = CCSR_AUDIO_ENA; | 517 | |
566 | } | ||
567 | if ((link->manf_id == MANFID_IBM) && | 518 | if ((link->manf_id == MANFID_IBM) && |
568 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | 519 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) |
569 | link->conf.ConfigIndex |= 0x10; | 520 | link->config_index |= 0x10; |
570 | 521 | ||
571 | ret = pcmcia_request_configuration(link, &link->conf); | 522 | ret = pcmcia_enable_device(link); |
572 | if (ret) | 523 | if (ret) |
573 | return NULL; | 524 | return NULL; |
574 | 525 | ||
@@ -583,7 +534,7 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | |||
583 | } else | 534 | } else |
584 | dev->if_port = 0; | 535 | dev->if_port = 0; |
585 | 536 | ||
586 | if ((link->conf.ConfigBase == 0x03c0) && | 537 | if ((link->config_base == 0x03c0) && |
587 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | 538 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { |
588 | dev_info(&link->dev, | 539 | dev_info(&link->dev, |
589 | "this is an AX88190 card - use axnet_cs instead.\n"); | 540 | "this is an AX88190 card - use axnet_cs instead.\n"); |
@@ -689,14 +640,6 @@ failed: | |||
689 | return -ENODEV; | 640 | return -ENODEV; |
690 | } /* pcnet_config */ | 641 | } /* pcnet_config */ |
691 | 642 | ||
692 | /*====================================================================== | ||
693 | |||
694 | After a card is removed, pcnet_release() will unregister the net | ||
695 | device, and release the PCMCIA configuration. If the device is | ||
696 | still open, this will be postponed until it is closed. | ||
697 | |||
698 | ======================================================================*/ | ||
699 | |||
700 | static void pcnet_release(struct pcmcia_device *link) | 643 | static void pcnet_release(struct pcmcia_device *link) |
701 | { | 644 | { |
702 | pcnet_dev_t *info = PRIV(link->priv); | 645 | pcnet_dev_t *info = PRIV(link->priv); |
@@ -709,15 +652,6 @@ static void pcnet_release(struct pcmcia_device *link) | |||
709 | pcmcia_disable_device(link); | 652 | pcmcia_disable_device(link); |
710 | } | 653 | } |
711 | 654 | ||
712 | /*====================================================================== | ||
713 | |||
714 | The card status event handler. Mostly, this schedules other | ||
715 | stuff to run after an event is received. A CARD_REMOVAL event | ||
716 | also sets some flags to discourage the net drivers from trying | ||
717 | to talk to the card any more. | ||
718 | |||
719 | ======================================================================*/ | ||
720 | |||
721 | static int pcnet_suspend(struct pcmcia_device *link) | 655 | static int pcnet_suspend(struct pcmcia_device *link) |
722 | { | 656 | { |
723 | struct net_device *dev = link->priv; | 657 | struct net_device *dev = link->priv; |
@@ -1486,7 +1420,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, | |||
1486 | { | 1420 | { |
1487 | struct net_device *dev = link->priv; | 1421 | struct net_device *dev = link->priv; |
1488 | pcnet_dev_t *info = PRIV(dev); | 1422 | pcnet_dev_t *info = PRIV(dev); |
1489 | win_req_t req; | ||
1490 | int i, window_size, offset, ret; | 1423 | int i, window_size, offset, ret; |
1491 | 1424 | ||
1492 | window_size = (stop_pg - start_pg) << 8; | 1425 | window_size = (stop_pg - start_pg) << 8; |
@@ -1497,22 +1430,22 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, | |||
1497 | window_size = roundup_pow_of_two(window_size); | 1430 | window_size = roundup_pow_of_two(window_size); |
1498 | 1431 | ||
1499 | /* Allocate a memory window */ | 1432 | /* Allocate a memory window */ |
1500 | req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | 1433 | link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; |
1501 | req.Attributes |= WIN_USE_WAIT; | 1434 | link->resource[3]->flags |= WIN_USE_WAIT; |
1502 | req.Base = 0; req.Size = window_size; | 1435 | link->resource[3]->start = 0; link->resource[3]->end = window_size; |
1503 | req.AccessSpeed = mem_speed; | 1436 | ret = pcmcia_request_window(link, link->resource[3], mem_speed); |
1504 | ret = pcmcia_request_window(link, &req, &link->win); | ||
1505 | if (ret) | 1437 | if (ret) |
1506 | goto failed; | 1438 | goto failed; |
1507 | 1439 | ||
1508 | offset = (start_pg << 8) + cm_offset; | 1440 | offset = (start_pg << 8) + cm_offset; |
1509 | offset -= offset % window_size; | 1441 | offset -= offset % window_size; |
1510 | ret = pcmcia_map_mem_page(link, link->win, offset); | 1442 | ret = pcmcia_map_mem_page(link, link->resource[3], offset); |
1511 | if (ret) | 1443 | if (ret) |
1512 | goto failed; | 1444 | goto failed; |
1513 | 1445 | ||
1514 | /* Try scribbling on the buffer */ | 1446 | /* Try scribbling on the buffer */ |
1515 | info->base = ioremap(req.Base, window_size); | 1447 | info->base = ioremap(link->resource[3]->start, |
1448 | resource_size(link->resource[3])); | ||
1516 | for (i = 0; i < (TX_PAGES<<8); i += 2) | 1449 | for (i = 0; i < (TX_PAGES<<8); i += 2) |
1517 | __raw_writew((i>>1), info->base+offset+i); | 1450 | __raw_writew((i>>1), info->base+offset+i); |
1518 | udelay(100); | 1451 | udelay(100); |
@@ -1521,19 +1454,20 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg, | |||
1521 | pcnet_reset_8390(dev); | 1454 | pcnet_reset_8390(dev); |
1522 | if (i != (TX_PAGES<<8)) { | 1455 | if (i != (TX_PAGES<<8)) { |
1523 | iounmap(info->base); | 1456 | iounmap(info->base); |
1524 | pcmcia_release_window(link, link->win); | 1457 | pcmcia_release_window(link, link->resource[3]); |
1525 | info->base = NULL; link->win = 0; | 1458 | info->base = NULL; |
1526 | goto failed; | 1459 | goto failed; |
1527 | } | 1460 | } |
1528 | 1461 | ||
1529 | ei_status.mem = info->base + offset; | 1462 | ei_status.mem = info->base + offset; |
1530 | ei_status.priv = req.Size; | 1463 | ei_status.priv = resource_size(link->resource[3]); |
1531 | dev->mem_start = (u_long)ei_status.mem; | 1464 | dev->mem_start = (u_long)ei_status.mem; |
1532 | dev->mem_end = dev->mem_start + req.Size; | 1465 | dev->mem_end = dev->mem_start + resource_size(link->resource[3]); |
1533 | 1466 | ||
1534 | ei_status.tx_start_page = start_pg; | 1467 | ei_status.tx_start_page = start_pg; |
1535 | ei_status.rx_start_page = start_pg + TX_PAGES; | 1468 | ei_status.rx_start_page = start_pg + TX_PAGES; |
1536 | ei_status.stop_page = start_pg + ((req.Size - offset) >> 8); | 1469 | ei_status.stop_page = start_pg + ( |
1470 | (resource_size(link->resource[3]) - offset) >> 8); | ||
1537 | 1471 | ||
1538 | /* set up block i/o functions */ | 1472 | /* set up block i/o functions */ |
1539 | ei_status.get_8390_hdr = &shmem_get_8390_hdr; | 1473 | ei_status.get_8390_hdr = &shmem_get_8390_hdr; |
@@ -1772,9 +1706,7 @@ MODULE_FIRMWARE("cis/PE-200.cis"); | |||
1772 | MODULE_FIRMWARE("cis/tamarack.cis"); | 1706 | MODULE_FIRMWARE("cis/tamarack.cis"); |
1773 | 1707 | ||
1774 | static struct pcmcia_driver pcnet_driver = { | 1708 | static struct pcmcia_driver pcnet_driver = { |
1775 | .drv = { | 1709 | .name = "pcnet_cs", |
1776 | .name = "pcnet_cs", | ||
1777 | }, | ||
1778 | .probe = pcnet_probe, | 1710 | .probe = pcnet_probe, |
1779 | .remove = pcnet_detach, | 1711 | .remove = pcnet_detach, |
1780 | .owner = THIS_MODULE, | 1712 | .owner = THIS_MODULE, |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 377367d03b41..0af2fc8ec164 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/jiffies.h> | 44 | #include <linux/jiffies.h> |
45 | #include <linux/firmware.h> | 45 | #include <linux/firmware.h> |
46 | 46 | ||
47 | #include <pcmcia/cs.h> | ||
48 | #include <pcmcia/cistpl.h> | 47 | #include <pcmcia/cistpl.h> |
49 | #include <pcmcia/cisreg.h> | 48 | #include <pcmcia/cisreg.h> |
50 | #include <pcmcia/ciscode.h> | 49 | #include <pcmcia/ciscode.h> |
@@ -300,14 +299,6 @@ static const struct net_device_ops smc_netdev_ops = { | |||
300 | .ndo_validate_addr = eth_validate_addr, | 299 | .ndo_validate_addr = eth_validate_addr, |
301 | }; | 300 | }; |
302 | 301 | ||
303 | /*====================================================================== | ||
304 | |||
305 | smc91c92_attach() creates an "instance" of the driver, allocating | ||
306 | local data structures for one device. The device is registered | ||
307 | with Card Services. | ||
308 | |||
309 | ======================================================================*/ | ||
310 | |||
311 | static int smc91c92_probe(struct pcmcia_device *link) | 302 | static int smc91c92_probe(struct pcmcia_device *link) |
312 | { | 303 | { |
313 | struct smc_private *smc; | 304 | struct smc_private *smc; |
@@ -324,10 +315,6 @@ static int smc91c92_probe(struct pcmcia_device *link) | |||
324 | link->priv = dev; | 315 | link->priv = dev; |
325 | 316 | ||
326 | spin_lock_init(&smc->lock); | 317 | spin_lock_init(&smc->lock); |
327 | link->resource[0]->end = 16; | ||
328 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
329 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
330 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
331 | 318 | ||
332 | /* The SMC91c92-specific entries in the device structure. */ | 319 | /* The SMC91c92-specific entries in the device structure. */ |
333 | dev->netdev_ops = &smc_netdev_ops; | 320 | dev->netdev_ops = &smc_netdev_ops; |
@@ -343,15 +330,6 @@ static int smc91c92_probe(struct pcmcia_device *link) | |||
343 | return smc91c92_config(link); | 330 | return smc91c92_config(link); |
344 | } /* smc91c92_attach */ | 331 | } /* smc91c92_attach */ |
345 | 332 | ||
346 | /*====================================================================== | ||
347 | |||
348 | This deletes a driver "instance". The device is de-registered | ||
349 | with Card Services. If it has been released, all local data | ||
350 | structures are freed. Otherwise, the structures will be freed | ||
351 | when the device is released. | ||
352 | |||
353 | ======================================================================*/ | ||
354 | |||
355 | static void smc91c92_detach(struct pcmcia_device *link) | 333 | static void smc91c92_detach(struct pcmcia_device *link) |
356 | { | 334 | { |
357 | struct net_device *dev = link->priv; | 335 | struct net_device *dev = link->priv; |
@@ -412,26 +390,28 @@ static int mhz_3288_power(struct pcmcia_device *link) | |||
412 | mdelay(200); | 390 | mdelay(200); |
413 | 391 | ||
414 | /* Now read and write the COR... */ | 392 | /* Now read and write the COR... */ |
415 | tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR); | 393 | tmp = readb(smc->base + link->config_base + CISREG_COR); |
416 | udelay(5); | 394 | udelay(5); |
417 | writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR); | 395 | writeb(tmp, smc->base + link->config_base + CISREG_COR); |
418 | 396 | ||
419 | return 0; | 397 | return 0; |
420 | } | 398 | } |
421 | 399 | ||
422 | static int mhz_mfc_config_check(struct pcmcia_device *p_dev, | 400 | static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data) |
423 | cistpl_cftable_entry_t *cf, | ||
424 | cistpl_cftable_entry_t *dflt, | ||
425 | unsigned int vcc, | ||
426 | void *priv_data) | ||
427 | { | 401 | { |
428 | int k; | 402 | int k; |
429 | p_dev->resource[1]->start = cf->io.win[0].base; | 403 | p_dev->io_lines = 16; |
404 | p_dev->resource[1]->start = p_dev->resource[0]->start; | ||
405 | p_dev->resource[1]->end = 8; | ||
406 | p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | ||
407 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
408 | p_dev->resource[0]->end = 16; | ||
409 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
410 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
430 | for (k = 0; k < 0x400; k += 0x10) { | 411 | for (k = 0; k < 0x400; k += 0x10) { |
431 | if (k & 0x80) | 412 | if (k & 0x80) |
432 | continue; | 413 | continue; |
433 | p_dev->resource[0]->start = k ^ 0x300; | 414 | p_dev->resource[0]->start = k ^ 0x300; |
434 | p_dev->io_lines = 16; | ||
435 | if (!pcmcia_request_io(p_dev)) | 415 | if (!pcmcia_request_io(p_dev)) |
436 | return 0; | 416 | return 0; |
437 | } | 417 | } |
@@ -442,14 +422,11 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
442 | { | 422 | { |
443 | struct net_device *dev = link->priv; | 423 | struct net_device *dev = link->priv; |
444 | struct smc_private *smc = netdev_priv(dev); | 424 | struct smc_private *smc = netdev_priv(dev); |
445 | win_req_t req; | ||
446 | unsigned int offset; | 425 | unsigned int offset; |
447 | int i; | 426 | int i; |
448 | 427 | ||
449 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 428 | link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ | |
450 | link->conf.Status = CCSR_AUDIO_ENA; | 429 | CONF_AUTO_SET_IO; |
451 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
452 | link->resource[1]->end = 8; | ||
453 | 430 | ||
454 | /* The Megahertz combo cards have modem-like CIS entries, so | 431 | /* The Megahertz combo cards have modem-like CIS entries, so |
455 | we have to explicitly try a bunch of port combinations. */ | 432 | we have to explicitly try a bunch of port combinations. */ |
@@ -459,16 +436,16 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
459 | dev->base_addr = link->resource[0]->start; | 436 | dev->base_addr = link->resource[0]->start; |
460 | 437 | ||
461 | /* Allocate a memory window, for accessing the ISR */ | 438 | /* Allocate a memory window, for accessing the ISR */ |
462 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 439 | link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
463 | req.Base = req.Size = 0; | 440 | link->resource[2]->start = link->resource[2]->end = 0; |
464 | req.AccessSpeed = 0; | 441 | i = pcmcia_request_window(link, link->resource[2], 0); |
465 | i = pcmcia_request_window(link, &req, &link->win); | ||
466 | if (i != 0) | 442 | if (i != 0) |
467 | return -ENODEV; | 443 | return -ENODEV; |
468 | 444 | ||
469 | smc->base = ioremap(req.Base, req.Size); | 445 | smc->base = ioremap(link->resource[2]->start, |
470 | offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0; | 446 | resource_size(link->resource[2])); |
471 | i = pcmcia_map_mem_page(link, link->win, offset); | 447 | offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0; |
448 | i = pcmcia_map_mem_page(link, link->resource[2], offset); | ||
472 | if ((i == 0) && | 449 | if ((i == 0) && |
473 | (smc->manfid == MANFID_MEGAHERTZ) && | 450 | (smc->manfid == MANFID_MEGAHERTZ) && |
474 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | 451 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) |
@@ -591,14 +568,12 @@ static int mot_setup(struct pcmcia_device *link) | |||
591 | 568 | ||
592 | /*====================================================================*/ | 569 | /*====================================================================*/ |
593 | 570 | ||
594 | static int smc_configcheck(struct pcmcia_device *p_dev, | 571 | static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data) |
595 | cistpl_cftable_entry_t *cf, | ||
596 | cistpl_cftable_entry_t *dflt, | ||
597 | unsigned int vcc, | ||
598 | void *priv_data) | ||
599 | { | 572 | { |
600 | p_dev->resource[0]->start = cf->io.win[0].base; | 573 | p_dev->resource[0]->end = 16; |
601 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 574 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
575 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
576 | |||
602 | return pcmcia_request_io(p_dev); | 577 | return pcmcia_request_io(p_dev); |
603 | } | 578 | } |
604 | 579 | ||
@@ -607,7 +582,8 @@ static int smc_config(struct pcmcia_device *link) | |||
607 | struct net_device *dev = link->priv; | 582 | struct net_device *dev = link->priv; |
608 | int i; | 583 | int i; |
609 | 584 | ||
610 | link->resource[0]->end = 16; | 585 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
586 | |||
611 | i = pcmcia_loop_config(link, smc_configcheck, NULL); | 587 | i = pcmcia_loop_config(link, smc_configcheck, NULL); |
612 | if (!i) | 588 | if (!i) |
613 | dev->base_addr = link->resource[0]->start; | 589 | dev->base_addr = link->resource[0]->start; |
@@ -640,15 +616,14 @@ static int osi_config(struct pcmcia_device *link) | |||
640 | static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; | 616 | static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; |
641 | int i, j; | 617 | int i, j; |
642 | 618 | ||
643 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 619 | link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ; |
644 | link->conf.Status = CCSR_AUDIO_ENA; | ||
645 | link->resource[0]->end = 64; | 620 | link->resource[0]->end = 64; |
646 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | 621 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
647 | link->resource[1]->end = 8; | 622 | link->resource[1]->end = 8; |
648 | 623 | ||
649 | /* Enable Hard Decode, LAN, Modem */ | 624 | /* Enable Hard Decode, LAN, Modem */ |
650 | link->conf.ConfigIndex = 0x23; | ||
651 | link->io_lines = 16; | 625 | link->io_lines = 16; |
626 | link->config_index = 0x23; | ||
652 | 627 | ||
653 | for (i = j = 0; j < 4; j++) { | 628 | for (i = j = 0; j < 4; j++) { |
654 | link->resource[1]->start = com[j]; | 629 | link->resource[1]->start = com[j]; |
@@ -658,7 +633,7 @@ static int osi_config(struct pcmcia_device *link) | |||
658 | } | 633 | } |
659 | if (i != 0) { | 634 | if (i != 0) { |
660 | /* Fallback: turn off hard decode */ | 635 | /* Fallback: turn off hard decode */ |
661 | link->conf.ConfigIndex = 0x03; | 636 | link->config_index = 0x03; |
662 | link->resource[1]->end = 0; | 637 | link->resource[1]->end = 0; |
663 | i = pcmcia_request_io(link); | 638 | i = pcmcia_request_io(link); |
664 | } | 639 | } |
@@ -817,27 +792,16 @@ static int check_sig(struct pcmcia_device *link) | |||
817 | } | 792 | } |
818 | 793 | ||
819 | if (width) { | 794 | if (width) { |
820 | modconf_t mod = { | ||
821 | .Attributes = CONF_IO_CHANGE_WIDTH, | ||
822 | }; | ||
823 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | 795 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); |
824 | 796 | ||
825 | smc91c92_suspend(link); | 797 | smc91c92_suspend(link); |
826 | pcmcia_modify_configuration(link, &mod); | 798 | pcmcia_fixup_iowidth(link); |
827 | smc91c92_resume(link); | 799 | smc91c92_resume(link); |
828 | return check_sig(link); | 800 | return check_sig(link); |
829 | } | 801 | } |
830 | return -ENODEV; | 802 | return -ENODEV; |
831 | } | 803 | } |
832 | 804 | ||
833 | /*====================================================================== | ||
834 | |||
835 | smc91c92_config() is scheduled to run after a CARD_INSERTION event | ||
836 | is received, to configure the PCMCIA socket, and to make the | ||
837 | ethernet device available to the system. | ||
838 | |||
839 | ======================================================================*/ | ||
840 | |||
841 | static int smc91c92_config(struct pcmcia_device *link) | 805 | static int smc91c92_config(struct pcmcia_device *link) |
842 | { | 806 | { |
843 | struct net_device *dev = link->priv; | 807 | struct net_device *dev = link->priv; |
@@ -869,7 +833,7 @@ static int smc91c92_config(struct pcmcia_device *link) | |||
869 | i = pcmcia_request_irq(link, smc_interrupt); | 833 | i = pcmcia_request_irq(link, smc_interrupt); |
870 | if (i) | 834 | if (i) |
871 | goto config_failed; | 835 | goto config_failed; |
872 | i = pcmcia_request_configuration(link, &link->conf); | 836 | i = pcmcia_enable_device(link); |
873 | if (i) | 837 | if (i) |
874 | goto config_failed; | 838 | goto config_failed; |
875 | 839 | ||
@@ -988,18 +952,10 @@ config_failed: | |||
988 | return -ENODEV; | 952 | return -ENODEV; |
989 | } /* smc91c92_config */ | 953 | } /* smc91c92_config */ |
990 | 954 | ||
991 | /*====================================================================== | ||
992 | |||
993 | After a card is removed, smc91c92_release() will unregister the net | ||
994 | device, and release the PCMCIA configuration. If the device is | ||
995 | still open, this will be postponed until it is closed. | ||
996 | |||
997 | ======================================================================*/ | ||
998 | |||
999 | static void smc91c92_release(struct pcmcia_device *link) | 955 | static void smc91c92_release(struct pcmcia_device *link) |
1000 | { | 956 | { |
1001 | dev_dbg(&link->dev, "smc91c92_release\n"); | 957 | dev_dbg(&link->dev, "smc91c92_release\n"); |
1002 | if (link->win) { | 958 | if (link->resource[2]->end) { |
1003 | struct net_device *dev = link->priv; | 959 | struct net_device *dev = link->priv; |
1004 | struct smc_private *smc = netdev_priv(dev); | 960 | struct smc_private *smc = netdev_priv(dev); |
1005 | iounmap(smc->base); | 961 | iounmap(smc->base); |
@@ -2101,9 +2057,7 @@ MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids); | |||
2101 | 2057 | ||
2102 | static struct pcmcia_driver smc91c92_cs_driver = { | 2058 | static struct pcmcia_driver smc91c92_cs_driver = { |
2103 | .owner = THIS_MODULE, | 2059 | .owner = THIS_MODULE, |
2104 | .drv = { | 2060 | .name = "smc91c92_cs", |
2105 | .name = "smc91c92_cs", | ||
2106 | }, | ||
2107 | .probe = smc91c92_probe, | 2061 | .probe = smc91c92_probe, |
2108 | .remove = smc91c92_detach, | 2062 | .remove = smc91c92_detach, |
2109 | .id_table = smc91c92_ids, | 2063 | .id_table = smc91c92_ids, |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index f5819526b5ee..1fece617c069 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -82,7 +82,6 @@ | |||
82 | #include <linux/bitops.h> | 82 | #include <linux/bitops.h> |
83 | #include <linux/mii.h> | 83 | #include <linux/mii.h> |
84 | 84 | ||
85 | #include <pcmcia/cs.h> | ||
86 | #include <pcmcia/cistpl.h> | 85 | #include <pcmcia/cistpl.h> |
87 | #include <pcmcia/cisreg.h> | 86 | #include <pcmcia/cisreg.h> |
88 | #include <pcmcia/ciscode.h> | 87 | #include <pcmcia/ciscode.h> |
@@ -267,33 +266,11 @@ static unsigned mii_rd(unsigned int ioaddr, u_char phyaddr, u_char phyreg); | |||
267 | static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, | 266 | static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, |
268 | unsigned data, int len); | 267 | unsigned data, int len); |
269 | 268 | ||
270 | /* | ||
271 | * The event() function is this driver's Card Services event handler. | ||
272 | * It will be called by Card Services when an appropriate card status | ||
273 | * event is received. The config() and release() entry points are | ||
274 | * used to configure or release a socket, in response to card insertion | ||
275 | * and ejection events. They are invoked from the event handler. | ||
276 | */ | ||
277 | |||
278 | static int has_ce2_string(struct pcmcia_device * link); | 269 | static int has_ce2_string(struct pcmcia_device * link); |
279 | static int xirc2ps_config(struct pcmcia_device * link); | 270 | static int xirc2ps_config(struct pcmcia_device * link); |
280 | static void xirc2ps_release(struct pcmcia_device * link); | 271 | static void xirc2ps_release(struct pcmcia_device * link); |
281 | |||
282 | /**************** | ||
283 | * The attach() and detach() entry points are used to create and destroy | ||
284 | * "instances" of the driver, where each instance represents everything | ||
285 | * needed to manage one actual PCMCIA card. | ||
286 | */ | ||
287 | |||
288 | static void xirc2ps_detach(struct pcmcia_device *p_dev); | 272 | static void xirc2ps_detach(struct pcmcia_device *p_dev); |
289 | 273 | ||
290 | /**************** | ||
291 | * You'll also need to prototype all the functions that will actually | ||
292 | * be used to talk to your device. See 'pcmem_cs' for a good example | ||
293 | * of a fully self-sufficient driver; the other drivers rely more or | ||
294 | * less on other parts of the kernel. | ||
295 | */ | ||
296 | |||
297 | static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); | 274 | static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); |
298 | 275 | ||
299 | typedef struct local_info_t { | 276 | typedef struct local_info_t { |
@@ -501,16 +478,6 @@ static const struct net_device_ops netdev_ops = { | |||
501 | .ndo_validate_addr = eth_validate_addr, | 478 | .ndo_validate_addr = eth_validate_addr, |
502 | }; | 479 | }; |
503 | 480 | ||
504 | /**************** | ||
505 | * xirc2ps_attach() creates an "instance" of the driver, allocating | ||
506 | * local data structures for one device. The device is registered | ||
507 | * with Card Services. | ||
508 | * | ||
509 | * The dev_link structure is initialized, but we don't actually | ||
510 | * configure the card at this point -- we wait until we receive a | ||
511 | * card insertion event. | ||
512 | */ | ||
513 | |||
514 | static int | 481 | static int |
515 | xirc2ps_probe(struct pcmcia_device *link) | 482 | xirc2ps_probe(struct pcmcia_device *link) |
516 | { | 483 | { |
@@ -529,9 +496,7 @@ xirc2ps_probe(struct pcmcia_device *link) | |||
529 | link->priv = dev; | 496 | link->priv = dev; |
530 | 497 | ||
531 | /* General socket configuration */ | 498 | /* General socket configuration */ |
532 | link->conf.Attributes = CONF_ENABLE_IRQ; | 499 | link->config_index = 1; |
533 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
534 | link->conf.ConfigIndex = 1; | ||
535 | 500 | ||
536 | /* Fill in card specific entries */ | 501 | /* Fill in card specific entries */ |
537 | dev->netdev_ops = &netdev_ops; | 502 | dev->netdev_ops = &netdev_ops; |
@@ -542,13 +507,6 @@ xirc2ps_probe(struct pcmcia_device *link) | |||
542 | return xirc2ps_config(link); | 507 | return xirc2ps_config(link); |
543 | } /* xirc2ps_attach */ | 508 | } /* xirc2ps_attach */ |
544 | 509 | ||
545 | /**************** | ||
546 | * This deletes a driver "instance". The device is de-registered | ||
547 | * with Card Services. If it has been released, all local data | ||
548 | * structures are freed. Otherwise, the structures will be freed | ||
549 | * when the device is released. | ||
550 | */ | ||
551 | |||
552 | static void | 510 | static void |
553 | xirc2ps_detach(struct pcmcia_device *link) | 511 | xirc2ps_detach(struct pcmcia_device *link) |
554 | { | 512 | { |
@@ -667,44 +625,53 @@ has_ce2_string(struct pcmcia_device * p_dev) | |||
667 | } | 625 | } |
668 | 626 | ||
669 | static int | 627 | static int |
670 | xirc2ps_config_modem(struct pcmcia_device *p_dev, | 628 | xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data) |
671 | cistpl_cftable_entry_t *cf, | ||
672 | cistpl_cftable_entry_t *dflt, | ||
673 | unsigned int vcc, | ||
674 | void *priv_data) | ||
675 | { | 629 | { |
676 | unsigned int ioaddr; | 630 | unsigned int ioaddr; |
677 | 631 | ||
678 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { | 632 | if ((p_dev->resource[0]->start & 0xf) == 8) |
679 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | 633 | return -ENODEV; |
680 | p_dev->resource[1]->start = cf->io.win[0].base; | 634 | |
681 | p_dev->resource[0]->start = ioaddr; | 635 | p_dev->resource[0]->end = 16; |
682 | if (!pcmcia_request_io(p_dev)) | 636 | p_dev->resource[1]->end = 8; |
683 | return 0; | 637 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
684 | } | 638 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; |
639 | p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | ||
640 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
641 | p_dev->io_lines = 10; | ||
642 | |||
643 | p_dev->resource[1]->start = p_dev->resource[0]->start; | ||
644 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | ||
645 | p_dev->resource[0]->start = ioaddr; | ||
646 | if (!pcmcia_request_io(p_dev)) | ||
647 | return 0; | ||
685 | } | 648 | } |
686 | return -ENODEV; | 649 | return -ENODEV; |
687 | } | 650 | } |
688 | 651 | ||
689 | static int | 652 | static int |
690 | xirc2ps_config_check(struct pcmcia_device *p_dev, | 653 | xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data) |
691 | cistpl_cftable_entry_t *cf, | ||
692 | cistpl_cftable_entry_t *dflt, | ||
693 | unsigned int vcc, | ||
694 | void *priv_data) | ||
695 | { | 654 | { |
696 | int *pass = priv_data; | 655 | int *pass = priv_data; |
656 | resource_size_t tmp = p_dev->resource[1]->start; | ||
697 | 657 | ||
698 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { | 658 | tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8) |
699 | p_dev->resource[1]->start = cf->io.win[0].base; | 659 | : (p_dev->config_index & 0x20 ? 8 : -24)); |
700 | p_dev->resource[0]->start = p_dev->resource[1]->start | 660 | |
701 | + (*pass ? (cf->index & 0x20 ? -24:8) | 661 | if ((p_dev->resource[0]->start & 0xf) == 8) |
702 | : (cf->index & 0x20 ? 8:-24)); | 662 | return -ENODEV; |
703 | if (!pcmcia_request_io(p_dev)) | 663 | |
704 | return 0; | 664 | p_dev->resource[0]->end = 18; |
705 | } | 665 | p_dev->resource[1]->end = 8; |
706 | return -ENODEV; | 666 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
667 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | ||
668 | p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; | ||
669 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
670 | p_dev->io_lines = 10; | ||
707 | 671 | ||
672 | p_dev->resource[1]->start = p_dev->resource[0]->start; | ||
673 | p_dev->resource[0]->start = tmp; | ||
674 | return pcmcia_request_io(p_dev); | ||
708 | } | 675 | } |
709 | 676 | ||
710 | 677 | ||
@@ -727,11 +694,6 @@ static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev, | |||
727 | }; | 694 | }; |
728 | 695 | ||
729 | 696 | ||
730 | /**************** | ||
731 | * xirc2ps_config() is scheduled to run after a CARD_INSERTION event | ||
732 | * is received, to configure the PCMCIA socket, and to make the | ||
733 | * ethernet device available to the system. | ||
734 | */ | ||
735 | static int | 697 | static int |
736 | xirc2ps_config(struct pcmcia_device * link) | 698 | xirc2ps_config(struct pcmcia_device * link) |
737 | { | 699 | { |
@@ -807,32 +769,24 @@ xirc2ps_config(struct pcmcia_device * link) | |||
807 | goto failure; | 769 | goto failure; |
808 | } | 770 | } |
809 | 771 | ||
810 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | ||
811 | link->io_lines = 10; | ||
812 | if (local->modem) { | 772 | if (local->modem) { |
813 | int pass; | 773 | int pass; |
774 | link->config_flags |= CONF_AUTO_SET_IO; | ||
814 | 775 | ||
815 | if (do_sound) { | ||
816 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
817 | link->conf.Status |= CCSR_AUDIO_ENA; | ||
818 | } | ||
819 | link->resource[1]->end = 8; | ||
820 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
821 | if (local->dingo) { | 776 | if (local->dingo) { |
822 | /* Take the Modem IO port from the CIS and scan for a free | 777 | /* Take the Modem IO port from the CIS and scan for a free |
823 | * Ethernet port */ | 778 | * Ethernet port */ |
824 | link->resource[0]->end = 16; /* no Mako stuff anymore */ | ||
825 | if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL)) | 779 | if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL)) |
826 | goto port_found; | 780 | goto port_found; |
827 | } else { | 781 | } else { |
828 | link->resource[0]->end = 18; | ||
829 | /* We do 2 passes here: The first one uses the regular mapping and | 782 | /* We do 2 passes here: The first one uses the regular mapping and |
830 | * the second tries again, thereby considering that the 32 ports are | 783 | * the second tries again, thereby considering that the 32 ports are |
831 | * mirrored every 32 bytes. Actually we use a mirrored port for | 784 | * mirrored every 32 bytes. Actually we use a mirrored port for |
832 | * the Mako if (on the first pass) the COR bit 5 is set. | 785 | * the Mako if (on the first pass) the COR bit 5 is set. |
833 | */ | 786 | */ |
834 | for (pass=0; pass < 2; pass++) | 787 | for (pass=0; pass < 2; pass++) |
835 | if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass)) | 788 | if (!pcmcia_loop_config(link, xirc2ps_config_check, |
789 | &pass)) | ||
836 | goto port_found; | 790 | goto port_found; |
837 | /* if special option: | 791 | /* if special option: |
838 | * try to configure as Ethernet only. | 792 | * try to configure as Ethernet only. |
@@ -840,7 +794,9 @@ xirc2ps_config(struct pcmcia_device * link) | |||
840 | } | 794 | } |
841 | printk(KNOT_XIRC "no ports available\n"); | 795 | printk(KNOT_XIRC "no ports available\n"); |
842 | } else { | 796 | } else { |
797 | link->io_lines = 10; | ||
843 | link->resource[0]->end = 16; | 798 | link->resource[0]->end = 16; |
799 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | ||
844 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | 800 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { |
845 | link->resource[0]->start = ioaddr; | 801 | link->resource[0]->start = ioaddr; |
846 | if (!(err = pcmcia_request_io(link))) | 802 | if (!(err = pcmcia_request_io(link))) |
@@ -861,16 +817,14 @@ xirc2ps_config(struct pcmcia_device * link) | |||
861 | if ((err=pcmcia_request_irq(link, xirc2ps_interrupt))) | 817 | if ((err=pcmcia_request_irq(link, xirc2ps_interrupt))) |
862 | goto config_error; | 818 | goto config_error; |
863 | 819 | ||
864 | /**************** | 820 | link->config_flags |= CONF_ENABLE_IRQ; |
865 | * This actually configures the PCMCIA socket -- setting up | 821 | if (do_sound) |
866 | * the I/O windows and the interrupt mapping. | 822 | link->config_flags |= CONF_ENABLE_SPKR; |
867 | */ | 823 | |
868 | if ((err=pcmcia_request_configuration(link, &link->conf))) | 824 | if ((err = pcmcia_enable_device(link))) |
869 | goto config_error; | 825 | goto config_error; |
870 | 826 | ||
871 | if (local->dingo) { | 827 | if (local->dingo) { |
872 | win_req_t req; | ||
873 | |||
874 | /* Reset the modem's BAR to the correct value | 828 | /* Reset the modem's BAR to the correct value |
875 | * This is necessary because in the RequestConfiguration call, | 829 | * This is necessary because in the RequestConfiguration call, |
876 | * the base address of the ethernet port (BasePort1) is written | 830 | * the base address of the ethernet port (BasePort1) is written |
@@ -890,14 +844,14 @@ xirc2ps_config(struct pcmcia_device * link) | |||
890 | * is at 0x0800. So we allocate a window into the attribute | 844 | * is at 0x0800. So we allocate a window into the attribute |
891 | * memory and write direct to the CIS registers | 845 | * memory and write direct to the CIS registers |
892 | */ | 846 | */ |
893 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 847 | link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | |
894 | req.Base = req.Size = 0; | 848 | WIN_ENABLE; |
895 | req.AccessSpeed = 0; | 849 | link->resource[2]->start = link->resource[2]->end = 0; |
896 | if ((err = pcmcia_request_window(link, &req, &link->win))) | 850 | if ((err = pcmcia_request_window(link, link->resource[2], 0))) |
897 | goto config_error; | 851 | goto config_error; |
898 | 852 | ||
899 | local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; | 853 | local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800; |
900 | if ((err = pcmcia_map_mem_page(link, link->win, 0))) | 854 | if ((err = pcmcia_map_mem_page(link, link->resource[2], 0))) |
901 | goto config_error; | 855 | goto config_error; |
902 | 856 | ||
903 | /* Setup the CCRs; there are no infos in the CIS about the Ethernet | 857 | /* Setup the CCRs; there are no infos in the CIS about the Ethernet |
@@ -978,17 +932,12 @@ xirc2ps_config(struct pcmcia_device * link) | |||
978 | return -ENODEV; | 932 | return -ENODEV; |
979 | } /* xirc2ps_config */ | 933 | } /* xirc2ps_config */ |
980 | 934 | ||
981 | /**************** | ||
982 | * After a card is removed, xirc2ps_release() will unregister the net | ||
983 | * device, and release the PCMCIA configuration. If the device is | ||
984 | * still open, this will be postponed until it is closed. | ||
985 | */ | ||
986 | static void | 935 | static void |
987 | xirc2ps_release(struct pcmcia_device *link) | 936 | xirc2ps_release(struct pcmcia_device *link) |
988 | { | 937 | { |
989 | dev_dbg(&link->dev, "release\n"); | 938 | dev_dbg(&link->dev, "release\n"); |
990 | 939 | ||
991 | if (link->win) { | 940 | if (link->resource[2]->end) { |
992 | struct net_device *dev = link->priv; | 941 | struct net_device *dev = link->priv; |
993 | local_info_t *local = netdev_priv(dev); | 942 | local_info_t *local = netdev_priv(dev); |
994 | if (local->dingo) | 943 | if (local->dingo) |
@@ -1830,9 +1779,7 @@ MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); | |||
1830 | 1779 | ||
1831 | static struct pcmcia_driver xirc2ps_cs_driver = { | 1780 | static struct pcmcia_driver xirc2ps_cs_driver = { |
1832 | .owner = THIS_MODULE, | 1781 | .owner = THIS_MODULE, |
1833 | .drv = { | 1782 | .name = "xirc2ps_cs", |
1834 | .name = "xirc2ps_cs", | ||
1835 | }, | ||
1836 | .probe = xirc2ps_probe, | 1783 | .probe = xirc2ps_probe, |
1837 | .remove = xirc2ps_detach, | 1784 | .remove = xirc2ps_detach, |
1838 | .id_table = xirc2ps_ids, | 1785 | .id_table = xirc2ps_ids, |
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index af50a530daee..78d70a6481bf 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c | |||
@@ -184,7 +184,7 @@ ppp_asynctty_open(struct tty_struct *tty) | |||
184 | tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap); | 184 | tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap); |
185 | 185 | ||
186 | atomic_set(&ap->refcnt, 1); | 186 | atomic_set(&ap->refcnt, 1); |
187 | init_MUTEX_LOCKED(&ap->dead_sem); | 187 | sema_init(&ap->dead_sem, 0); |
188 | 188 | ||
189 | ap->chan.private = ap; | 189 | ap->chan.private = ap; |
190 | ap->chan.ops = &async_ops; | 190 | ap->chan.ops = &async_ops; |
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a0da4a17b025..992db2fa136e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -1212,7 +1212,8 @@ static void rtl8169_update_counters(struct net_device *dev) | |||
1212 | if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) | 1212 | if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) |
1213 | return; | 1213 | return; |
1214 | 1214 | ||
1215 | counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); | 1215 | counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters), |
1216 | &paddr, GFP_KERNEL); | ||
1216 | if (!counters) | 1217 | if (!counters) |
1217 | return; | 1218 | return; |
1218 | 1219 | ||
@@ -1233,7 +1234,8 @@ static void rtl8169_update_counters(struct net_device *dev) | |||
1233 | RTL_W32(CounterAddrLow, 0); | 1234 | RTL_W32(CounterAddrLow, 0); |
1234 | RTL_W32(CounterAddrHigh, 0); | 1235 | RTL_W32(CounterAddrHigh, 0); |
1235 | 1236 | ||
1236 | pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); | 1237 | dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters, |
1238 | paddr); | ||
1237 | } | 1239 | } |
1238 | 1240 | ||
1239 | static void rtl8169_get_ethtool_stats(struct net_device *dev, | 1241 | static void rtl8169_get_ethtool_stats(struct net_device *dev, |
@@ -3292,15 +3294,15 @@ static int rtl8169_open(struct net_device *dev) | |||
3292 | 3294 | ||
3293 | /* | 3295 | /* |
3294 | * Rx and Tx desscriptors needs 256 bytes alignment. | 3296 | * Rx and Tx desscriptors needs 256 bytes alignment. |
3295 | * pci_alloc_consistent provides more. | 3297 | * dma_alloc_coherent provides more. |
3296 | */ | 3298 | */ |
3297 | tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, | 3299 | tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, |
3298 | &tp->TxPhyAddr); | 3300 | &tp->TxPhyAddr, GFP_KERNEL); |
3299 | if (!tp->TxDescArray) | 3301 | if (!tp->TxDescArray) |
3300 | goto err_pm_runtime_put; | 3302 | goto err_pm_runtime_put; |
3301 | 3303 | ||
3302 | tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, | 3304 | tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, |
3303 | &tp->RxPhyAddr); | 3305 | &tp->RxPhyAddr, GFP_KERNEL); |
3304 | if (!tp->RxDescArray) | 3306 | if (!tp->RxDescArray) |
3305 | goto err_free_tx_0; | 3307 | goto err_free_tx_0; |
3306 | 3308 | ||
@@ -3334,12 +3336,12 @@ out: | |||
3334 | err_release_ring_2: | 3336 | err_release_ring_2: |
3335 | rtl8169_rx_clear(tp); | 3337 | rtl8169_rx_clear(tp); |
3336 | err_free_rx_1: | 3338 | err_free_rx_1: |
3337 | pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, | 3339 | dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, |
3338 | tp->RxPhyAddr); | 3340 | tp->RxPhyAddr); |
3339 | tp->RxDescArray = NULL; | 3341 | tp->RxDescArray = NULL; |
3340 | err_free_tx_0: | 3342 | err_free_tx_0: |
3341 | pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, | 3343 | dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, |
3342 | tp->TxPhyAddr); | 3344 | tp->TxPhyAddr); |
3343 | tp->TxDescArray = NULL; | 3345 | tp->TxDescArray = NULL; |
3344 | err_pm_runtime_put: | 3346 | err_pm_runtime_put: |
3345 | pm_runtime_put_noidle(&pdev->dev); | 3347 | pm_runtime_put_noidle(&pdev->dev); |
@@ -3975,7 +3977,7 @@ static void rtl8169_free_rx_skb(struct rtl8169_private *tp, | |||
3975 | { | 3977 | { |
3976 | struct pci_dev *pdev = tp->pci_dev; | 3978 | struct pci_dev *pdev = tp->pci_dev; |
3977 | 3979 | ||
3978 | pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, | 3980 | dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, |
3979 | PCI_DMA_FROMDEVICE); | 3981 | PCI_DMA_FROMDEVICE); |
3980 | dev_kfree_skb(*sk_buff); | 3982 | dev_kfree_skb(*sk_buff); |
3981 | *sk_buff = NULL; | 3983 | *sk_buff = NULL; |
@@ -4000,7 +4002,7 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, | |||
4000 | static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, | 4002 | static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, |
4001 | struct net_device *dev, | 4003 | struct net_device *dev, |
4002 | struct RxDesc *desc, int rx_buf_sz, | 4004 | struct RxDesc *desc, int rx_buf_sz, |
4003 | unsigned int align) | 4005 | unsigned int align, gfp_t gfp) |
4004 | { | 4006 | { |
4005 | struct sk_buff *skb; | 4007 | struct sk_buff *skb; |
4006 | dma_addr_t mapping; | 4008 | dma_addr_t mapping; |
@@ -4008,13 +4010,13 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, | |||
4008 | 4010 | ||
4009 | pad = align ? align : NET_IP_ALIGN; | 4011 | pad = align ? align : NET_IP_ALIGN; |
4010 | 4012 | ||
4011 | skb = netdev_alloc_skb(dev, rx_buf_sz + pad); | 4013 | skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); |
4012 | if (!skb) | 4014 | if (!skb) |
4013 | goto err_out; | 4015 | goto err_out; |
4014 | 4016 | ||
4015 | skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); | 4017 | skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); |
4016 | 4018 | ||
4017 | mapping = pci_map_single(pdev, skb->data, rx_buf_sz, | 4019 | mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, |
4018 | PCI_DMA_FROMDEVICE); | 4020 | PCI_DMA_FROMDEVICE); |
4019 | 4021 | ||
4020 | rtl8169_map_to_asic(desc, mapping, rx_buf_sz); | 4022 | rtl8169_map_to_asic(desc, mapping, rx_buf_sz); |
@@ -4039,7 +4041,7 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) | |||
4039 | } | 4041 | } |
4040 | 4042 | ||
4041 | static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, | 4043 | static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, |
4042 | u32 start, u32 end) | 4044 | u32 start, u32 end, gfp_t gfp) |
4043 | { | 4045 | { |
4044 | u32 cur; | 4046 | u32 cur; |
4045 | 4047 | ||
@@ -4054,7 +4056,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, | |||
4054 | 4056 | ||
4055 | skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, | 4057 | skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, |
4056 | tp->RxDescArray + i, | 4058 | tp->RxDescArray + i, |
4057 | tp->rx_buf_sz, tp->align); | 4059 | tp->rx_buf_sz, tp->align, gfp); |
4058 | if (!skb) | 4060 | if (!skb) |
4059 | break; | 4061 | break; |
4060 | 4062 | ||
@@ -4082,7 +4084,7 @@ static int rtl8169_init_ring(struct net_device *dev) | |||
4082 | memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); | 4084 | memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); |
4083 | memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); | 4085 | memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); |
4084 | 4086 | ||
4085 | if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) | 4087 | if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) |
4086 | goto err_out; | 4088 | goto err_out; |
4087 | 4089 | ||
4088 | rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); | 4090 | rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); |
@@ -4099,7 +4101,8 @@ static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, | |||
4099 | { | 4101 | { |
4100 | unsigned int len = tx_skb->len; | 4102 | unsigned int len = tx_skb->len; |
4101 | 4103 | ||
4102 | pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); | 4104 | dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, |
4105 | PCI_DMA_TODEVICE); | ||
4103 | desc->opts1 = 0x00; | 4106 | desc->opts1 = 0x00; |
4104 | desc->opts2 = 0x00; | 4107 | desc->opts2 = 0x00; |
4105 | desc->addr = 0x00; | 4108 | desc->addr = 0x00; |
@@ -4243,7 +4246,8 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, | |||
4243 | txd = tp->TxDescArray + entry; | 4246 | txd = tp->TxDescArray + entry; |
4244 | len = frag->size; | 4247 | len = frag->size; |
4245 | addr = ((void *) page_address(frag->page)) + frag->page_offset; | 4248 | addr = ((void *) page_address(frag->page)) + frag->page_offset; |
4246 | mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); | 4249 | mapping = dma_map_single(&tp->pci_dev->dev, addr, len, |
4250 | PCI_DMA_TODEVICE); | ||
4247 | 4251 | ||
4248 | /* anti gcc 2.95.3 bugware (sic) */ | 4252 | /* anti gcc 2.95.3 bugware (sic) */ |
4249 | status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); | 4253 | status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); |
@@ -4313,7 +4317,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, | |||
4313 | tp->tx_skb[entry].skb = skb; | 4317 | tp->tx_skb[entry].skb = skb; |
4314 | } | 4318 | } |
4315 | 4319 | ||
4316 | mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); | 4320 | mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, |
4321 | PCI_DMA_TODEVICE); | ||
4317 | 4322 | ||
4318 | tp->tx_skb[entry].len = len; | 4323 | tp->tx_skb[entry].len = len; |
4319 | txd->addr = cpu_to_le64(mapping); | 4324 | txd->addr = cpu_to_le64(mapping); |
@@ -4477,8 +4482,8 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, | |||
4477 | if (!skb) | 4482 | if (!skb) |
4478 | goto out; | 4483 | goto out; |
4479 | 4484 | ||
4480 | pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, | 4485 | dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, |
4481 | PCI_DMA_FROMDEVICE); | 4486 | PCI_DMA_FROMDEVICE); |
4482 | skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); | 4487 | skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); |
4483 | *sk_buff = skb; | 4488 | *sk_buff = skb; |
4484 | done = true; | 4489 | done = true; |
@@ -4549,11 +4554,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev, | |||
4549 | rtl8169_rx_csum(skb, desc); | 4554 | rtl8169_rx_csum(skb, desc); |
4550 | 4555 | ||
4551 | if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { | 4556 | if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { |
4552 | pci_dma_sync_single_for_device(pdev, addr, | 4557 | dma_sync_single_for_device(&pdev->dev, addr, |
4553 | pkt_size, PCI_DMA_FROMDEVICE); | 4558 | pkt_size, PCI_DMA_FROMDEVICE); |
4554 | rtl8169_mark_to_asic(desc, tp->rx_buf_sz); | 4559 | rtl8169_mark_to_asic(desc, tp->rx_buf_sz); |
4555 | } else { | 4560 | } else { |
4556 | pci_unmap_single(pdev, addr, tp->rx_buf_sz, | 4561 | dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, |
4557 | PCI_DMA_FROMDEVICE); | 4562 | PCI_DMA_FROMDEVICE); |
4558 | tp->Rx_skbuff[entry] = NULL; | 4563 | tp->Rx_skbuff[entry] = NULL; |
4559 | } | 4564 | } |
@@ -4583,7 +4588,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, | |||
4583 | count = cur_rx - tp->cur_rx; | 4588 | count = cur_rx - tp->cur_rx; |
4584 | tp->cur_rx = cur_rx; | 4589 | tp->cur_rx = cur_rx; |
4585 | 4590 | ||
4586 | delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); | 4591 | delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); |
4587 | if (!delta && count) | 4592 | if (!delta && count) |
4588 | netif_info(tp, intr, dev, "no Rx buffer allocated\n"); | 4593 | netif_info(tp, intr, dev, "no Rx buffer allocated\n"); |
4589 | tp->dirty_rx += delta; | 4594 | tp->dirty_rx += delta; |
@@ -4769,10 +4774,10 @@ static int rtl8169_close(struct net_device *dev) | |||
4769 | 4774 | ||
4770 | free_irq(dev->irq, dev); | 4775 | free_irq(dev->irq, dev); |
4771 | 4776 | ||
4772 | pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, | 4777 | dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, |
4773 | tp->RxPhyAddr); | 4778 | tp->RxPhyAddr); |
4774 | pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, | 4779 | dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, |
4775 | tp->TxPhyAddr); | 4780 | tp->TxPhyAddr); |
4776 | tp->TxDescArray = NULL; | 4781 | tp->TxDescArray = NULL; |
4777 | tp->RxDescArray = NULL; | 4782 | tp->RxDescArray = NULL; |
4778 | 4783 | ||
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 40e5c46e7571..465ae7e84507 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/mii.h> | 44 | #include <linux/mii.h> |
45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
46 | #include <linux/dmi.h> | ||
46 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
47 | 48 | ||
48 | #include "skge.h" | 49 | #include "skge.h" |
@@ -3868,6 +3869,8 @@ static void __devinit skge_show_addr(struct net_device *dev) | |||
3868 | netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); | 3869 | netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); |
3869 | } | 3870 | } |
3870 | 3871 | ||
3872 | static int only_32bit_dma; | ||
3873 | |||
3871 | static int __devinit skge_probe(struct pci_dev *pdev, | 3874 | static int __devinit skge_probe(struct pci_dev *pdev, |
3872 | const struct pci_device_id *ent) | 3875 | const struct pci_device_id *ent) |
3873 | { | 3876 | { |
@@ -3889,7 +3892,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
3889 | 3892 | ||
3890 | pci_set_master(pdev); | 3893 | pci_set_master(pdev); |
3891 | 3894 | ||
3892 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | 3895 | if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { |
3893 | using_dac = 1; | 3896 | using_dac = 1; |
3894 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | 3897 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); |
3895 | } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { | 3898 | } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { |
@@ -4147,8 +4150,21 @@ static struct pci_driver skge_driver = { | |||
4147 | .shutdown = skge_shutdown, | 4150 | .shutdown = skge_shutdown, |
4148 | }; | 4151 | }; |
4149 | 4152 | ||
4153 | static struct dmi_system_id skge_32bit_dma_boards[] = { | ||
4154 | { | ||
4155 | .ident = "Gigabyte nForce boards", | ||
4156 | .matches = { | ||
4157 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), | ||
4158 | DMI_MATCH(DMI_BOARD_NAME, "nForce"), | ||
4159 | }, | ||
4160 | }, | ||
4161 | {} | ||
4162 | }; | ||
4163 | |||
4150 | static int __init skge_init_module(void) | 4164 | static int __init skge_init_module(void) |
4151 | { | 4165 | { |
4166 | if (dmi_check_system(skge_32bit_dma_boards)) | ||
4167 | only_32bit_dma = 1; | ||
4152 | skge_debug_init(); | 4168 | skge_debug_init(); |
4153 | return pci_register_driver(&skge_driver); | 4169 | return pci_register_driver(&skge_driver); |
4154 | } | 4170 | } |
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 10cf0cbc2185..726df611ee17 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
@@ -72,6 +72,7 @@ static const char version[] = | |||
72 | #include <linux/sched.h> | 72 | #include <linux/sched.h> |
73 | #include <linux/delay.h> | 73 | #include <linux/delay.h> |
74 | #include <linux/interrupt.h> | 74 | #include <linux/interrupt.h> |
75 | #include <linux/irq.h> | ||
75 | #include <linux/errno.h> | 76 | #include <linux/errno.h> |
76 | #include <linux/ioport.h> | 77 | #include <linux/ioport.h> |
77 | #include <linux/crc32.h> | 78 | #include <linux/crc32.h> |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bc3af78a869f..1ec4b9e0239a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4666,7 +4666,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) | |||
4666 | desc_idx, *post_ptr); | 4666 | desc_idx, *post_ptr); |
4667 | drop_it_no_recycle: | 4667 | drop_it_no_recycle: |
4668 | /* Other statistics kept track of by card. */ | 4668 | /* Other statistics kept track of by card. */ |
4669 | tp->net_stats.rx_dropped++; | 4669 | tp->rx_dropped++; |
4670 | goto next_pkt; | 4670 | goto next_pkt; |
4671 | } | 4671 | } |
4672 | 4672 | ||
@@ -4726,7 +4726,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) | |||
4726 | if (len > (tp->dev->mtu + ETH_HLEN) && | 4726 | if (len > (tp->dev->mtu + ETH_HLEN) && |
4727 | skb->protocol != htons(ETH_P_8021Q)) { | 4727 | skb->protocol != htons(ETH_P_8021Q)) { |
4728 | dev_kfree_skb(skb); | 4728 | dev_kfree_skb(skb); |
4729 | goto next_pkt; | 4729 | goto drop_it_no_recycle; |
4730 | } | 4730 | } |
4731 | 4731 | ||
4732 | if (desc->type_flags & RXD_FLAG_VLAN && | 4732 | if (desc->type_flags & RXD_FLAG_VLAN && |
@@ -9240,6 +9240,8 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, | |||
9240 | stats->rx_missed_errors = old_stats->rx_missed_errors + | 9240 | stats->rx_missed_errors = old_stats->rx_missed_errors + |
9241 | get_stat64(&hw_stats->rx_discards); | 9241 | get_stat64(&hw_stats->rx_discards); |
9242 | 9242 | ||
9243 | stats->rx_dropped = tp->rx_dropped; | ||
9244 | |||
9243 | return stats; | 9245 | return stats; |
9244 | } | 9246 | } |
9245 | 9247 | ||
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 4937bd190964..be7ff138a7f9 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2759,7 +2759,7 @@ struct tg3 { | |||
2759 | 2759 | ||
2760 | 2760 | ||
2761 | /* begin "everything else" cacheline(s) section */ | 2761 | /* begin "everything else" cacheline(s) section */ |
2762 | struct rtnl_link_stats64 net_stats; | 2762 | unsigned long rx_dropped; |
2763 | struct rtnl_link_stats64 net_stats_prev; | 2763 | struct rtnl_link_stats64 net_stats_prev; |
2764 | struct tg3_ethtool_stats estats; | 2764 | struct tg3_ethtool_stats estats; |
2765 | struct tg3_ethtool_stats estats_prev; | 2765 | struct tg3_ethtool_stats estats_prev; |
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 04c6cd4333f1..10bafd59f9c3 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c | |||
@@ -575,7 +575,7 @@ static int cosa_probe(int base, int irq, int dma) | |||
575 | 575 | ||
576 | /* Initialize the chardev data structures */ | 576 | /* Initialize the chardev data structures */ |
577 | mutex_init(&chan->rlock); | 577 | mutex_init(&chan->rlock); |
578 | init_MUTEX(&chan->wsem); | 578 | sema_init(&chan->wsem, 1); |
579 | 579 | ||
580 | /* Register the network interface */ | 580 | /* Register the network interface */ |
581 | if (!(chan->netdev = alloc_hdlcdev(chan))) { | 581 | if (!(chan->netdev = alloc_hdlcdev(chan))) { |
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 8cc9e319f435..1737d1488b35 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c | |||
@@ -1244,16 +1244,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) | |||
1244 | int i, result; | 1244 | int i, result; |
1245 | struct device *dev = i2400m_dev(i2400m); | 1245 | struct device *dev = i2400m_dev(i2400m); |
1246 | const struct i2400m_msg_hdr *msg_hdr; | 1246 | const struct i2400m_msg_hdr *msg_hdr; |
1247 | size_t pl_itr, pl_size, skb_len; | 1247 | size_t pl_itr, pl_size; |
1248 | unsigned long flags; | 1248 | unsigned long flags; |
1249 | unsigned num_pls, single_last; | 1249 | unsigned num_pls, single_last, skb_len; |
1250 | 1250 | ||
1251 | skb_len = skb->len; | 1251 | skb_len = skb->len; |
1252 | d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n", | 1252 | d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n", |
1253 | i2400m, skb, skb_len); | 1253 | i2400m, skb, skb_len); |
1254 | result = -EIO; | 1254 | result = -EIO; |
1255 | msg_hdr = (void *) skb->data; | 1255 | msg_hdr = (void *) skb->data; |
1256 | result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len); | 1256 | result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len); |
1257 | if (result < 0) | 1257 | if (result < 0) |
1258 | goto error_msg_hdr_check; | 1258 | goto error_msg_hdr_check; |
1259 | result = -EIO; | 1259 | result = -EIO; |
@@ -1261,10 +1261,10 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) | |||
1261 | pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ | 1261 | pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ |
1262 | num_pls * sizeof(msg_hdr->pld[0]); | 1262 | num_pls * sizeof(msg_hdr->pld[0]); |
1263 | pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); | 1263 | pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); |
1264 | if (pl_itr > skb->len) { /* got all the payload descriptors? */ | 1264 | if (pl_itr > skb_len) { /* got all the payload descriptors? */ |
1265 | dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " | 1265 | dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " |
1266 | "%u payload descriptors (%zu each, total %zu)\n", | 1266 | "%u payload descriptors (%zu each, total %zu)\n", |
1267 | skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); | 1267 | skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); |
1268 | goto error_pl_descr_short; | 1268 | goto error_pl_descr_short; |
1269 | } | 1269 | } |
1270 | /* Walk each payload payload--check we really got it */ | 1270 | /* Walk each payload payload--check we really got it */ |
@@ -1272,7 +1272,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) | |||
1272 | /* work around old gcc warnings */ | 1272 | /* work around old gcc warnings */ |
1273 | pl_size = i2400m_pld_size(&msg_hdr->pld[i]); | 1273 | pl_size = i2400m_pld_size(&msg_hdr->pld[i]); |
1274 | result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i], | 1274 | result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i], |
1275 | pl_itr, skb->len); | 1275 | pl_itr, skb_len); |
1276 | if (result < 0) | 1276 | if (result < 0) |
1277 | goto error_pl_descr_check; | 1277 | goto error_pl_descr_check; |
1278 | single_last = num_pls == 1 || i == num_pls - 1; | 1278 | single_last = num_pls == 1 || i == num_pls - 1; |
@@ -1290,16 +1290,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) | |||
1290 | if (i < i2400m->rx_pl_min) | 1290 | if (i < i2400m->rx_pl_min) |
1291 | i2400m->rx_pl_min = i; | 1291 | i2400m->rx_pl_min = i; |
1292 | i2400m->rx_num++; | 1292 | i2400m->rx_num++; |
1293 | i2400m->rx_size_acc += skb->len; | 1293 | i2400m->rx_size_acc += skb_len; |
1294 | if (skb->len < i2400m->rx_size_min) | 1294 | if (skb_len < i2400m->rx_size_min) |
1295 | i2400m->rx_size_min = skb->len; | 1295 | i2400m->rx_size_min = skb_len; |
1296 | if (skb->len > i2400m->rx_size_max) | 1296 | if (skb_len > i2400m->rx_size_max) |
1297 | i2400m->rx_size_max = skb->len; | 1297 | i2400m->rx_size_max = skb_len; |
1298 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | 1298 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); |
1299 | error_pl_descr_check: | 1299 | error_pl_descr_check: |
1300 | error_pl_descr_short: | 1300 | error_pl_descr_short: |
1301 | error_msg_hdr_check: | 1301 | error_msg_hdr_check: |
1302 | d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n", | 1302 | d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n", |
1303 | i2400m, skb, skb_len, result); | 1303 | i2400m, skb, skb_len, result); |
1304 | return result; | 1304 | return result; |
1305 | } | 1305 | } |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 9a121a5b787c..df2484d45474 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
33 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
34 | 34 | ||
35 | #include <pcmcia/cs.h> | ||
36 | #include <pcmcia/cistpl.h> | 35 | #include <pcmcia/cistpl.h> |
37 | #include <pcmcia/cisreg.h> | 36 | #include <pcmcia/cisreg.h> |
38 | #include <pcmcia/ds.h> | 37 | #include <pcmcia/ds.h> |
@@ -54,58 +53,21 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); | |||
54 | 53 | ||
55 | /*====================================================================*/ | 54 | /*====================================================================*/ |
56 | 55 | ||
57 | /* | ||
58 | The event() function is this driver's Card Services event handler. | ||
59 | It will be called by Card Services when an appropriate card status | ||
60 | event is received. The config() and release() entry points are | ||
61 | used to configure or release a socket, in response to card | ||
62 | insertion and ejection events. They are invoked from the airo_cs | ||
63 | event handler. | ||
64 | */ | ||
65 | |||
66 | static int airo_config(struct pcmcia_device *link); | 56 | static int airo_config(struct pcmcia_device *link); |
67 | static void airo_release(struct pcmcia_device *link); | 57 | static void airo_release(struct pcmcia_device *link); |
68 | 58 | ||
69 | /* | ||
70 | The attach() and detach() entry points are used to create and destroy | ||
71 | "instances" of the driver, where each instance represents everything | ||
72 | needed to manage one actual PCMCIA card. | ||
73 | */ | ||
74 | |||
75 | static void airo_detach(struct pcmcia_device *p_dev); | 59 | static void airo_detach(struct pcmcia_device *p_dev); |
76 | 60 | ||
77 | typedef struct local_info_t { | 61 | typedef struct local_info_t { |
78 | struct net_device *eth_dev; | 62 | struct net_device *eth_dev; |
79 | } local_info_t; | 63 | } local_info_t; |
80 | 64 | ||
81 | /*====================================================================== | ||
82 | |||
83 | airo_attach() creates an "instance" of the driver, allocating | ||
84 | local data structures for one device. The device is registered | ||
85 | with Card Services. | ||
86 | |||
87 | The dev_link structure is initialized, but we don't actually | ||
88 | configure the card at this point -- we wait until we receive a | ||
89 | card insertion event. | ||
90 | |||
91 | ======================================================================*/ | ||
92 | |||
93 | static int airo_probe(struct pcmcia_device *p_dev) | 65 | static int airo_probe(struct pcmcia_device *p_dev) |
94 | { | 66 | { |
95 | local_info_t *local; | 67 | local_info_t *local; |
96 | 68 | ||
97 | dev_dbg(&p_dev->dev, "airo_attach()\n"); | 69 | dev_dbg(&p_dev->dev, "airo_attach()\n"); |
98 | 70 | ||
99 | /* | ||
100 | General socket configuration defaults can go here. In this | ||
101 | client, we assume very little, and rely on the CIS for almost | ||
102 | everything. In most clients, many details (i.e., number, sizes, | ||
103 | and attributes of IO windows) are fixed by the nature of the | ||
104 | device, and can be hard-wired here. | ||
105 | */ | ||
106 | p_dev->conf.Attributes = 0; | ||
107 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
108 | |||
109 | /* Allocate space for private device-specific data */ | 71 | /* Allocate space for private device-specific data */ |
110 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 72 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
111 | if (!local) { | 73 | if (!local) { |
@@ -117,15 +79,6 @@ static int airo_probe(struct pcmcia_device *p_dev) | |||
117 | return airo_config(p_dev); | 79 | return airo_config(p_dev); |
118 | } /* airo_attach */ | 80 | } /* airo_attach */ |
119 | 81 | ||
120 | /*====================================================================== | ||
121 | |||
122 | This deletes a driver "instance". The device is de-registered | ||
123 | with Card Services. If it has been released, all local data | ||
124 | structures are freed. Otherwise, the structures will be freed | ||
125 | when the device is released. | ||
126 | |||
127 | ======================================================================*/ | ||
128 | |||
129 | static void airo_detach(struct pcmcia_device *link) | 82 | static void airo_detach(struct pcmcia_device *link) |
130 | { | 83 | { |
131 | dev_dbg(&link->dev, "airo_detach\n"); | 84 | dev_dbg(&link->dev, "airo_detach\n"); |
@@ -140,60 +93,12 @@ static void airo_detach(struct pcmcia_device *link) | |||
140 | kfree(link->priv); | 93 | kfree(link->priv); |
141 | } /* airo_detach */ | 94 | } /* airo_detach */ |
142 | 95 | ||
143 | /*====================================================================== | 96 | static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) |
144 | |||
145 | airo_config() is scheduled to run after a CARD_INSERTION event | ||
146 | is received, to configure the PCMCIA socket, and to make the | ||
147 | device available to the system. | ||
148 | |||
149 | ======================================================================*/ | ||
150 | |||
151 | static int airo_cs_config_check(struct pcmcia_device *p_dev, | ||
152 | cistpl_cftable_entry_t *cfg, | ||
153 | cistpl_cftable_entry_t *dflt, | ||
154 | unsigned int vcc, | ||
155 | void *priv_data) | ||
156 | { | 97 | { |
157 | if (cfg->index == 0) | 98 | if (p_dev->config_index == 0) |
158 | return -ENODEV; | 99 | return -EINVAL; |
159 | |||
160 | /* Does this card need audio output? */ | ||
161 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
162 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
163 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
164 | } | ||
165 | |||
166 | /* Use power settings for Vcc and Vpp if present */ | ||
167 | /* Note that the CIS values need to be rescaled */ | ||
168 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
169 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
170 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
171 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
172 | |||
173 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
174 | |||
175 | /* IO window settings */ | ||
176 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
177 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
178 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
179 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
180 | p_dev->resource[0]->flags |= | ||
181 | pcmcia_io_cfg_data_width(io->flags); | ||
182 | p_dev->resource[0]->start = io->win[0].base; | ||
183 | p_dev->resource[0]->end = io->win[0].len; | ||
184 | if (io->nwin > 1) { | ||
185 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
186 | p_dev->resource[1]->start = io->win[1].base; | ||
187 | p_dev->resource[1]->end = io->win[1].len; | ||
188 | } | ||
189 | } | ||
190 | 100 | ||
191 | /* This reserves IO space but doesn't actually enable it */ | 101 | return pcmcia_request_io(p_dev); |
192 | if (pcmcia_request_io(p_dev) != 0) | ||
193 | return -ENODEV; | ||
194 | |||
195 | /* If we got this far, we're cool! */ | ||
196 | return 0; | ||
197 | } | 102 | } |
198 | 103 | ||
199 | 104 | ||
@@ -206,20 +111,9 @@ static int airo_config(struct pcmcia_device *link) | |||
206 | 111 | ||
207 | dev_dbg(&link->dev, "airo_config\n"); | 112 | dev_dbg(&link->dev, "airo_config\n"); |
208 | 113 | ||
209 | /* | 114 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | |
210 | * In this loop, we scan the CIS for configuration table | 115 | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; |
211 | * entries, each of which describes a valid card | 116 | |
212 | * configuration, including voltage, IO window, memory window, | ||
213 | * and interrupt settings. | ||
214 | * | ||
215 | * We make no assumptions about the card to be configured: we | ||
216 | * use just the information available in the CIS. In an ideal | ||
217 | * world, this would work for any PCMCIA card, but it requires | ||
218 | * a complete and accurate CIS. In practice, a driver usually | ||
219 | * "knows" most of these things without consulting the CIS, | ||
220 | * and most client drivers will only use the CIS to fill in | ||
221 | * implementation-defined details. | ||
222 | */ | ||
223 | ret = pcmcia_loop_config(link, airo_cs_config_check, NULL); | 117 | ret = pcmcia_loop_config(link, airo_cs_config_check, NULL); |
224 | if (ret) | 118 | if (ret) |
225 | goto failed; | 119 | goto failed; |
@@ -227,12 +121,7 @@ static int airo_config(struct pcmcia_device *link) | |||
227 | if (!link->irq) | 121 | if (!link->irq) |
228 | goto failed; | 122 | goto failed; |
229 | 123 | ||
230 | /* | 124 | ret = pcmcia_enable_device(link); |
231 | This actually configures the PCMCIA socket -- setting up | ||
232 | the I/O windows and the interrupt mapping, and putting the | ||
233 | card and host interface into "Memory and IO" mode. | ||
234 | */ | ||
235 | ret = pcmcia_request_configuration(link, &link->conf); | ||
236 | if (ret) | 125 | if (ret) |
237 | goto failed; | 126 | goto failed; |
238 | ((local_info_t *)link->priv)->eth_dev = | 127 | ((local_info_t *)link->priv)->eth_dev = |
@@ -241,17 +130,6 @@ static int airo_config(struct pcmcia_device *link) | |||
241 | if (!((local_info_t *)link->priv)->eth_dev) | 130 | if (!((local_info_t *)link->priv)->eth_dev) |
242 | goto failed; | 131 | goto failed; |
243 | 132 | ||
244 | /* Finally, report what we've done */ | ||
245 | dev_info(&link->dev, "index 0x%02x: ", | ||
246 | link->conf.ConfigIndex); | ||
247 | if (link->conf.Vpp) | ||
248 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); | ||
249 | printk(", irq %d", link->irq); | ||
250 | if (link->resource[0]) | ||
251 | printk(" & %pR", link->resource[0]); | ||
252 | if (link->resource[1]) | ||
253 | printk(" & %pR", link->resource[1]); | ||
254 | printk("\n"); | ||
255 | return 0; | 133 | return 0; |
256 | 134 | ||
257 | failed: | 135 | failed: |
@@ -259,14 +137,6 @@ static int airo_config(struct pcmcia_device *link) | |||
259 | return -ENODEV; | 137 | return -ENODEV; |
260 | } /* airo_config */ | 138 | } /* airo_config */ |
261 | 139 | ||
262 | /*====================================================================== | ||
263 | |||
264 | After a card is removed, airo_release() will unregister the | ||
265 | device, and release the PCMCIA configuration. If the device is | ||
266 | still open, this will be postponed until it is closed. | ||
267 | |||
268 | ======================================================================*/ | ||
269 | |||
270 | static void airo_release(struct pcmcia_device *link) | 140 | static void airo_release(struct pcmcia_device *link) |
271 | { | 141 | { |
272 | dev_dbg(&link->dev, "airo_release\n"); | 142 | dev_dbg(&link->dev, "airo_release\n"); |
@@ -305,9 +175,7 @@ MODULE_DEVICE_TABLE(pcmcia, airo_ids); | |||
305 | 175 | ||
306 | static struct pcmcia_driver airo_driver = { | 176 | static struct pcmcia_driver airo_driver = { |
307 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
308 | .drv = { | 178 | .name = "airo_cs", |
309 | .name = "airo_cs", | ||
310 | }, | ||
311 | .probe = airo_probe, | 179 | .probe = airo_probe, |
312 | .remove = airo_detach, | 180 | .remove = airo_detach, |
313 | .id_table = airo_ids, | 181 | .id_table = airo_ids, |
@@ -315,12 +183,12 @@ static struct pcmcia_driver airo_driver = { | |||
315 | .resume = airo_resume, | 183 | .resume = airo_resume, |
316 | }; | 184 | }; |
317 | 185 | ||
318 | static int airo_cs_init(void) | 186 | static int __init airo_cs_init(void) |
319 | { | 187 | { |
320 | return pcmcia_register_driver(&airo_driver); | 188 | return pcmcia_register_driver(&airo_driver); |
321 | } | 189 | } |
322 | 190 | ||
323 | static void airo_cs_cleanup(void) | 191 | static void __exit airo_cs_cleanup(void) |
324 | { | 192 | { |
325 | pcmcia_unregister_driver(&airo_driver); | 193 | pcmcia_unregister_driver(&airo_driver); |
326 | } | 194 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cc648b6ae31c..a3d95cca8f0c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -543,7 +543,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | |||
543 | if (conf_is_ht40(conf)) | 543 | if (conf_is_ht40(conf)) |
544 | return clockrate * 2; | 544 | return clockrate * 2; |
545 | 545 | ||
546 | return clockrate * 2; | 546 | return clockrate; |
547 | } | 547 | } |
548 | 548 | ||
549 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 549 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 3b632161c106..c96e19da2949 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/moduleparam.h> | 42 | #include <linux/moduleparam.h> |
43 | #include <linux/device.h> | 43 | #include <linux/device.h> |
44 | 44 | ||
45 | #include <pcmcia/cs.h> | ||
46 | #include <pcmcia/cistpl.h> | 45 | #include <pcmcia/cistpl.h> |
47 | #include <pcmcia/cisreg.h> | 46 | #include <pcmcia/cisreg.h> |
48 | #include <pcmcia/ds.h> | 47 | #include <pcmcia/ds.h> |
@@ -64,58 +63,21 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); | |||
64 | 63 | ||
65 | /*====================================================================*/ | 64 | /*====================================================================*/ |
66 | 65 | ||
67 | /* | ||
68 | The event() function is this driver's Card Services event handler. | ||
69 | It will be called by Card Services when an appropriate card status | ||
70 | event is received. The config() and release() entry points are | ||
71 | used to configure or release a socket, in response to card | ||
72 | insertion and ejection events. They are invoked from the atmel_cs | ||
73 | event handler. | ||
74 | */ | ||
75 | |||
76 | static int atmel_config(struct pcmcia_device *link); | 66 | static int atmel_config(struct pcmcia_device *link); |
77 | static void atmel_release(struct pcmcia_device *link); | 67 | static void atmel_release(struct pcmcia_device *link); |
78 | 68 | ||
79 | /* | ||
80 | The attach() and detach() entry points are used to create and destroy | ||
81 | "instances" of the driver, where each instance represents everything | ||
82 | needed to manage one actual PCMCIA card. | ||
83 | */ | ||
84 | |||
85 | static void atmel_detach(struct pcmcia_device *p_dev); | 69 | static void atmel_detach(struct pcmcia_device *p_dev); |
86 | 70 | ||
87 | typedef struct local_info_t { | 71 | typedef struct local_info_t { |
88 | struct net_device *eth_dev; | 72 | struct net_device *eth_dev; |
89 | } local_info_t; | 73 | } local_info_t; |
90 | 74 | ||
91 | /*====================================================================== | ||
92 | |||
93 | atmel_attach() creates an "instance" of the driver, allocating | ||
94 | local data structures for one device. The device is registered | ||
95 | with Card Services. | ||
96 | |||
97 | The dev_link structure is initialized, but we don't actually | ||
98 | configure the card at this point -- we wait until we receive a | ||
99 | card insertion event. | ||
100 | |||
101 | ======================================================================*/ | ||
102 | |||
103 | static int atmel_probe(struct pcmcia_device *p_dev) | 75 | static int atmel_probe(struct pcmcia_device *p_dev) |
104 | { | 76 | { |
105 | local_info_t *local; | 77 | local_info_t *local; |
106 | 78 | ||
107 | dev_dbg(&p_dev->dev, "atmel_attach()\n"); | 79 | dev_dbg(&p_dev->dev, "atmel_attach()\n"); |
108 | 80 | ||
109 | /* | ||
110 | General socket configuration defaults can go here. In this | ||
111 | client, we assume very little, and rely on the CIS for almost | ||
112 | everything. In most clients, many details (i.e., number, sizes, | ||
113 | and attributes of IO windows) are fixed by the nature of the | ||
114 | device, and can be hard-wired here. | ||
115 | */ | ||
116 | p_dev->conf.Attributes = 0; | ||
117 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
118 | |||
119 | /* Allocate space for private device-specific data */ | 81 | /* Allocate space for private device-specific data */ |
120 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 82 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
121 | if (!local) { | 83 | if (!local) { |
@@ -127,15 +89,6 @@ static int atmel_probe(struct pcmcia_device *p_dev) | |||
127 | return atmel_config(p_dev); | 89 | return atmel_config(p_dev); |
128 | } /* atmel_attach */ | 90 | } /* atmel_attach */ |
129 | 91 | ||
130 | /*====================================================================== | ||
131 | |||
132 | This deletes a driver "instance". The device is de-registered | ||
133 | with Card Services. If it has been released, all local data | ||
134 | structures are freed. Otherwise, the structures will be freed | ||
135 | when the device is released. | ||
136 | |||
137 | ======================================================================*/ | ||
138 | |||
139 | static void atmel_detach(struct pcmcia_device *link) | 92 | static void atmel_detach(struct pcmcia_device *link) |
140 | { | 93 | { |
141 | dev_dbg(&link->dev, "atmel_detach\n"); | 94 | dev_dbg(&link->dev, "atmel_detach\n"); |
@@ -145,14 +98,6 @@ static void atmel_detach(struct pcmcia_device *link) | |||
145 | kfree(link->priv); | 98 | kfree(link->priv); |
146 | } | 99 | } |
147 | 100 | ||
148 | /*====================================================================== | ||
149 | |||
150 | atmel_config() is scheduled to run after a CARD_INSERTION event | ||
151 | is received, to configure the PCMCIA socket, and to make the | ||
152 | device available to the system. | ||
153 | |||
154 | ======================================================================*/ | ||
155 | |||
156 | /* Call-back function to interrogate PCMCIA-specific information | 101 | /* Call-back function to interrogate PCMCIA-specific information |
157 | about the current existance of the card */ | 102 | about the current existance of the card */ |
158 | static int card_present(void *arg) | 103 | static int card_present(void *arg) |
@@ -165,47 +110,11 @@ static int card_present(void *arg) | |||
165 | return 0; | 110 | return 0; |
166 | } | 111 | } |
167 | 112 | ||
168 | static int atmel_config_check(struct pcmcia_device *p_dev, | 113 | static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data) |
169 | cistpl_cftable_entry_t *cfg, | ||
170 | cistpl_cftable_entry_t *dflt, | ||
171 | unsigned int vcc, | ||
172 | void *priv_data) | ||
173 | { | 114 | { |
174 | if (cfg->index == 0) | 115 | if (p_dev->config_index == 0) |
175 | return -ENODEV; | 116 | return -EINVAL; |
176 | |||
177 | /* Does this card need audio output? */ | ||
178 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
179 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
180 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
181 | } | ||
182 | 117 | ||
183 | /* Use power settings for Vcc and Vpp if present */ | ||
184 | /* Note that the CIS values need to be rescaled */ | ||
185 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
186 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
187 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
188 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
189 | |||
190 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
191 | |||
192 | /* IO window settings */ | ||
193 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
194 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
195 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
196 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
197 | p_dev->resource[0]->flags |= | ||
198 | pcmcia_io_cfg_data_width(io->flags); | ||
199 | p_dev->resource[0]->start = io->win[0].base; | ||
200 | p_dev->resource[0]->end = io->win[0].len; | ||
201 | if (io->nwin > 1) { | ||
202 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
203 | p_dev->resource[1]->start = io->win[1].base; | ||
204 | p_dev->resource[1]->end = io->win[1].len; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | /* This reserves IO space but doesn't actually enable it */ | ||
209 | return pcmcia_request_io(p_dev); | 118 | return pcmcia_request_io(p_dev); |
210 | } | 119 | } |
211 | 120 | ||
@@ -220,18 +129,9 @@ static int atmel_config(struct pcmcia_device *link) | |||
220 | 129 | ||
221 | dev_dbg(&link->dev, "atmel_config\n"); | 130 | dev_dbg(&link->dev, "atmel_config\n"); |
222 | 131 | ||
223 | /* | 132 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | |
224 | In this loop, we scan the CIS for configuration table entries, | 133 | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; |
225 | each of which describes a valid card configuration, including | 134 | |
226 | voltage, IO window, memory window, and interrupt settings. | ||
227 | |||
228 | We make no assumptions about the card to be configured: we use | ||
229 | just the information available in the CIS. In an ideal world, | ||
230 | this would work for any PCMCIA card, but it requires a complete | ||
231 | and accurate CIS. In practice, a driver usually "knows" most of | ||
232 | these things without consulting the CIS, and most client drivers | ||
233 | will only use the CIS to fill in implementation-defined details. | ||
234 | */ | ||
235 | if (pcmcia_loop_config(link, atmel_config_check, NULL)) | 135 | if (pcmcia_loop_config(link, atmel_config_check, NULL)) |
236 | goto failed; | 136 | goto failed; |
237 | 137 | ||
@@ -240,12 +140,7 @@ static int atmel_config(struct pcmcia_device *link) | |||
240 | goto failed; | 140 | goto failed; |
241 | } | 141 | } |
242 | 142 | ||
243 | /* | 143 | ret = pcmcia_enable_device(link); |
244 | This actually configures the PCMCIA socket -- setting up | ||
245 | the I/O windows and the interrupt mapping, and putting the | ||
246 | card and host interface into "Memory and IO" mode. | ||
247 | */ | ||
248 | ret = pcmcia_request_configuration(link, &link->conf); | ||
249 | if (ret) | 144 | if (ret) |
250 | goto failed; | 145 | goto failed; |
251 | 146 | ||
@@ -267,14 +162,6 @@ static int atmel_config(struct pcmcia_device *link) | |||
267 | return -ENODEV; | 162 | return -ENODEV; |
268 | } | 163 | } |
269 | 164 | ||
270 | /*====================================================================== | ||
271 | |||
272 | After a card is removed, atmel_release() will unregister the | ||
273 | device, and release the PCMCIA configuration. If the device is | ||
274 | still open, this will be postponed until it is closed. | ||
275 | |||
276 | ======================================================================*/ | ||
277 | |||
278 | static void atmel_release(struct pcmcia_device *link) | 165 | static void atmel_release(struct pcmcia_device *link) |
279 | { | 166 | { |
280 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; | 167 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; |
@@ -353,9 +240,7 @@ MODULE_DEVICE_TABLE(pcmcia, atmel_ids); | |||
353 | 240 | ||
354 | static struct pcmcia_driver atmel_driver = { | 241 | static struct pcmcia_driver atmel_driver = { |
355 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
356 | .drv = { | 243 | .name = "atmel_cs", |
357 | .name = "atmel_cs", | ||
358 | }, | ||
359 | .probe = atmel_probe, | 244 | .probe = atmel_probe, |
360 | .remove = atmel_detach, | 245 | .remove = atmel_detach, |
361 | .id_table = atmel_ids, | 246 | .id_table = atmel_ids, |
@@ -363,12 +248,12 @@ static struct pcmcia_driver atmel_driver = { | |||
363 | .resume = atmel_resume, | 248 | .resume = atmel_resume, |
364 | }; | 249 | }; |
365 | 250 | ||
366 | static int atmel_cs_init(void) | 251 | static int __init atmel_cs_init(void) |
367 | { | 252 | { |
368 | return pcmcia_register_driver(&atmel_driver); | 253 | return pcmcia_register_driver(&atmel_driver); |
369 | } | 254 | } |
370 | 255 | ||
371 | static void atmel_cs_cleanup(void) | 256 | static void __exit atmel_cs_cleanup(void) |
372 | { | 257 | { |
373 | pcmcia_unregister_driver(&atmel_driver); | 258 | pcmcia_unregister_driver(&atmel_driver); |
374 | } | 259 | } |
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index dfbc41d431ff..7dcba5fafdc7 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/ssb/ssb.h> | 26 | #include <linux/ssb/ssb.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | 28 | ||
29 | #include <pcmcia/cs.h> | ||
30 | #include <pcmcia/cistpl.h> | 29 | #include <pcmcia/cistpl.h> |
31 | #include <pcmcia/ciscode.h> | 30 | #include <pcmcia/ciscode.h> |
32 | #include <pcmcia/ds.h> | 31 | #include <pcmcia/ds.h> |
@@ -63,7 +62,6 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev) | |||
63 | static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) | 62 | static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) |
64 | { | 63 | { |
65 | struct ssb_bus *ssb; | 64 | struct ssb_bus *ssb; |
66 | win_req_t win; | ||
67 | int err = -ENOMEM; | 65 | int err = -ENOMEM; |
68 | int res = 0; | 66 | int res = 0; |
69 | 67 | ||
@@ -73,30 +71,28 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) | |||
73 | 71 | ||
74 | err = -ENODEV; | 72 | err = -ENODEV; |
75 | 73 | ||
76 | dev->conf.Attributes = CONF_ENABLE_IRQ; | 74 | dev->config_flags |= CONF_ENABLE_IRQ; |
77 | dev->conf.IntType = INT_MEMORY_AND_IO; | ||
78 | 75 | ||
79 | win.Attributes = WIN_ENABLE | WIN_DATA_WIDTH_16 | | 76 | dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | |
80 | WIN_USE_WAIT; | 77 | WIN_USE_WAIT; |
81 | win.Base = 0; | 78 | dev->resource[2]->start = 0; |
82 | win.Size = SSB_CORE_SIZE; | 79 | dev->resource[2]->end = SSB_CORE_SIZE; |
83 | win.AccessSpeed = 250; | 80 | res = pcmcia_request_window(dev, dev->resource[2], 250); |
84 | res = pcmcia_request_window(dev, &win, &dev->win); | ||
85 | if (res != 0) | 81 | if (res != 0) |
86 | goto err_kfree_ssb; | 82 | goto err_kfree_ssb; |
87 | 83 | ||
88 | res = pcmcia_map_mem_page(dev, dev->win, 0); | 84 | res = pcmcia_map_mem_page(dev, dev->resource[2], 0); |
89 | if (res != 0) | 85 | if (res != 0) |
90 | goto err_disable; | 86 | goto err_disable; |
91 | 87 | ||
92 | if (!dev->irq) | 88 | if (!dev->irq) |
93 | goto err_disable; | 89 | goto err_disable; |
94 | 90 | ||
95 | res = pcmcia_request_configuration(dev, &dev->conf); | 91 | res = pcmcia_enable_device(dev); |
96 | if (res != 0) | 92 | if (res != 0) |
97 | goto err_disable; | 93 | goto err_disable; |
98 | 94 | ||
99 | err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); | 95 | err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); |
100 | if (err) | 96 | if (err) |
101 | goto err_disable; | 97 | goto err_disable; |
102 | dev->priv = ssb; | 98 | dev->priv = ssb; |
@@ -125,9 +121,7 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) | |||
125 | 121 | ||
126 | static struct pcmcia_driver b43_pcmcia_driver = { | 122 | static struct pcmcia_driver b43_pcmcia_driver = { |
127 | .owner = THIS_MODULE, | 123 | .owner = THIS_MODULE, |
128 | .drv = { | 124 | .name = "b43-pcmcia", |
129 | .name = "b43-pcmcia", | ||
130 | }, | ||
131 | .id_table = b43_pcmcia_tbl, | 125 | .id_table = b43_pcmcia_tbl, |
132 | .probe = b43_pcmcia_probe, | 126 | .probe = b43_pcmcia_probe, |
133 | .remove = __devexit_p(b43_pcmcia_remove), | 127 | .remove = __devexit_p(b43_pcmcia_remove), |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index ba54d1b04d22..bd8a4134edeb 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/wireless.h> | 12 | #include <linux/wireless.h> |
13 | #include <net/iw_handler.h> | 13 | #include <net/iw_handler.h> |
14 | 14 | ||
15 | #include <pcmcia/cs.h> | ||
16 | #include <pcmcia/cistpl.h> | 15 | #include <pcmcia/cistpl.h> |
17 | #include <pcmcia/cisreg.h> | 16 | #include <pcmcia/cisreg.h> |
18 | #include <pcmcia/ds.h> | 17 | #include <pcmcia/ds.h> |
@@ -437,7 +436,6 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev) | |||
437 | int ret; | 436 | int ret; |
438 | 437 | ||
439 | PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); | 438 | PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); |
440 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
441 | 439 | ||
442 | ret = prism2_config(p_dev); | 440 | ret = prism2_config(p_dev); |
443 | if (ret) { | 441 | if (ret) { |
@@ -468,74 +466,11 @@ static void prism2_detach(struct pcmcia_device *link) | |||
468 | } | 466 | } |
469 | 467 | ||
470 | 468 | ||
471 | /* run after a CARD_INSERTION event is received to configure the PCMCIA | 469 | static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data) |
472 | * socket and make the device available to the system */ | ||
473 | |||
474 | static int prism2_config_check(struct pcmcia_device *p_dev, | ||
475 | cistpl_cftable_entry_t *cfg, | ||
476 | cistpl_cftable_entry_t *dflt, | ||
477 | unsigned int vcc, | ||
478 | void *priv_data) | ||
479 | { | 470 | { |
480 | if (cfg->index == 0) | 471 | if (p_dev->config_index == 0) |
481 | return -ENODEV; | 472 | return -EINVAL; |
482 | |||
483 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
484 | "(default 0x%02X)\n", cfg->index, dflt->index); | ||
485 | |||
486 | /* Does this card need audio output? */ | ||
487 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
488 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
489 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
490 | } | ||
491 | |||
492 | /* Use power settings for Vcc and Vpp if present */ | ||
493 | /* Note that the CIS values need to be rescaled */ | ||
494 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
495 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
496 | 10000 && !ignore_cis_vcc) { | ||
497 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
498 | " this entry\n"); | ||
499 | return -ENODEV; | ||
500 | } | ||
501 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
502 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / | ||
503 | 10000 && !ignore_cis_vcc) { | ||
504 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
505 | "- skipping this entry\n"); | ||
506 | return -ENODEV; | ||
507 | } | ||
508 | } | ||
509 | 473 | ||
510 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
511 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
512 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
513 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
514 | |||
515 | /* Do we need to allocate an interrupt? */ | ||
516 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
517 | |||
518 | /* IO window settings */ | ||
519 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
520 | "dflt->io.nwin=%d\n", | ||
521 | cfg->io.nwin, dflt->io.nwin); | ||
522 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
523 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
524 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
525 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
526 | p_dev->resource[0]->flags |= | ||
527 | pcmcia_io_cfg_data_width(io->flags); | ||
528 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
529 | p_dev->resource[0]->start = io->win[0].base; | ||
530 | p_dev->resource[0]->end = io->win[0].len; | ||
531 | if (io->nwin > 1) { | ||
532 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
533 | p_dev->resource[1]->start = io->win[1].base; | ||
534 | p_dev->resource[1]->end = io->win[1].len; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | /* This reserves IO space but doesn't actually enable it */ | ||
539 | return pcmcia_request_io(p_dev); | 474 | return pcmcia_request_io(p_dev); |
540 | } | 475 | } |
541 | 476 | ||
@@ -557,6 +492,10 @@ static int prism2_config(struct pcmcia_device *link) | |||
557 | } | 492 | } |
558 | 493 | ||
559 | /* Look for an appropriate configuration table entry in the CIS */ | 494 | /* Look for an appropriate configuration table entry in the CIS */ |
495 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | | ||
496 | CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; | ||
497 | if (ignore_cis_vcc) | ||
498 | link->config_flags &= ~CONF_AUTO_CHECK_VCC; | ||
560 | ret = pcmcia_loop_config(link, prism2_config_check, NULL); | 499 | ret = pcmcia_loop_config(link, prism2_config_check, NULL); |
561 | if (ret) { | 500 | if (ret) { |
562 | if (!ignore_cis_vcc) | 501 | if (!ignore_cis_vcc) |
@@ -588,12 +527,7 @@ static int prism2_config(struct pcmcia_device *link) | |||
588 | if (ret) | 527 | if (ret) |
589 | goto failed_unlock; | 528 | goto failed_unlock; |
590 | 529 | ||
591 | /* | 530 | ret = pcmcia_enable_device(link); |
592 | * This actually configures the PCMCIA socket -- setting up | ||
593 | * the I/O windows and the interrupt mapping, and putting the | ||
594 | * card and host interface into "Memory and IO" mode. | ||
595 | */ | ||
596 | ret = pcmcia_request_configuration(link, &link->conf); | ||
597 | if (ret) | 531 | if (ret) |
598 | goto failed_unlock; | 532 | goto failed_unlock; |
599 | 533 | ||
@@ -602,20 +536,6 @@ static int prism2_config(struct pcmcia_device *link) | |||
602 | 536 | ||
603 | spin_unlock_irqrestore(&local->irq_init_lock, flags); | 537 | spin_unlock_irqrestore(&local->irq_init_lock, flags); |
604 | 538 | ||
605 | /* Finally, report what we've done */ | ||
606 | printk(KERN_INFO "%s: index 0x%02x: ", | ||
607 | dev_info, link->conf.ConfigIndex); | ||
608 | if (link->conf.Vpp) | ||
609 | printk(", Vpp %d.%d", link->conf.Vpp / 10, | ||
610 | link->conf.Vpp % 10); | ||
611 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
612 | printk(", irq %d", link->irq); | ||
613 | if (link->resource[0]) | ||
614 | printk(" & %pR", link->resource[0]); | ||
615 | if (link->resource[1]) | ||
616 | printk(" & %pR", link->resource[1]); | ||
617 | printk("\n"); | ||
618 | |||
619 | local->shutdown = 0; | 539 | local->shutdown = 0; |
620 | 540 | ||
621 | sandisk_enable_wireless(dev); | 541 | sandisk_enable_wireless(dev); |
@@ -627,7 +547,7 @@ static int prism2_config(struct pcmcia_device *link) | |||
627 | return ret; | 547 | return ret; |
628 | 548 | ||
629 | failed_unlock: | 549 | failed_unlock: |
630 | spin_unlock_irqrestore(&local->irq_init_lock, flags); | 550 | spin_unlock_irqrestore(&local->irq_init_lock, flags); |
631 | failed: | 551 | failed: |
632 | kfree(hw_priv); | 552 | kfree(hw_priv); |
633 | prism2_release((u_long)link); | 553 | prism2_release((u_long)link); |
@@ -779,9 +699,7 @@ MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); | |||
779 | 699 | ||
780 | 700 | ||
781 | static struct pcmcia_driver hostap_driver = { | 701 | static struct pcmcia_driver hostap_driver = { |
782 | .drv = { | 702 | .name = "hostap_cs", |
783 | .name = "hostap_cs", | ||
784 | }, | ||
785 | .probe = hostap_cs_probe, | 703 | .probe = hostap_cs_probe, |
786 | .remove = prism2_detach, | 704 | .remove = prism2_detach, |
787 | .owner = THIS_MODULE, | 705 | .owner = THIS_MODULE, |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 9c298396be50..ff1280f41336 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
30 | 30 | ||
31 | #include <pcmcia/cs.h> | ||
32 | #include <pcmcia/cistpl.h> | 31 | #include <pcmcia/cistpl.h> |
33 | #include <pcmcia/ds.h> | 32 | #include <pcmcia/ds.h> |
34 | 33 | ||
@@ -761,15 +760,6 @@ static int if_cs_host_to_card(struct lbs_private *priv, | |||
761 | } | 760 | } |
762 | 761 | ||
763 | 762 | ||
764 | /********************************************************************/ | ||
765 | /* Card Services */ | ||
766 | /********************************************************************/ | ||
767 | |||
768 | /* | ||
769 | * After a card is removed, if_cs_release() will unregister the | ||
770 | * device, and release the PCMCIA configuration. If the device is | ||
771 | * still open, this will be postponed until it is closed. | ||
772 | */ | ||
773 | static void if_cs_release(struct pcmcia_device *p_dev) | 763 | static void if_cs_release(struct pcmcia_device *p_dev) |
774 | { | 764 | { |
775 | struct if_cs_card *card = p_dev->priv; | 765 | struct if_cs_card *card = p_dev->priv; |
@@ -785,31 +775,12 @@ static void if_cs_release(struct pcmcia_device *p_dev) | |||
785 | } | 775 | } |
786 | 776 | ||
787 | 777 | ||
788 | /* | 778 | static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data) |
789 | * This creates an "instance" of the driver, allocating local data | ||
790 | * structures for one device. The device is registered with Card | ||
791 | * Services. | ||
792 | * | ||
793 | * The dev_link structure is initialized, but we don't actually | ||
794 | * configure the card at this point -- we wait until we receive a card | ||
795 | * insertion event. | ||
796 | */ | ||
797 | |||
798 | static int if_cs_ioprobe(struct pcmcia_device *p_dev, | ||
799 | cistpl_cftable_entry_t *cfg, | ||
800 | cistpl_cftable_entry_t *dflt, | ||
801 | unsigned int vcc, | ||
802 | void *priv_data) | ||
803 | { | 779 | { |
780 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
804 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 781 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
805 | p_dev->resource[0]->start = cfg->io.win[0].base; | ||
806 | p_dev->resource[0]->end = cfg->io.win[0].len; | ||
807 | |||
808 | /* Do we need to allocate an interrupt? */ | ||
809 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
810 | 782 | ||
811 | /* IO window settings */ | 783 | if (p_dev->resource[1]->end) { |
812 | if (cfg->io.nwin != 1) { | ||
813 | lbs_pr_err("wrong CIS (check number of IO windows)\n"); | 784 | lbs_pr_err("wrong CIS (check number of IO windows)\n"); |
814 | return -ENODEV; | 785 | return -ENODEV; |
815 | } | 786 | } |
@@ -835,15 +806,13 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
835 | card->p_dev = p_dev; | 806 | card->p_dev = p_dev; |
836 | p_dev->priv = card; | 807 | p_dev->priv = card; |
837 | 808 | ||
838 | p_dev->conf.Attributes = 0; | 809 | p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
839 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
840 | 810 | ||
841 | if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { | 811 | if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { |
842 | lbs_pr_err("error in pcmcia_loop_config\n"); | 812 | lbs_pr_err("error in pcmcia_loop_config\n"); |
843 | goto out1; | 813 | goto out1; |
844 | } | 814 | } |
845 | 815 | ||
846 | |||
847 | /* | 816 | /* |
848 | * Allocate an interrupt line. Note that this does not assign | 817 | * Allocate an interrupt line. Note that this does not assign |
849 | * a handler to the interrupt, unless the 'Handler' member of | 818 | * a handler to the interrupt, unless the 'Handler' member of |
@@ -861,14 +830,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
861 | goto out1; | 830 | goto out1; |
862 | } | 831 | } |
863 | 832 | ||
864 | /* | 833 | ret = pcmcia_enable_device(p_dev); |
865 | * This actually configures the PCMCIA socket -- setting up | ||
866 | * the I/O windows and the interrupt mapping, and putting the | ||
867 | * card and host interface into "Memory and IO" mode. | ||
868 | */ | ||
869 | ret = pcmcia_request_configuration(p_dev, &p_dev->conf); | ||
870 | if (ret) { | 834 | if (ret) { |
871 | lbs_pr_err("error in pcmcia_request_configuration\n"); | 835 | lbs_pr_err("error in pcmcia_enable_device\n"); |
872 | goto out2; | 836 | goto out2; |
873 | } | 837 | } |
874 | 838 | ||
@@ -962,12 +926,6 @@ out: | |||
962 | } | 926 | } |
963 | 927 | ||
964 | 928 | ||
965 | /* | ||
966 | * This deletes a driver "instance". The device is de-registered with | ||
967 | * Card Services. If it has been released, all local data structures | ||
968 | * are freed. Otherwise, the structures will be freed when the device | ||
969 | * is released. | ||
970 | */ | ||
971 | static void if_cs_detach(struct pcmcia_device *p_dev) | 929 | static void if_cs_detach(struct pcmcia_device *p_dev) |
972 | { | 930 | { |
973 | struct if_cs_card *card = p_dev->priv; | 931 | struct if_cs_card *card = p_dev->priv; |
@@ -1000,9 +958,7 @@ MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); | |||
1000 | 958 | ||
1001 | static struct pcmcia_driver lbs_driver = { | 959 | static struct pcmcia_driver lbs_driver = { |
1002 | .owner = THIS_MODULE, | 960 | .owner = THIS_MODULE, |
1003 | .drv = { | 961 | .name = DRV_NAME, |
1004 | .name = DRV_NAME, | ||
1005 | }, | ||
1006 | .probe = if_cs_probe, | 962 | .probe = if_cs_probe, |
1007 | .remove = if_cs_detach, | 963 | .remove = if_cs_detach, |
1008 | .id_table = if_cs_ids, | 964 | .id_table = if_cs_ids, |
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index ef46a2d88539..71b3d68b9403 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/cistpl.h> | 20 | #include <pcmcia/cistpl.h> |
22 | #include <pcmcia/cisreg.h> | 21 | #include <pcmcia/cisreg.h> |
23 | #include <pcmcia/ds.h> | 22 | #include <pcmcia/ds.h> |
@@ -93,14 +92,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) | |||
93 | /* PCMCIA stuff */ | 92 | /* PCMCIA stuff */ |
94 | /********************************************************************/ | 93 | /********************************************************************/ |
95 | 94 | ||
96 | /* | ||
97 | * This creates an "instance" of the driver, allocating local data | ||
98 | * structures for one device. The device is registered with Card | ||
99 | * Services. | ||
100 | * | ||
101 | * The dev_link structure is initialized, but we don't actually | ||
102 | * configure the card at this point -- we wait until we receive a card | ||
103 | * insertion event. */ | ||
104 | static int | 95 | static int |
105 | orinoco_cs_probe(struct pcmcia_device *link) | 96 | orinoco_cs_probe(struct pcmcia_device *link) |
106 | { | 97 | { |
@@ -117,23 +108,9 @@ orinoco_cs_probe(struct pcmcia_device *link) | |||
117 | card->p_dev = link; | 108 | card->p_dev = link; |
118 | link->priv = priv; | 109 | link->priv = priv; |
119 | 110 | ||
120 | /* General socket configuration defaults can go here. In this | ||
121 | * client, we assume very little, and rely on the CIS for | ||
122 | * almost everything. In most clients, many details (i.e., | ||
123 | * number, sizes, and attributes of IO windows) are fixed by | ||
124 | * the nature of the device, and can be hard-wired here. */ | ||
125 | link->conf.Attributes = 0; | ||
126 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
127 | |||
128 | return orinoco_cs_config(link); | 111 | return orinoco_cs_config(link); |
129 | } /* orinoco_cs_attach */ | 112 | } /* orinoco_cs_attach */ |
130 | 113 | ||
131 | /* | ||
132 | * This deletes a driver "instance". The device is de-registered with | ||
133 | * Card Services. If it has been released, all local data structures | ||
134 | * are freed. Otherwise, the structures will be freed when the device | ||
135 | * is released. | ||
136 | */ | ||
137 | static void orinoco_cs_detach(struct pcmcia_device *link) | 114 | static void orinoco_cs_detach(struct pcmcia_device *link) |
138 | { | 115 | { |
139 | struct orinoco_private *priv = link->priv; | 116 | struct orinoco_private *priv = link->priv; |
@@ -145,76 +122,12 @@ static void orinoco_cs_detach(struct pcmcia_device *link) | |||
145 | free_orinocodev(priv); | 122 | free_orinocodev(priv); |
146 | } /* orinoco_cs_detach */ | 123 | } /* orinoco_cs_detach */ |
147 | 124 | ||
148 | /* | 125 | static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) |
149 | * orinoco_cs_config() is scheduled to run after a CARD_INSERTION | ||
150 | * event is received, to configure the PCMCIA socket, and to make the | ||
151 | * device available to the system. | ||
152 | */ | ||
153 | |||
154 | static int orinoco_cs_config_check(struct pcmcia_device *p_dev, | ||
155 | cistpl_cftable_entry_t *cfg, | ||
156 | cistpl_cftable_entry_t *dflt, | ||
157 | unsigned int vcc, | ||
158 | void *priv_data) | ||
159 | { | 126 | { |
160 | if (cfg->index == 0) | 127 | if (p_dev->config_index == 0) |
161 | goto next_entry; | 128 | return -EINVAL; |
162 | |||
163 | /* Use power settings for Vcc and Vpp if present */ | ||
164 | /* Note that the CIS values need to be rescaled */ | ||
165 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
166 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
167 | DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", | ||
168 | __func__, vcc, | ||
169 | cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
170 | if (!ignore_cis_vcc) | ||
171 | goto next_entry; | ||
172 | } | ||
173 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
174 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
175 | DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", | ||
176 | __func__, vcc, | ||
177 | dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
178 | if (!ignore_cis_vcc) | ||
179 | goto next_entry; | ||
180 | } | ||
181 | } | ||
182 | 129 | ||
183 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 130 | return pcmcia_request_io(p_dev); |
184 | p_dev->conf.Vpp = | ||
185 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
186 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
187 | p_dev->conf.Vpp = | ||
188 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
189 | |||
190 | /* Do we need to allocate an interrupt? */ | ||
191 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
192 | |||
193 | /* IO window settings */ | ||
194 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
195 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
196 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
197 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
198 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
199 | p_dev->resource[0]->flags |= | ||
200 | pcmcia_io_cfg_data_width(io->flags); | ||
201 | p_dev->resource[0]->start = io->win[0].base; | ||
202 | p_dev->resource[0]->end = io->win[0].len; | ||
203 | if (io->nwin > 1) { | ||
204 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
205 | p_dev->resource[1]->start = io->win[1].base; | ||
206 | p_dev->resource[1]->end = io->win[1].len; | ||
207 | } | ||
208 | |||
209 | /* This reserves IO space but doesn't actually enable it */ | ||
210 | if (pcmcia_request_io(p_dev) != 0) | ||
211 | goto next_entry; | ||
212 | } | ||
213 | return 0; | ||
214 | |||
215 | next_entry: | ||
216 | pcmcia_disable_device(p_dev); | ||
217 | return -ENODEV; | ||
218 | }; | 131 | }; |
219 | 132 | ||
220 | static int | 133 | static int |
@@ -225,20 +138,10 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
225 | int ret; | 138 | int ret; |
226 | void __iomem *mem; | 139 | void __iomem *mem; |
227 | 140 | ||
228 | /* | 141 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC | |
229 | * In this loop, we scan the CIS for configuration table | 142 | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; |
230 | * entries, each of which describes a valid card | 143 | if (ignore_cis_vcc) |
231 | * configuration, including voltage, IO window, memory window, | 144 | link->config_flags &= ~CONF_AUTO_CHECK_VCC; |
232 | * and interrupt settings. | ||
233 | * | ||
234 | * We make no assumptions about the card to be configured: we | ||
235 | * use just the information available in the CIS. In an ideal | ||
236 | * world, this would work for any PCMCIA card, but it requires | ||
237 | * a complete and accurate CIS. In practice, a driver usually | ||
238 | * "knows" most of these things without consulting the CIS, | ||
239 | * and most client drivers will only use the CIS to fill in | ||
240 | * implementation-defined details. | ||
241 | */ | ||
242 | ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); | 145 | ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); |
243 | if (ret) { | 146 | if (ret) { |
244 | if (!ignore_cis_vcc) | 147 | if (!ignore_cis_vcc) |
@@ -262,12 +165,7 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
262 | 165 | ||
263 | hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); | 166 | hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); |
264 | 167 | ||
265 | /* | 168 | ret = pcmcia_enable_device(link); |
266 | * This actually configures the PCMCIA socket -- setting up | ||
267 | * the I/O windows and the interrupt mapping, and putting the | ||
268 | * card and host interface into "Memory and IO" mode. | ||
269 | */ | ||
270 | ret = pcmcia_request_configuration(link, &link->conf); | ||
271 | if (ret) | 169 | if (ret) |
272 | goto failed; | 170 | goto failed; |
273 | 171 | ||
@@ -291,11 +189,6 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
291 | return -ENODEV; | 189 | return -ENODEV; |
292 | } /* orinoco_cs_config */ | 190 | } /* orinoco_cs_config */ |
293 | 191 | ||
294 | /* | ||
295 | * After a card is removed, orinoco_cs_release() will unregister the | ||
296 | * device, and release the PCMCIA configuration. If the device is | ||
297 | * still open, this will be postponed until it is closed. | ||
298 | */ | ||
299 | static void | 192 | static void |
300 | orinoco_cs_release(struct pcmcia_device *link) | 193 | orinoco_cs_release(struct pcmcia_device *link) |
301 | { | 194 | { |
@@ -344,12 +237,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link) | |||
344 | /* Module initialization */ | 237 | /* Module initialization */ |
345 | /********************************************************************/ | 238 | /********************************************************************/ |
346 | 239 | ||
347 | /* Can't be declared "const" or the whole __initdata section will | ||
348 | * become const */ | ||
349 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | ||
350 | " (David Gibson <hermes@gibson.dropbear.id.au>, " | ||
351 | "Pavel Roskin <proski@gnu.org>, et al)"; | ||
352 | |||
353 | static struct pcmcia_device_id orinoco_cs_ids[] = { | 240 | static struct pcmcia_device_id orinoco_cs_ids[] = { |
354 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ | 241 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ |
355 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ | 242 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ |
@@ -441,9 +328,7 @@ MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); | |||
441 | 328 | ||
442 | static struct pcmcia_driver orinoco_driver = { | 329 | static struct pcmcia_driver orinoco_driver = { |
443 | .owner = THIS_MODULE, | 330 | .owner = THIS_MODULE, |
444 | .drv = { | 331 | .name = DRIVER_NAME, |
445 | .name = DRIVER_NAME, | ||
446 | }, | ||
447 | .probe = orinoco_cs_probe, | 332 | .probe = orinoco_cs_probe, |
448 | .remove = orinoco_cs_detach, | 333 | .remove = orinoco_cs_detach, |
449 | .id_table = orinoco_cs_ids, | 334 | .id_table = orinoco_cs_ids, |
@@ -454,8 +339,6 @@ static struct pcmcia_driver orinoco_driver = { | |||
454 | static int __init | 339 | static int __init |
455 | init_orinoco_cs(void) | 340 | init_orinoco_cs(void) |
456 | { | 341 | { |
457 | printk(KERN_DEBUG "%s\n", version); | ||
458 | |||
459 | return pcmcia_register_driver(&orinoco_driver); | 342 | return pcmcia_register_driver(&orinoco_driver); |
460 | } | 343 | } |
461 | 344 | ||
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 873877e17e1b..fb859a5ad2eb 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <pcmcia/cs.h> | ||
29 | #include <pcmcia/cistpl.h> | 28 | #include <pcmcia/cistpl.h> |
30 | #include <pcmcia/cisreg.h> | 29 | #include <pcmcia/cisreg.h> |
31 | #include <pcmcia/ds.h> | 30 | #include <pcmcia/ds.h> |
@@ -154,14 +153,6 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle) | |||
154 | /* PCMCIA stuff */ | 153 | /* PCMCIA stuff */ |
155 | /********************************************************************/ | 154 | /********************************************************************/ |
156 | 155 | ||
157 | /* | ||
158 | * This creates an "instance" of the driver, allocating local data | ||
159 | * structures for one device. The device is registered with Card | ||
160 | * Services. | ||
161 | * | ||
162 | * The dev_link structure is initialized, but we don't actually | ||
163 | * configure the card at this point -- we wait until we receive a card | ||
164 | * insertion event. */ | ||
165 | static int | 156 | static int |
166 | spectrum_cs_probe(struct pcmcia_device *link) | 157 | spectrum_cs_probe(struct pcmcia_device *link) |
167 | { | 158 | { |
@@ -179,23 +170,9 @@ spectrum_cs_probe(struct pcmcia_device *link) | |||
179 | card->p_dev = link; | 170 | card->p_dev = link; |
180 | link->priv = priv; | 171 | link->priv = priv; |
181 | 172 | ||
182 | /* General socket configuration defaults can go here. In this | ||
183 | * client, we assume very little, and rely on the CIS for | ||
184 | * almost everything. In most clients, many details (i.e., | ||
185 | * number, sizes, and attributes of IO windows) are fixed by | ||
186 | * the nature of the device, and can be hard-wired here. */ | ||
187 | link->conf.Attributes = 0; | ||
188 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
189 | |||
190 | return spectrum_cs_config(link); | 173 | return spectrum_cs_config(link); |
191 | } /* spectrum_cs_attach */ | 174 | } /* spectrum_cs_attach */ |
192 | 175 | ||
193 | /* | ||
194 | * This deletes a driver "instance". The device is de-registered with | ||
195 | * Card Services. If it has been released, all local data structures | ||
196 | * are freed. Otherwise, the structures will be freed when the device | ||
197 | * is released. | ||
198 | */ | ||
199 | static void spectrum_cs_detach(struct pcmcia_device *link) | 176 | static void spectrum_cs_detach(struct pcmcia_device *link) |
200 | { | 177 | { |
201 | struct orinoco_private *priv = link->priv; | 178 | struct orinoco_private *priv = link->priv; |
@@ -207,76 +184,13 @@ static void spectrum_cs_detach(struct pcmcia_device *link) | |||
207 | free_orinocodev(priv); | 184 | free_orinocodev(priv); |
208 | } /* spectrum_cs_detach */ | 185 | } /* spectrum_cs_detach */ |
209 | 186 | ||
210 | /* | ||
211 | * spectrum_cs_config() is scheduled to run after a CARD_INSERTION | ||
212 | * event is received, to configure the PCMCIA socket, and to make the | ||
213 | * device available to the system. | ||
214 | */ | ||
215 | |||
216 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, | 187 | static int spectrum_cs_config_check(struct pcmcia_device *p_dev, |
217 | cistpl_cftable_entry_t *cfg, | ||
218 | cistpl_cftable_entry_t *dflt, | ||
219 | unsigned int vcc, | ||
220 | void *priv_data) | 188 | void *priv_data) |
221 | { | 189 | { |
222 | if (cfg->index == 0) | 190 | if (p_dev->config_index == 0) |
223 | goto next_entry; | 191 | return -EINVAL; |
224 | |||
225 | /* Use power settings for Vcc and Vpp if present */ | ||
226 | /* Note that the CIS values need to be rescaled */ | ||
227 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
228 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
229 | DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", | ||
230 | __func__, vcc, | ||
231 | cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
232 | if (!ignore_cis_vcc) | ||
233 | goto next_entry; | ||
234 | } | ||
235 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
236 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
237 | DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", | ||
238 | __func__, vcc, | ||
239 | dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
240 | if (!ignore_cis_vcc) | ||
241 | goto next_entry; | ||
242 | } | ||
243 | } | ||
244 | 192 | ||
245 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 193 | return pcmcia_request_io(p_dev); |
246 | p_dev->conf.Vpp = | ||
247 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
248 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
249 | p_dev->conf.Vpp = | ||
250 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
251 | |||
252 | /* Do we need to allocate an interrupt? */ | ||
253 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
254 | |||
255 | /* IO window settings */ | ||
256 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
257 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
258 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
259 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
260 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
261 | p_dev->resource[0]->flags |= | ||
262 | pcmcia_io_cfg_data_width(io->flags); | ||
263 | p_dev->resource[0]->start = io->win[0].base; | ||
264 | p_dev->resource[0]->end = io->win[0].len; | ||
265 | if (io->nwin > 1) { | ||
266 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
267 | p_dev->resource[1]->start = io->win[1].base; | ||
268 | p_dev->resource[1]->end = io->win[1].len; | ||
269 | } | ||
270 | |||
271 | /* This reserves IO space but doesn't actually enable it */ | ||
272 | if (pcmcia_request_io(p_dev) != 0) | ||
273 | goto next_entry; | ||
274 | } | ||
275 | return 0; | ||
276 | |||
277 | next_entry: | ||
278 | pcmcia_disable_device(p_dev); | ||
279 | return -ENODEV; | ||
280 | }; | 194 | }; |
281 | 195 | ||
282 | static int | 196 | static int |
@@ -287,20 +201,10 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
287 | int ret; | 201 | int ret; |
288 | void __iomem *mem; | 202 | void __iomem *mem; |
289 | 203 | ||
290 | /* | 204 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC | |
291 | * In this loop, we scan the CIS for configuration table | 205 | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; |
292 | * entries, each of which describes a valid card | 206 | if (ignore_cis_vcc) |
293 | * configuration, including voltage, IO window, memory window, | 207 | link->config_flags &= ~CONF_AUTO_CHECK_VCC; |
294 | * and interrupt settings. | ||
295 | * | ||
296 | * We make no assumptions about the card to be configured: we | ||
297 | * use just the information available in the CIS. In an ideal | ||
298 | * world, this would work for any PCMCIA card, but it requires | ||
299 | * a complete and accurate CIS. In practice, a driver usually | ||
300 | * "knows" most of these things without consulting the CIS, | ||
301 | * and most client drivers will only use the CIS to fill in | ||
302 | * implementation-defined details. | ||
303 | */ | ||
304 | ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); | 208 | ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); |
305 | if (ret) { | 209 | if (ret) { |
306 | if (!ignore_cis_vcc) | 210 | if (!ignore_cis_vcc) |
@@ -325,12 +229,7 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
325 | hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); | 229 | hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); |
326 | hw->eeprom_pda = true; | 230 | hw->eeprom_pda = true; |
327 | 231 | ||
328 | /* | 232 | ret = pcmcia_enable_device(link); |
329 | * This actually configures the PCMCIA socket -- setting up | ||
330 | * the I/O windows and the interrupt mapping, and putting the | ||
331 | * card and host interface into "Memory and IO" mode. | ||
332 | */ | ||
333 | ret = pcmcia_request_configuration(link, &link->conf); | ||
334 | if (ret) | 233 | if (ret) |
335 | goto failed; | 234 | goto failed; |
336 | 235 | ||
@@ -358,11 +257,6 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
358 | return -ENODEV; | 257 | return -ENODEV; |
359 | } /* spectrum_cs_config */ | 258 | } /* spectrum_cs_config */ |
360 | 259 | ||
361 | /* | ||
362 | * After a card is removed, spectrum_cs_release() will unregister the | ||
363 | * device, and release the PCMCIA configuration. If the device is | ||
364 | * still open, this will be postponed until it is closed. | ||
365 | */ | ||
366 | static void | 260 | static void |
367 | spectrum_cs_release(struct pcmcia_device *link) | 261 | spectrum_cs_release(struct pcmcia_device *link) |
368 | { | 262 | { |
@@ -407,12 +301,6 @@ spectrum_cs_resume(struct pcmcia_device *link) | |||
407 | /* Module initialization */ | 301 | /* Module initialization */ |
408 | /********************************************************************/ | 302 | /********************************************************************/ |
409 | 303 | ||
410 | /* Can't be declared "const" or the whole __initdata section will | ||
411 | * become const */ | ||
412 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | ||
413 | " (Pavel Roskin <proski@gnu.org>," | ||
414 | " David Gibson <hermes@gibson.dropbear.id.au>, et al)"; | ||
415 | |||
416 | static struct pcmcia_device_id spectrum_cs_ids[] = { | 304 | static struct pcmcia_device_id spectrum_cs_ids[] = { |
417 | PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ | 305 | PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ |
418 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ | 306 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ |
@@ -423,9 +311,7 @@ MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids); | |||
423 | 311 | ||
424 | static struct pcmcia_driver orinoco_driver = { | 312 | static struct pcmcia_driver orinoco_driver = { |
425 | .owner = THIS_MODULE, | 313 | .owner = THIS_MODULE, |
426 | .drv = { | 314 | .name = DRIVER_NAME, |
427 | .name = DRIVER_NAME, | ||
428 | }, | ||
429 | .probe = spectrum_cs_probe, | 315 | .probe = spectrum_cs_probe, |
430 | .remove = spectrum_cs_detach, | 316 | .remove = spectrum_cs_detach, |
431 | .suspend = spectrum_cs_suspend, | 317 | .suspend = spectrum_cs_suspend, |
@@ -436,8 +322,6 @@ static struct pcmcia_driver orinoco_driver = { | |||
436 | static int __init | 322 | static int __init |
437 | init_spectrum_cs(void) | 323 | init_spectrum_cs(void) |
438 | { | 324 | { |
439 | printk(KERN_DEBUG "%s\n", version); | ||
440 | |||
441 | return pcmcia_register_driver(&orinoco_driver); | 325 | return pcmcia_register_driver(&orinoco_driver); |
442 | } | 326 | } |
443 | 327 | ||
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 88560d0ae50a..af5b17ce5a15 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <linux/ethtool.h> | 46 | #include <linux/ethtool.h> |
47 | #include <linux/ieee80211.h> | 47 | #include <linux/ieee80211.h> |
48 | 48 | ||
49 | #include <pcmcia/cs.h> | ||
50 | #include <pcmcia/cistpl.h> | 49 | #include <pcmcia/cistpl.h> |
51 | #include <pcmcia/cisreg.h> | 50 | #include <pcmcia/cisreg.h> |
52 | #include <pcmcia/ds.h> | 51 | #include <pcmcia/ds.h> |
@@ -169,13 +168,6 @@ static int bc; | |||
169 | */ | 168 | */ |
170 | static char *phy_addr = NULL; | 169 | static char *phy_addr = NULL; |
171 | 170 | ||
172 | |||
173 | /* A struct pcmcia_device structure has fields for most things that are needed | ||
174 | to keep track of a socket, but there will usually be some device | ||
175 | specific information that also needs to be kept track of. The | ||
176 | 'priv' pointer in a struct pcmcia_device structure can be used to point to | ||
177 | a device-specific private data structure, like this. | ||
178 | */ | ||
179 | static unsigned int ray_mem_speed = 500; | 171 | static unsigned int ray_mem_speed = 500; |
180 | 172 | ||
181 | /* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */ | 173 | /* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */ |
@@ -290,14 +282,6 @@ static const struct net_device_ops ray_netdev_ops = { | |||
290 | .ndo_validate_addr = eth_validate_addr, | 282 | .ndo_validate_addr = eth_validate_addr, |
291 | }; | 283 | }; |
292 | 284 | ||
293 | /*============================================================================= | ||
294 | ray_attach() creates an "instance" of the driver, allocating | ||
295 | local data structures for one device. The device is registered | ||
296 | with Card Services. | ||
297 | The dev_link structure is initialized, but we don't actually | ||
298 | configure the card at this point -- we wait until we receive a | ||
299 | card insertion event. | ||
300 | =============================================================================*/ | ||
301 | static int ray_probe(struct pcmcia_device *p_dev) | 285 | static int ray_probe(struct pcmcia_device *p_dev) |
302 | { | 286 | { |
303 | ray_dev_t *local; | 287 | ray_dev_t *local; |
@@ -318,9 +302,8 @@ static int ray_probe(struct pcmcia_device *p_dev) | |||
318 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 302 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
319 | 303 | ||
320 | /* General socket configuration */ | 304 | /* General socket configuration */ |
321 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 305 | p_dev->config_flags |= CONF_ENABLE_IRQ; |
322 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 306 | p_dev->config_index = 1; |
323 | p_dev->conf.ConfigIndex = 1; | ||
324 | 307 | ||
325 | p_dev->priv = dev; | 308 | p_dev->priv = dev; |
326 | 309 | ||
@@ -353,12 +336,6 @@ fail_alloc_dev: | |||
353 | return -ENOMEM; | 336 | return -ENOMEM; |
354 | } /* ray_attach */ | 337 | } /* ray_attach */ |
355 | 338 | ||
356 | /*============================================================================= | ||
357 | This deletes a driver "instance". The device is de-registered | ||
358 | with Card Services. If it has been released, all local data | ||
359 | structures are freed. Otherwise, the structures will be freed | ||
360 | when the device is released. | ||
361 | =============================================================================*/ | ||
362 | static void ray_detach(struct pcmcia_device *link) | 339 | static void ray_detach(struct pcmcia_device *link) |
363 | { | 340 | { |
364 | struct net_device *dev; | 341 | struct net_device *dev; |
@@ -381,17 +358,11 @@ static void ray_detach(struct pcmcia_device *link) | |||
381 | dev_dbg(&link->dev, "ray_cs ray_detach ending\n"); | 358 | dev_dbg(&link->dev, "ray_cs ray_detach ending\n"); |
382 | } /* ray_detach */ | 359 | } /* ray_detach */ |
383 | 360 | ||
384 | /*============================================================================= | ||
385 | ray_config() is run after a CARD_INSERTION event | ||
386 | is received, to configure the PCMCIA socket, and to make the | ||
387 | ethernet device available to the system. | ||
388 | =============================================================================*/ | ||
389 | #define MAX_TUPLE_SIZE 128 | 361 | #define MAX_TUPLE_SIZE 128 |
390 | static int ray_config(struct pcmcia_device *link) | 362 | static int ray_config(struct pcmcia_device *link) |
391 | { | 363 | { |
392 | int ret = 0; | 364 | int ret = 0; |
393 | int i; | 365 | int i; |
394 | win_req_t req; | ||
395 | struct net_device *dev = (struct net_device *)link->priv; | 366 | struct net_device *dev = (struct net_device *)link->priv; |
396 | ray_dev_t *local = netdev_priv(dev); | 367 | ray_dev_t *local = netdev_priv(dev); |
397 | 368 | ||
@@ -412,54 +383,50 @@ static int ray_config(struct pcmcia_device *link) | |||
412 | goto failed; | 383 | goto failed; |
413 | dev->irq = link->irq; | 384 | dev->irq = link->irq; |
414 | 385 | ||
415 | /* This actually configures the PCMCIA socket -- setting up | 386 | ret = pcmcia_enable_device(link); |
416 | the I/O windows and the interrupt mapping. | ||
417 | */ | ||
418 | ret = pcmcia_request_configuration(link, &link->conf); | ||
419 | if (ret) | 387 | if (ret) |
420 | goto failed; | 388 | goto failed; |
421 | 389 | ||
422 | /*** Set up 32k window for shared memory (transmit and control) ************/ | 390 | /*** Set up 32k window for shared memory (transmit and control) ************/ |
423 | req.Attributes = | 391 | link->resource[2]->flags |= WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; |
424 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; | 392 | link->resource[2]->start = 0; |
425 | req.Base = 0; | 393 | link->resource[2]->end = 0x8000; |
426 | req.Size = 0x8000; | 394 | ret = pcmcia_request_window(link, link->resource[2], ray_mem_speed); |
427 | req.AccessSpeed = ray_mem_speed; | ||
428 | ret = pcmcia_request_window(link, &req, &link->win); | ||
429 | if (ret) | 395 | if (ret) |
430 | goto failed; | 396 | goto failed; |
431 | ret = pcmcia_map_mem_page(link, link->win, 0); | 397 | ret = pcmcia_map_mem_page(link, link->resource[2], 0); |
432 | if (ret) | 398 | if (ret) |
433 | goto failed; | 399 | goto failed; |
434 | local->sram = ioremap(req.Base, req.Size); | 400 | local->sram = ioremap(link->resource[2]->start, |
401 | resource_size(link->resource[2])); | ||
435 | 402 | ||
436 | /*** Set up 16k window for shared memory (receive buffer) ***************/ | 403 | /*** Set up 16k window for shared memory (receive buffer) ***************/ |
437 | req.Attributes = | 404 | link->resource[3]->flags |= |
438 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; | 405 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; |
439 | req.Base = 0; | 406 | link->resource[3]->start = 0; |
440 | req.Size = 0x4000; | 407 | link->resource[3]->end = 0x4000; |
441 | req.AccessSpeed = ray_mem_speed; | 408 | ret = pcmcia_request_window(link, link->resource[3], ray_mem_speed); |
442 | ret = pcmcia_request_window(link, &req, &local->rmem_handle); | ||
443 | if (ret) | 409 | if (ret) |
444 | goto failed; | 410 | goto failed; |
445 | ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000); | 411 | ret = pcmcia_map_mem_page(link, link->resource[3], 0x8000); |
446 | if (ret) | 412 | if (ret) |
447 | goto failed; | 413 | goto failed; |
448 | local->rmem = ioremap(req.Base, req.Size); | 414 | local->rmem = ioremap(link->resource[3]->start, |
415 | resource_size(link->resource[3])); | ||
449 | 416 | ||
450 | /*** Set up window for attribute memory ***********************************/ | 417 | /*** Set up window for attribute memory ***********************************/ |
451 | req.Attributes = | 418 | link->resource[4]->flags |= |
452 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; | 419 | WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; |
453 | req.Base = 0; | 420 | link->resource[4]->start = 0; |
454 | req.Size = 0x1000; | 421 | link->resource[4]->end = 0x1000; |
455 | req.AccessSpeed = ray_mem_speed; | 422 | ret = pcmcia_request_window(link, link->resource[4], ray_mem_speed); |
456 | ret = pcmcia_request_window(link, &req, &local->amem_handle); | ||
457 | if (ret) | 423 | if (ret) |
458 | goto failed; | 424 | goto failed; |
459 | ret = pcmcia_map_mem_page(link, local->amem_handle, 0); | 425 | ret = pcmcia_map_mem_page(link, link->resource[4], 0); |
460 | if (ret) | 426 | if (ret) |
461 | goto failed; | 427 | goto failed; |
462 | local->amem = ioremap(req.Base, req.Size); | 428 | local->amem = ioremap(link->resource[4]->start, |
429 | resource_size(link->resource[4])); | ||
463 | 430 | ||
464 | dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram); | 431 | dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram); |
465 | dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem); | 432 | dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem); |
@@ -775,11 +742,7 @@ static void join_net(u_long data) | |||
775 | local->card_status = CARD_DOING_ACQ; | 742 | local->card_status = CARD_DOING_ACQ; |
776 | } | 743 | } |
777 | 744 | ||
778 | /*============================================================================ | 745 | |
779 | After a card is removed, ray_release() will unregister the net | ||
780 | device, and release the PCMCIA configuration. If the device is | ||
781 | still open, this will be postponed until it is closed. | ||
782 | =============================================================================*/ | ||
783 | static void ray_release(struct pcmcia_device *link) | 746 | static void ray_release(struct pcmcia_device *link) |
784 | { | 747 | { |
785 | struct net_device *dev = link->priv; | 748 | struct net_device *dev = link->priv; |
@@ -2847,9 +2810,7 @@ MODULE_DEVICE_TABLE(pcmcia, ray_ids); | |||
2847 | 2810 | ||
2848 | static struct pcmcia_driver ray_driver = { | 2811 | static struct pcmcia_driver ray_driver = { |
2849 | .owner = THIS_MODULE, | 2812 | .owner = THIS_MODULE, |
2850 | .drv = { | 2813 | .name = "ray_cs", |
2851 | .name = "ray_cs", | ||
2852 | }, | ||
2853 | .probe = ray_probe, | 2814 | .probe = ray_probe, |
2854 | .remove = ray_detach, | 2815 | .remove = ray_detach, |
2855 | .id_table = ray_ids, | 2816 | .id_table = ray_ids, |
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h index 9f01ddb19748..e79848fbcca1 100644 --- a/drivers/net/wireless/ray_cs.h +++ b/drivers/net/wireless/ray_cs.h | |||
@@ -25,8 +25,6 @@ struct beacon_rx { | |||
25 | typedef struct ray_dev_t { | 25 | typedef struct ray_dev_t { |
26 | int card_status; | 26 | int card_status; |
27 | int authentication_state; | 27 | int authentication_state; |
28 | window_handle_t amem_handle; /* handle to window for attribute memory */ | ||
29 | window_handle_t rmem_handle; /* handle to window for rx buffer on card */ | ||
30 | void __iomem *sram; /* pointer to beginning of shared RAM */ | 28 | void __iomem *sram; /* pointer to beginning of shared RAM */ |
31 | void __iomem *amem; /* pointer to attribute mem window */ | 29 | void __iomem *amem; /* pointer to attribute mem window */ |
32 | void __iomem *rmem; /* pointer to receive buffer window */ | 30 | void __iomem *rmem; /* pointer to receive buffer window */ |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index a1cc2d498a1c..ca3f8961fa27 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -48,7 +48,6 @@ | |||
48 | 48 | ||
49 | #include <net/iw_handler.h> | 49 | #include <net/iw_handler.h> |
50 | 50 | ||
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/cisreg.h> | 52 | #include <pcmcia/cisreg.h> |
54 | #include <pcmcia/ds.h> | 53 | #include <pcmcia/ds.h> |
@@ -78,13 +77,6 @@ | |||
78 | #define WL3501_RESUME 0 | 77 | #define WL3501_RESUME 0 |
79 | #define WL3501_SUSPEND 1 | 78 | #define WL3501_SUSPEND 1 |
80 | 79 | ||
81 | /* | ||
82 | * The event() function is this driver's Card Services event handler. It will | ||
83 | * be called by Card Services when an appropriate card status event is | ||
84 | * received. The config() and release() entry points are used to configure or | ||
85 | * release a socket, in response to card insertion and ejection events. They | ||
86 | * are invoked from the wl24 event handler. | ||
87 | */ | ||
88 | static int wl3501_config(struct pcmcia_device *link); | 80 | static int wl3501_config(struct pcmcia_device *link); |
89 | static void wl3501_release(struct pcmcia_device *link); | 81 | static void wl3501_release(struct pcmcia_device *link); |
90 | 82 | ||
@@ -1869,15 +1861,6 @@ static const struct net_device_ops wl3501_netdev_ops = { | |||
1869 | .ndo_validate_addr = eth_validate_addr, | 1861 | .ndo_validate_addr = eth_validate_addr, |
1870 | }; | 1862 | }; |
1871 | 1863 | ||
1872 | /** | ||
1873 | * wl3501_attach - creates an "instance" of the driver | ||
1874 | * | ||
1875 | * Creates an "instance" of the driver, allocating local data structures for | ||
1876 | * one device. The device is registered with Card Services. | ||
1877 | * | ||
1878 | * The dev_link structure is initialized, but we don't actually configure the | ||
1879 | * card at this point -- we wait until we receive a card insertion event. | ||
1880 | */ | ||
1881 | static int wl3501_probe(struct pcmcia_device *p_dev) | 1864 | static int wl3501_probe(struct pcmcia_device *p_dev) |
1882 | { | 1865 | { |
1883 | struct net_device *dev; | 1866 | struct net_device *dev; |
@@ -1888,9 +1871,8 @@ static int wl3501_probe(struct pcmcia_device *p_dev) | |||
1888 | p_dev->resource[0]->flags = IO_DATA_PATH_WIDTH_8; | 1871 | p_dev->resource[0]->flags = IO_DATA_PATH_WIDTH_8; |
1889 | 1872 | ||
1890 | /* General socket configuration */ | 1873 | /* General socket configuration */ |
1891 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 1874 | p_dev->config_flags = CONF_ENABLE_IRQ; |
1892 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 1875 | p_dev->config_index = 1; |
1893 | p_dev->conf.ConfigIndex = 1; | ||
1894 | 1876 | ||
1895 | dev = alloc_etherdev(sizeof(struct wl3501_card)); | 1877 | dev = alloc_etherdev(sizeof(struct wl3501_card)); |
1896 | if (!dev) | 1878 | if (!dev) |
@@ -1914,14 +1896,6 @@ out_link: | |||
1914 | return -ENOMEM; | 1896 | return -ENOMEM; |
1915 | } | 1897 | } |
1916 | 1898 | ||
1917 | /** | ||
1918 | * wl3501_config - configure the PCMCIA socket and make eth device available | ||
1919 | * @link - FILL_IN | ||
1920 | * | ||
1921 | * wl3501_config() is scheduled to run after a CARD_INSERTION event is | ||
1922 | * received, to configure the PCMCIA socket, and to make the ethernet device | ||
1923 | * available to the system. | ||
1924 | */ | ||
1925 | static int wl3501_config(struct pcmcia_device *link) | 1899 | static int wl3501_config(struct pcmcia_device *link) |
1926 | { | 1900 | { |
1927 | struct net_device *dev = link->priv; | 1901 | struct net_device *dev = link->priv; |
@@ -1952,10 +1926,7 @@ static int wl3501_config(struct pcmcia_device *link) | |||
1952 | if (ret) | 1926 | if (ret) |
1953 | goto failed; | 1927 | goto failed; |
1954 | 1928 | ||
1955 | /* This actually configures the PCMCIA socket -- setting up the I/O | 1929 | ret = pcmcia_enable_device(link); |
1956 | * windows and the interrupt mapping. */ | ||
1957 | |||
1958 | ret = pcmcia_request_configuration(link, &link->conf); | ||
1959 | if (ret) | 1930 | if (ret) |
1960 | goto failed; | 1931 | goto failed; |
1961 | 1932 | ||
@@ -2010,14 +1981,6 @@ failed: | |||
2010 | return -ENODEV; | 1981 | return -ENODEV; |
2011 | } | 1982 | } |
2012 | 1983 | ||
2013 | /** | ||
2014 | * wl3501_release - unregister the net, release PCMCIA configuration | ||
2015 | * @arg - link | ||
2016 | * | ||
2017 | * After a card is removed, wl3501_release() will unregister the net device, | ||
2018 | * and release the PCMCIA configuration. If the device is still open, this | ||
2019 | * will be postponed until it is closed. | ||
2020 | */ | ||
2021 | static void wl3501_release(struct pcmcia_device *link) | 1984 | static void wl3501_release(struct pcmcia_device *link) |
2022 | { | 1985 | { |
2023 | pcmcia_disable_device(link); | 1986 | pcmcia_disable_device(link); |
@@ -2056,9 +2019,7 @@ MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); | |||
2056 | 2019 | ||
2057 | static struct pcmcia_driver wl3501_driver = { | 2020 | static struct pcmcia_driver wl3501_driver = { |
2058 | .owner = THIS_MODULE, | 2021 | .owner = THIS_MODULE, |
2059 | .drv = { | 2022 | .name = "wl3501_cs", |
2060 | .name = "wl3501_cs", | ||
2061 | }, | ||
2062 | .probe = wl3501_probe, | 2023 | .probe = wl3501_probe, |
2063 | .remove = wl3501_detach, | 2024 | .remove = wl3501_detach, |
2064 | .id_table = wl3501_ids, | 2025 | .id_table = wl3501_ids, |
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index b336cd9ee7a1..f9bda64fcd1b 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c | |||
@@ -225,26 +225,17 @@ post_sync: | |||
225 | mutex_unlock(&start_mutex); | 225 | mutex_unlock(&start_mutex); |
226 | } | 226 | } |
227 | 227 | ||
228 | int oprofile_set_backtrace(unsigned long val) | 228 | int oprofile_set_ulong(unsigned long *addr, unsigned long val) |
229 | { | 229 | { |
230 | int err = 0; | 230 | int err = -EBUSY; |
231 | 231 | ||
232 | mutex_lock(&start_mutex); | 232 | mutex_lock(&start_mutex); |
233 | 233 | if (!oprofile_started) { | |
234 | if (oprofile_started) { | 234 | *addr = val; |
235 | err = -EBUSY; | 235 | err = 0; |
236 | goto out; | ||
237 | } | ||
238 | |||
239 | if (!oprofile_ops.backtrace) { | ||
240 | err = -EINVAL; | ||
241 | goto out; | ||
242 | } | 236 | } |
243 | |||
244 | oprofile_backtrace_depth = val; | ||
245 | |||
246 | out: | ||
247 | mutex_unlock(&start_mutex); | 237 | mutex_unlock(&start_mutex); |
238 | |||
248 | return err; | 239 | return err; |
249 | } | 240 | } |
250 | 241 | ||
@@ -257,16 +248,9 @@ static int __init oprofile_init(void) | |||
257 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); | 248 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); |
258 | err = oprofile_timer_init(&oprofile_ops); | 249 | err = oprofile_timer_init(&oprofile_ops); |
259 | if (err) | 250 | if (err) |
260 | goto out_arch; | 251 | return err; |
261 | } | 252 | } |
262 | err = oprofilefs_register(); | 253 | return oprofilefs_register(); |
263 | if (err) | ||
264 | goto out_arch; | ||
265 | return 0; | ||
266 | |||
267 | out_arch: | ||
268 | oprofile_arch_exit(); | ||
269 | return err; | ||
270 | } | 254 | } |
271 | 255 | ||
272 | 256 | ||
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index 47e12cb4ee8b..177b73de5e5f 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h | |||
@@ -37,7 +37,7 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root); | |||
37 | int oprofile_timer_init(struct oprofile_operations *ops); | 37 | int oprofile_timer_init(struct oprofile_operations *ops); |
38 | void oprofile_timer_exit(void); | 38 | void oprofile_timer_exit(void); |
39 | 39 | ||
40 | int oprofile_set_backtrace(unsigned long depth); | 40 | int oprofile_set_ulong(unsigned long *addr, unsigned long val); |
41 | int oprofile_set_timeout(unsigned long time); | 41 | int oprofile_set_timeout(unsigned long time); |
42 | 42 | ||
43 | #endif /* OPROF_H */ | 43 | #endif /* OPROF_H */ |
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index bbd7516e0869..ccf099e684a4 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c | |||
@@ -79,14 +79,17 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou | |||
79 | if (*offset) | 79 | if (*offset) |
80 | return -EINVAL; | 80 | return -EINVAL; |
81 | 81 | ||
82 | if (!oprofile_ops.backtrace) | ||
83 | return -EINVAL; | ||
84 | |||
82 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 85 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
83 | if (retval) | 86 | if (retval) |
84 | return retval; | 87 | return retval; |
85 | 88 | ||
86 | retval = oprofile_set_backtrace(val); | 89 | retval = oprofile_set_ulong(&oprofile_backtrace_depth, val); |
87 | |||
88 | if (retval) | 90 | if (retval) |
89 | return retval; | 91 | return retval; |
92 | |||
90 | return count; | 93 | return count; |
91 | } | 94 | } |
92 | 95 | ||
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c new file mode 100644 index 000000000000..9046f7b2ed79 --- /dev/null +++ b/drivers/oprofile/oprofile_perf.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Copyright 2010 ARM Ltd. | ||
3 | * | ||
4 | * Perf-events backend for OProfile. | ||
5 | */ | ||
6 | #include <linux/perf_event.h> | ||
7 | #include <linux/platform_device.h> | ||
8 | #include <linux/oprofile.h> | ||
9 | #include <linux/slab.h> | ||
10 | |||
11 | /* | ||
12 | * Per performance monitor configuration as set via oprofilefs. | ||
13 | */ | ||
14 | struct op_counter_config { | ||
15 | unsigned long count; | ||
16 | unsigned long enabled; | ||
17 | unsigned long event; | ||
18 | unsigned long unit_mask; | ||
19 | unsigned long kernel; | ||
20 | unsigned long user; | ||
21 | struct perf_event_attr attr; | ||
22 | }; | ||
23 | |||
24 | static int oprofile_perf_enabled; | ||
25 | static DEFINE_MUTEX(oprofile_perf_mutex); | ||
26 | |||
27 | static struct op_counter_config *counter_config; | ||
28 | static struct perf_event **perf_events[nr_cpumask_bits]; | ||
29 | static int num_counters; | ||
30 | |||
31 | /* | ||
32 | * Overflow callback for oprofile. | ||
33 | */ | ||
34 | static void op_overflow_handler(struct perf_event *event, int unused, | ||
35 | struct perf_sample_data *data, struct pt_regs *regs) | ||
36 | { | ||
37 | int id; | ||
38 | u32 cpu = smp_processor_id(); | ||
39 | |||
40 | for (id = 0; id < num_counters; ++id) | ||
41 | if (perf_events[cpu][id] == event) | ||
42 | break; | ||
43 | |||
44 | if (id != num_counters) | ||
45 | oprofile_add_sample(regs, id); | ||
46 | else | ||
47 | pr_warning("oprofile: ignoring spurious overflow " | ||
48 | "on cpu %u\n", cpu); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Called by oprofile_perf_setup to create perf attributes to mirror the oprofile | ||
53 | * settings in counter_config. Attributes are created as `pinned' events and | ||
54 | * so are permanently scheduled on the PMU. | ||
55 | */ | ||
56 | static void op_perf_setup(void) | ||
57 | { | ||
58 | int i; | ||
59 | u32 size = sizeof(struct perf_event_attr); | ||
60 | struct perf_event_attr *attr; | ||
61 | |||
62 | for (i = 0; i < num_counters; ++i) { | ||
63 | attr = &counter_config[i].attr; | ||
64 | memset(attr, 0, size); | ||
65 | attr->type = PERF_TYPE_RAW; | ||
66 | attr->size = size; | ||
67 | attr->config = counter_config[i].event; | ||
68 | attr->sample_period = counter_config[i].count; | ||
69 | attr->pinned = 1; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static int op_create_counter(int cpu, int event) | ||
74 | { | ||
75 | struct perf_event *pevent; | ||
76 | |||
77 | if (!counter_config[event].enabled || perf_events[cpu][event]) | ||
78 | return 0; | ||
79 | |||
80 | pevent = perf_event_create_kernel_counter(&counter_config[event].attr, | ||
81 | cpu, NULL, | ||
82 | op_overflow_handler); | ||
83 | |||
84 | if (IS_ERR(pevent)) | ||
85 | return PTR_ERR(pevent); | ||
86 | |||
87 | if (pevent->state != PERF_EVENT_STATE_ACTIVE) { | ||
88 | perf_event_release_kernel(pevent); | ||
89 | pr_warning("oprofile: failed to enable event %d " | ||
90 | "on CPU %d\n", event, cpu); | ||
91 | return -EBUSY; | ||
92 | } | ||
93 | |||
94 | perf_events[cpu][event] = pevent; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static void op_destroy_counter(int cpu, int event) | ||
100 | { | ||
101 | struct perf_event *pevent = perf_events[cpu][event]; | ||
102 | |||
103 | if (pevent) { | ||
104 | perf_event_release_kernel(pevent); | ||
105 | perf_events[cpu][event] = NULL; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Called by oprofile_perf_start to create active perf events based on the | ||
111 | * perviously configured attributes. | ||
112 | */ | ||
113 | static int op_perf_start(void) | ||
114 | { | ||
115 | int cpu, event, ret = 0; | ||
116 | |||
117 | for_each_online_cpu(cpu) { | ||
118 | for (event = 0; event < num_counters; ++event) { | ||
119 | ret = op_create_counter(cpu, event); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Called by oprofile_perf_stop at the end of a profiling run. | ||
130 | */ | ||
131 | static void op_perf_stop(void) | ||
132 | { | ||
133 | int cpu, event; | ||
134 | |||
135 | for_each_online_cpu(cpu) | ||
136 | for (event = 0; event < num_counters; ++event) | ||
137 | op_destroy_counter(cpu, event); | ||
138 | } | ||
139 | |||
140 | static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root) | ||
141 | { | ||
142 | unsigned int i; | ||
143 | |||
144 | for (i = 0; i < num_counters; i++) { | ||
145 | struct dentry *dir; | ||
146 | char buf[4]; | ||
147 | |||
148 | snprintf(buf, sizeof buf, "%d", i); | ||
149 | dir = oprofilefs_mkdir(sb, root, buf); | ||
150 | oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); | ||
151 | oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event); | ||
152 | oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count); | ||
153 | oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask); | ||
154 | oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel); | ||
155 | oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user); | ||
156 | } | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int oprofile_perf_setup(void) | ||
162 | { | ||
163 | spin_lock(&oprofilefs_lock); | ||
164 | op_perf_setup(); | ||
165 | spin_unlock(&oprofilefs_lock); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int oprofile_perf_start(void) | ||
170 | { | ||
171 | int ret = -EBUSY; | ||
172 | |||
173 | mutex_lock(&oprofile_perf_mutex); | ||
174 | if (!oprofile_perf_enabled) { | ||
175 | ret = 0; | ||
176 | op_perf_start(); | ||
177 | oprofile_perf_enabled = 1; | ||
178 | } | ||
179 | mutex_unlock(&oprofile_perf_mutex); | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | static void oprofile_perf_stop(void) | ||
184 | { | ||
185 | mutex_lock(&oprofile_perf_mutex); | ||
186 | if (oprofile_perf_enabled) | ||
187 | op_perf_stop(); | ||
188 | oprofile_perf_enabled = 0; | ||
189 | mutex_unlock(&oprofile_perf_mutex); | ||
190 | } | ||
191 | |||
192 | #ifdef CONFIG_PM | ||
193 | |||
194 | static int oprofile_perf_suspend(struct platform_device *dev, pm_message_t state) | ||
195 | { | ||
196 | mutex_lock(&oprofile_perf_mutex); | ||
197 | if (oprofile_perf_enabled) | ||
198 | op_perf_stop(); | ||
199 | mutex_unlock(&oprofile_perf_mutex); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int oprofile_perf_resume(struct platform_device *dev) | ||
204 | { | ||
205 | mutex_lock(&oprofile_perf_mutex); | ||
206 | if (oprofile_perf_enabled && op_perf_start()) | ||
207 | oprofile_perf_enabled = 0; | ||
208 | mutex_unlock(&oprofile_perf_mutex); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static struct platform_driver oprofile_driver = { | ||
213 | .driver = { | ||
214 | .name = "oprofile-perf", | ||
215 | }, | ||
216 | .resume = oprofile_perf_resume, | ||
217 | .suspend = oprofile_perf_suspend, | ||
218 | }; | ||
219 | |||
220 | static struct platform_device *oprofile_pdev; | ||
221 | |||
222 | static int __init init_driverfs(void) | ||
223 | { | ||
224 | int ret; | ||
225 | |||
226 | ret = platform_driver_register(&oprofile_driver); | ||
227 | if (ret) | ||
228 | return ret; | ||
229 | |||
230 | oprofile_pdev = platform_device_register_simple( | ||
231 | oprofile_driver.driver.name, 0, NULL, 0); | ||
232 | if (IS_ERR(oprofile_pdev)) { | ||
233 | ret = PTR_ERR(oprofile_pdev); | ||
234 | platform_driver_unregister(&oprofile_driver); | ||
235 | } | ||
236 | |||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static void exit_driverfs(void) | ||
241 | { | ||
242 | platform_device_unregister(oprofile_pdev); | ||
243 | platform_driver_unregister(&oprofile_driver); | ||
244 | } | ||
245 | |||
246 | #else | ||
247 | |||
248 | static inline int init_driverfs(void) { return 0; } | ||
249 | static inline void exit_driverfs(void) { } | ||
250 | |||
251 | #endif /* CONFIG_PM */ | ||
252 | |||
253 | void oprofile_perf_exit(void) | ||
254 | { | ||
255 | int cpu, id; | ||
256 | struct perf_event *event; | ||
257 | |||
258 | for_each_possible_cpu(cpu) { | ||
259 | for (id = 0; id < num_counters; ++id) { | ||
260 | event = perf_events[cpu][id]; | ||
261 | if (event) | ||
262 | perf_event_release_kernel(event); | ||
263 | } | ||
264 | |||
265 | kfree(perf_events[cpu]); | ||
266 | } | ||
267 | |||
268 | kfree(counter_config); | ||
269 | exit_driverfs(); | ||
270 | } | ||
271 | |||
272 | int __init oprofile_perf_init(struct oprofile_operations *ops) | ||
273 | { | ||
274 | int cpu, ret = 0; | ||
275 | |||
276 | ret = init_driverfs(); | ||
277 | if (ret) | ||
278 | return ret; | ||
279 | |||
280 | memset(&perf_events, 0, sizeof(perf_events)); | ||
281 | |||
282 | num_counters = perf_num_counters(); | ||
283 | if (num_counters <= 0) { | ||
284 | pr_info("oprofile: no performance counters\n"); | ||
285 | ret = -ENODEV; | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | counter_config = kcalloc(num_counters, | ||
290 | sizeof(struct op_counter_config), GFP_KERNEL); | ||
291 | |||
292 | if (!counter_config) { | ||
293 | pr_info("oprofile: failed to allocate %d " | ||
294 | "counters\n", num_counters); | ||
295 | ret = -ENOMEM; | ||
296 | num_counters = 0; | ||
297 | goto out; | ||
298 | } | ||
299 | |||
300 | for_each_possible_cpu(cpu) { | ||
301 | perf_events[cpu] = kcalloc(num_counters, | ||
302 | sizeof(struct perf_event *), GFP_KERNEL); | ||
303 | if (!perf_events[cpu]) { | ||
304 | pr_info("oprofile: failed to allocate %d perf events " | ||
305 | "for cpu %d\n", num_counters, cpu); | ||
306 | ret = -ENOMEM; | ||
307 | goto out; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | ops->create_files = oprofile_perf_create_files; | ||
312 | ops->setup = oprofile_perf_setup; | ||
313 | ops->start = oprofile_perf_start; | ||
314 | ops->stop = oprofile_perf_stop; | ||
315 | ops->shutdown = oprofile_perf_stop; | ||
316 | ops->cpu_type = op_name_from_perf_id(); | ||
317 | |||
318 | if (!ops->cpu_type) | ||
319 | ret = -ENODEV; | ||
320 | else | ||
321 | pr_info("oprofile: using %s\n", ops->cpu_type); | ||
322 | |||
323 | out: | ||
324 | if (ret) | ||
325 | oprofile_perf_exit(); | ||
326 | |||
327 | return ret; | ||
328 | } | ||
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index 2766a6d3c2e9..1944621930d9 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c | |||
@@ -91,16 +91,20 @@ static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count | |||
91 | 91 | ||
92 | static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset) | 92 | static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset) |
93 | { | 93 | { |
94 | unsigned long *value = file->private_data; | 94 | unsigned long value; |
95 | int retval; | 95 | int retval; |
96 | 96 | ||
97 | if (*offset) | 97 | if (*offset) |
98 | return -EINVAL; | 98 | return -EINVAL; |
99 | 99 | ||
100 | retval = oprofilefs_ulong_from_user(value, buf, count); | 100 | retval = oprofilefs_ulong_from_user(&value, buf, count); |
101 | if (retval) | ||
102 | return retval; | ||
101 | 103 | ||
104 | retval = oprofile_set_ulong(file->private_data, value); | ||
102 | if (retval) | 105 | if (retval) |
103 | return retval; | 106 | return retval; |
107 | |||
104 | return count; | 108 | return count; |
105 | } | 109 | } |
106 | 110 | ||
@@ -126,50 +130,41 @@ static const struct file_operations ulong_ro_fops = { | |||
126 | }; | 130 | }; |
127 | 131 | ||
128 | 132 | ||
129 | static struct dentry *__oprofilefs_create_file(struct super_block *sb, | 133 | static int __oprofilefs_create_file(struct super_block *sb, |
130 | struct dentry *root, char const *name, const struct file_operations *fops, | 134 | struct dentry *root, char const *name, const struct file_operations *fops, |
131 | int perm) | 135 | int perm, void *priv) |
132 | { | 136 | { |
133 | struct dentry *dentry; | 137 | struct dentry *dentry; |
134 | struct inode *inode; | 138 | struct inode *inode; |
135 | 139 | ||
136 | dentry = d_alloc_name(root, name); | 140 | dentry = d_alloc_name(root, name); |
137 | if (!dentry) | 141 | if (!dentry) |
138 | return NULL; | 142 | return -ENOMEM; |
139 | inode = oprofilefs_get_inode(sb, S_IFREG | perm); | 143 | inode = oprofilefs_get_inode(sb, S_IFREG | perm); |
140 | if (!inode) { | 144 | if (!inode) { |
141 | dput(dentry); | 145 | dput(dentry); |
142 | return NULL; | 146 | return -ENOMEM; |
143 | } | 147 | } |
144 | inode->i_fop = fops; | 148 | inode->i_fop = fops; |
145 | d_add(dentry, inode); | 149 | d_add(dentry, inode); |
146 | return dentry; | 150 | dentry->d_inode->i_private = priv; |
151 | return 0; | ||
147 | } | 152 | } |
148 | 153 | ||
149 | 154 | ||
150 | int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root, | 155 | int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root, |
151 | char const *name, unsigned long *val) | 156 | char const *name, unsigned long *val) |
152 | { | 157 | { |
153 | struct dentry *d = __oprofilefs_create_file(sb, root, name, | 158 | return __oprofilefs_create_file(sb, root, name, |
154 | &ulong_fops, 0644); | 159 | &ulong_fops, 0644, val); |
155 | if (!d) | ||
156 | return -EFAULT; | ||
157 | |||
158 | d->d_inode->i_private = val; | ||
159 | return 0; | ||
160 | } | 160 | } |
161 | 161 | ||
162 | 162 | ||
163 | int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root, | 163 | int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root, |
164 | char const *name, unsigned long *val) | 164 | char const *name, unsigned long *val) |
165 | { | 165 | { |
166 | struct dentry *d = __oprofilefs_create_file(sb, root, name, | 166 | return __oprofilefs_create_file(sb, root, name, |
167 | &ulong_ro_fops, 0444); | 167 | &ulong_ro_fops, 0444, val); |
168 | if (!d) | ||
169 | return -EFAULT; | ||
170 | |||
171 | d->d_inode->i_private = val; | ||
172 | return 0; | ||
173 | } | 168 | } |
174 | 169 | ||
175 | 170 | ||
@@ -189,31 +184,22 @@ static const struct file_operations atomic_ro_fops = { | |||
189 | int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root, | 184 | int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root, |
190 | char const *name, atomic_t *val) | 185 | char const *name, atomic_t *val) |
191 | { | 186 | { |
192 | struct dentry *d = __oprofilefs_create_file(sb, root, name, | 187 | return __oprofilefs_create_file(sb, root, name, |
193 | &atomic_ro_fops, 0444); | 188 | &atomic_ro_fops, 0444, val); |
194 | if (!d) | ||
195 | return -EFAULT; | ||
196 | |||
197 | d->d_inode->i_private = val; | ||
198 | return 0; | ||
199 | } | 189 | } |
200 | 190 | ||
201 | 191 | ||
202 | int oprofilefs_create_file(struct super_block *sb, struct dentry *root, | 192 | int oprofilefs_create_file(struct super_block *sb, struct dentry *root, |
203 | char const *name, const struct file_operations *fops) | 193 | char const *name, const struct file_operations *fops) |
204 | { | 194 | { |
205 | if (!__oprofilefs_create_file(sb, root, name, fops, 0644)) | 195 | return __oprofilefs_create_file(sb, root, name, fops, 0644, NULL); |
206 | return -EFAULT; | ||
207 | return 0; | ||
208 | } | 196 | } |
209 | 197 | ||
210 | 198 | ||
211 | int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root, | 199 | int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root, |
212 | char const *name, const struct file_operations *fops, int perm) | 200 | char const *name, const struct file_operations *fops, int perm) |
213 | { | 201 | { |
214 | if (!__oprofilefs_create_file(sb, root, name, fops, perm)) | 202 | return __oprofilefs_create_file(sb, root, name, fops, perm, NULL); |
215 | return -EFAULT; | ||
216 | return 0; | ||
217 | } | 203 | } |
218 | 204 | ||
219 | 205 | ||
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 23e50f4a27c5..787ebdeae310 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include <linux/parport.h> | 48 | #include <linux/parport.h> |
49 | #include <linux/parport_pc.h> | 49 | #include <linux/parport_pc.h> |
50 | 50 | ||
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
54 | #include <pcmcia/cisreg.h> | 53 | #include <pcmcia/cisreg.h> |
@@ -81,14 +80,6 @@ static void parport_detach(struct pcmcia_device *p_dev); | |||
81 | static int parport_config(struct pcmcia_device *link); | 80 | static int parport_config(struct pcmcia_device *link); |
82 | static void parport_cs_release(struct pcmcia_device *); | 81 | static void parport_cs_release(struct pcmcia_device *); |
83 | 82 | ||
84 | /*====================================================================== | ||
85 | |||
86 | parport_attach() creates an "instance" of the driver, allocating | ||
87 | local data structures for one device. The device is registered | ||
88 | with Card Services. | ||
89 | |||
90 | ======================================================================*/ | ||
91 | |||
92 | static int parport_probe(struct pcmcia_device *link) | 83 | static int parport_probe(struct pcmcia_device *link) |
93 | { | 84 | { |
94 | parport_info_t *info; | 85 | parport_info_t *info; |
@@ -101,23 +92,11 @@ static int parport_probe(struct pcmcia_device *link) | |||
101 | link->priv = info; | 92 | link->priv = info; |
102 | info->p_dev = link; | 93 | info->p_dev = link; |
103 | 94 | ||
104 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 95 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
105 | link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
106 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
107 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
108 | 96 | ||
109 | return parport_config(link); | 97 | return parport_config(link); |
110 | } /* parport_attach */ | 98 | } /* parport_attach */ |
111 | 99 | ||
112 | /*====================================================================== | ||
113 | |||
114 | This deletes a driver "instance". The device is de-registered | ||
115 | with Card Services. If it has been released, all local data | ||
116 | structures are freed. Otherwise, the structures will be freed | ||
117 | when the device is released. | ||
118 | |||
119 | ======================================================================*/ | ||
120 | |||
121 | static void parport_detach(struct pcmcia_device *link) | 100 | static void parport_detach(struct pcmcia_device *link) |
122 | { | 101 | { |
123 | dev_dbg(&link->dev, "parport_detach\n"); | 102 | dev_dbg(&link->dev, "parport_detach\n"); |
@@ -127,36 +106,14 @@ static void parport_detach(struct pcmcia_device *link) | |||
127 | kfree(link->priv); | 106 | kfree(link->priv); |
128 | } /* parport_detach */ | 107 | } /* parport_detach */ |
129 | 108 | ||
130 | /*====================================================================== | 109 | static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data) |
131 | |||
132 | parport_config() is scheduled to run after a CARD_INSERTION event | ||
133 | is received, to configure the PCMCIA socket, and to make the | ||
134 | parport device available to the system. | ||
135 | |||
136 | ======================================================================*/ | ||
137 | |||
138 | static int parport_config_check(struct pcmcia_device *p_dev, | ||
139 | cistpl_cftable_entry_t *cfg, | ||
140 | cistpl_cftable_entry_t *dflt, | ||
141 | unsigned int vcc, | ||
142 | void *priv_data) | ||
143 | { | 110 | { |
144 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | 111 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
145 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | 112 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
146 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 113 | p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; |
147 | if (epp_mode) | 114 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
148 | p_dev->conf.ConfigIndex |= FORCE_EPP_MODE; | 115 | |
149 | p_dev->resource[0]->start = io->win[0].base; | 116 | return pcmcia_request_io(p_dev); |
150 | p_dev->resource[0]->end = io->win[0].len; | ||
151 | if (io->nwin == 2) { | ||
152 | p_dev->resource[1]->start = io->win[1].base; | ||
153 | p_dev->resource[1]->end = io->win[1].len; | ||
154 | } | ||
155 | if (pcmcia_request_io(p_dev) != 0) | ||
156 | return -ENODEV; | ||
157 | return 0; | ||
158 | } | ||
159 | return -ENODEV; | ||
160 | } | 117 | } |
161 | 118 | ||
162 | static int parport_config(struct pcmcia_device *link) | 119 | static int parport_config(struct pcmcia_device *link) |
@@ -167,13 +124,16 @@ static int parport_config(struct pcmcia_device *link) | |||
167 | 124 | ||
168 | dev_dbg(&link->dev, "parport_config\n"); | 125 | dev_dbg(&link->dev, "parport_config\n"); |
169 | 126 | ||
127 | if (epp_mode) | ||
128 | link->config_index |= FORCE_EPP_MODE; | ||
129 | |||
170 | ret = pcmcia_loop_config(link, parport_config_check, NULL); | 130 | ret = pcmcia_loop_config(link, parport_config_check, NULL); |
171 | if (ret) | 131 | if (ret) |
172 | goto failed; | 132 | goto failed; |
173 | 133 | ||
174 | if (!link->irq) | 134 | if (!link->irq) |
175 | goto failed; | 135 | goto failed; |
176 | ret = pcmcia_request_configuration(link, &link->conf); | 136 | ret = pcmcia_enable_device(link); |
177 | if (ret) | 137 | if (ret) |
178 | goto failed; | 138 | goto failed; |
179 | 139 | ||
@@ -202,14 +162,6 @@ failed: | |||
202 | return -ENODEV; | 162 | return -ENODEV; |
203 | } /* parport_config */ | 163 | } /* parport_config */ |
204 | 164 | ||
205 | /*====================================================================== | ||
206 | |||
207 | After a card is removed, parport_cs_release() will unregister the | ||
208 | device, and release the PCMCIA configuration. If the device is | ||
209 | still open, this will be postponed until it is closed. | ||
210 | |||
211 | ======================================================================*/ | ||
212 | |||
213 | static void parport_cs_release(struct pcmcia_device *link) | 165 | static void parport_cs_release(struct pcmcia_device *link) |
214 | { | 166 | { |
215 | parport_info_t *info = link->priv; | 167 | parport_info_t *info = link->priv; |
@@ -236,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, parport_ids); | |||
236 | 188 | ||
237 | static struct pcmcia_driver parport_cs_driver = { | 189 | static struct pcmcia_driver parport_cs_driver = { |
238 | .owner = THIS_MODULE, | 190 | .owner = THIS_MODULE, |
239 | .drv = { | 191 | .name = "parport_cs", |
240 | .name = "parport_cs", | ||
241 | }, | ||
242 | .probe = parport_probe, | 192 | .probe = parport_probe, |
243 | .remove = parport_detach, | 193 | .remove = parport_detach, |
244 | .id_table = parport_ids, | 194 | .id_table = parport_ids, |
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index dffa5d4fb298..a2d9d1e59260 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
@@ -306,7 +306,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, | |||
306 | spin_lock_init(&tmp->pardevice_lock); | 306 | spin_lock_init(&tmp->pardevice_lock); |
307 | tmp->ieee1284.mode = IEEE1284_MODE_COMPAT; | 307 | tmp->ieee1284.mode = IEEE1284_MODE_COMPAT; |
308 | tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; | 308 | tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE; |
309 | init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */ | 309 | sema_init(&tmp->ieee1284.irq, 0); |
310 | tmp->spintime = parport_default_spintime; | 310 | tmp->spintime = parport_default_spintime; |
311 | atomic_set (&tmp->ref_count, 1); | 311 | atomic_set (&tmp->ref_count, 1); |
312 | INIT_LIST_HEAD(&tmp->full_list); | 312 | INIT_LIST_HEAD(&tmp->full_list); |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0a19708074c2..0157708d474d 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/tboot.h> | 36 | #include <linux/tboot.h> |
37 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <asm/iommu_table.h> | ||
39 | 40 | ||
40 | #define PREFIX "DMAR: " | 41 | #define PREFIX "DMAR: " |
41 | 42 | ||
@@ -687,7 +688,7 @@ failed: | |||
687 | return 0; | 688 | return 0; |
688 | } | 689 | } |
689 | 690 | ||
690 | void __init detect_intel_iommu(void) | 691 | int __init detect_intel_iommu(void) |
691 | { | 692 | { |
692 | int ret; | 693 | int ret; |
693 | 694 | ||
@@ -723,6 +724,8 @@ void __init detect_intel_iommu(void) | |||
723 | } | 724 | } |
724 | early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size); | 725 | early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size); |
725 | dmar_tbl = NULL; | 726 | dmar_tbl = NULL; |
727 | |||
728 | return ret ? 1 : -ENODEV; | ||
726 | } | 729 | } |
727 | 730 | ||
728 | 731 | ||
@@ -1221,9 +1224,9 @@ const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type) | |||
1221 | } | 1224 | } |
1222 | } | 1225 | } |
1223 | 1226 | ||
1224 | void dmar_msi_unmask(unsigned int irq) | 1227 | void dmar_msi_unmask(struct irq_data *data) |
1225 | { | 1228 | { |
1226 | struct intel_iommu *iommu = get_irq_data(irq); | 1229 | struct intel_iommu *iommu = irq_data_get_irq_data(data); |
1227 | unsigned long flag; | 1230 | unsigned long flag; |
1228 | 1231 | ||
1229 | /* unmask it */ | 1232 | /* unmask it */ |
@@ -1234,10 +1237,10 @@ void dmar_msi_unmask(unsigned int irq) | |||
1234 | spin_unlock_irqrestore(&iommu->register_lock, flag); | 1237 | spin_unlock_irqrestore(&iommu->register_lock, flag); |
1235 | } | 1238 | } |
1236 | 1239 | ||
1237 | void dmar_msi_mask(unsigned int irq) | 1240 | void dmar_msi_mask(struct irq_data *data) |
1238 | { | 1241 | { |
1239 | unsigned long flag; | 1242 | unsigned long flag; |
1240 | struct intel_iommu *iommu = get_irq_data(irq); | 1243 | struct intel_iommu *iommu = irq_data_get_irq_data(data); |
1241 | 1244 | ||
1242 | /* mask it */ | 1245 | /* mask it */ |
1243 | spin_lock_irqsave(&iommu->register_lock, flag); | 1246 | spin_lock_irqsave(&iommu->register_lock, flag); |
@@ -1455,3 +1458,4 @@ int __init dmar_ir_support(void) | |||
1455 | return 0; | 1458 | return 0; |
1456 | return dmar->flags & 0x1; | 1459 | return dmar->flags & 0x1; |
1457 | } | 1460 | } |
1461 | IOMMU_INIT_POST(detect_intel_iommu); | ||
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 98abf8b91294..834842aa5bbf 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
@@ -57,28 +57,22 @@ void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | |||
57 | *msg = cfg->msg; | 57 | *msg = cfg->msg; |
58 | } | 58 | } |
59 | 59 | ||
60 | void mask_ht_irq(unsigned int irq) | 60 | void mask_ht_irq(struct irq_data *data) |
61 | { | 61 | { |
62 | struct ht_irq_cfg *cfg; | 62 | struct ht_irq_cfg *cfg = irq_data_get_irq_data(data); |
63 | struct ht_irq_msg msg; | 63 | struct ht_irq_msg msg = cfg->msg; |
64 | |||
65 | cfg = get_irq_data(irq); | ||
66 | 64 | ||
67 | msg = cfg->msg; | ||
68 | msg.address_lo |= 1; | 65 | msg.address_lo |= 1; |
69 | write_ht_irq_msg(irq, &msg); | 66 | write_ht_irq_msg(data->irq, &msg); |
70 | } | 67 | } |
71 | 68 | ||
72 | void unmask_ht_irq(unsigned int irq) | 69 | void unmask_ht_irq(struct irq_data *data) |
73 | { | 70 | { |
74 | struct ht_irq_cfg *cfg; | 71 | struct ht_irq_cfg *cfg = irq_data_get_irq_data(data); |
75 | struct ht_irq_msg msg; | 72 | struct ht_irq_msg msg = cfg->msg; |
76 | |||
77 | cfg = get_irq_data(irq); | ||
78 | 73 | ||
79 | msg = cfg->msg; | ||
80 | msg.address_lo &= ~1; | 74 | msg.address_lo &= ~1; |
81 | write_ht_irq_msg(irq, &msg); | 75 | write_ht_irq_msg(data->irq, &msg); |
82 | } | 76 | } |
83 | 77 | ||
84 | /** | 78 | /** |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index fd1d2867cdcc..ec87cd66f3eb 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -46,109 +46,24 @@ static __init int setup_intremap(char *str) | |||
46 | } | 46 | } |
47 | early_param("intremap", setup_intremap); | 47 | early_param("intremap", setup_intremap); |
48 | 48 | ||
49 | struct irq_2_iommu { | ||
50 | struct intel_iommu *iommu; | ||
51 | u16 irte_index; | ||
52 | u16 sub_handle; | ||
53 | u8 irte_mask; | ||
54 | }; | ||
55 | |||
56 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
57 | static struct irq_2_iommu *get_one_free_irq_2_iommu(int node) | ||
58 | { | ||
59 | struct irq_2_iommu *iommu; | ||
60 | |||
61 | iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); | ||
62 | printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node); | ||
63 | |||
64 | return iommu; | ||
65 | } | ||
66 | |||
67 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | ||
68 | { | ||
69 | struct irq_desc *desc; | ||
70 | |||
71 | desc = irq_to_desc(irq); | ||
72 | |||
73 | if (WARN_ON_ONCE(!desc)) | ||
74 | return NULL; | ||
75 | |||
76 | return desc->irq_2_iommu; | ||
77 | } | ||
78 | |||
79 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | ||
80 | { | ||
81 | struct irq_desc *desc; | ||
82 | struct irq_2_iommu *irq_iommu; | ||
83 | |||
84 | desc = irq_to_desc(irq); | ||
85 | if (!desc) { | ||
86 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | irq_iommu = desc->irq_2_iommu; | ||
91 | |||
92 | if (!irq_iommu) | ||
93 | desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq)); | ||
94 | |||
95 | return desc->irq_2_iommu; | ||
96 | } | ||
97 | |||
98 | #else /* !CONFIG_SPARSE_IRQ */ | ||
99 | |||
100 | static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; | ||
101 | |||
102 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | ||
103 | { | ||
104 | if (irq < nr_irqs) | ||
105 | return &irq_2_iommuX[irq]; | ||
106 | |||
107 | return NULL; | ||
108 | } | ||
109 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | ||
110 | { | ||
111 | return irq_2_iommu(irq); | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | static DEFINE_SPINLOCK(irq_2_ir_lock); | 49 | static DEFINE_SPINLOCK(irq_2_ir_lock); |
116 | 50 | ||
117 | static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq) | 51 | static struct irq_2_iommu *irq_2_iommu(unsigned int irq) |
118 | { | ||
119 | struct irq_2_iommu *irq_iommu; | ||
120 | |||
121 | irq_iommu = irq_2_iommu(irq); | ||
122 | |||
123 | if (!irq_iommu) | ||
124 | return NULL; | ||
125 | |||
126 | if (!irq_iommu->iommu) | ||
127 | return NULL; | ||
128 | |||
129 | return irq_iommu; | ||
130 | } | ||
131 | |||
132 | int irq_remapped(int irq) | ||
133 | { | 52 | { |
134 | return valid_irq_2_iommu(irq) != NULL; | 53 | struct irq_cfg *cfg = get_irq_chip_data(irq); |
54 | return cfg ? &cfg->irq_2_iommu : NULL; | ||
135 | } | 55 | } |
136 | 56 | ||
137 | int get_irte(int irq, struct irte *entry) | 57 | int get_irte(int irq, struct irte *entry) |
138 | { | 58 | { |
139 | int index; | 59 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
140 | struct irq_2_iommu *irq_iommu; | ||
141 | unsigned long flags; | 60 | unsigned long flags; |
61 | int index; | ||
142 | 62 | ||
143 | if (!entry) | 63 | if (!entry || !irq_iommu) |
144 | return -1; | 64 | return -1; |
145 | 65 | ||
146 | spin_lock_irqsave(&irq_2_ir_lock, flags); | 66 | spin_lock_irqsave(&irq_2_ir_lock, flags); |
147 | irq_iommu = valid_irq_2_iommu(irq); | ||
148 | if (!irq_iommu) { | ||
149 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
150 | return -1; | ||
151 | } | ||
152 | 67 | ||
153 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | 68 | index = irq_iommu->irte_index + irq_iommu->sub_handle; |
154 | *entry = *(irq_iommu->iommu->ir_table->base + index); | 69 | *entry = *(irq_iommu->iommu->ir_table->base + index); |
@@ -160,20 +75,14 @@ int get_irte(int irq, struct irte *entry) | |||
160 | int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | 75 | int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) |
161 | { | 76 | { |
162 | struct ir_table *table = iommu->ir_table; | 77 | struct ir_table *table = iommu->ir_table; |
163 | struct irq_2_iommu *irq_iommu; | 78 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
164 | u16 index, start_index; | 79 | u16 index, start_index; |
165 | unsigned int mask = 0; | 80 | unsigned int mask = 0; |
166 | unsigned long flags; | 81 | unsigned long flags; |
167 | int i; | 82 | int i; |
168 | 83 | ||
169 | if (!count) | 84 | if (!count || !irq_iommu) |
170 | return -1; | ||
171 | |||
172 | #ifndef CONFIG_SPARSE_IRQ | ||
173 | /* protect irq_2_iommu_alloc later */ | ||
174 | if (irq >= nr_irqs) | ||
175 | return -1; | 85 | return -1; |
176 | #endif | ||
177 | 86 | ||
178 | /* | 87 | /* |
179 | * start the IRTE search from index 0. | 88 | * start the IRTE search from index 0. |
@@ -214,13 +123,6 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
214 | for (i = index; i < index + count; i++) | 123 | for (i = index; i < index + count; i++) |
215 | table->base[i].present = 1; | 124 | table->base[i].present = 1; |
216 | 125 | ||
217 | irq_iommu = irq_2_iommu_alloc(irq); | ||
218 | if (!irq_iommu) { | ||
219 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
220 | printk(KERN_ERR "can't allocate irq_2_iommu\n"); | ||
221 | return -1; | ||
222 | } | ||
223 | |||
224 | irq_iommu->iommu = iommu; | 126 | irq_iommu->iommu = iommu; |
225 | irq_iommu->irte_index = index; | 127 | irq_iommu->irte_index = index; |
226 | irq_iommu->sub_handle = 0; | 128 | irq_iommu->sub_handle = 0; |
@@ -244,17 +146,14 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask) | |||
244 | 146 | ||
245 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) | 147 | int map_irq_to_irte_handle(int irq, u16 *sub_handle) |
246 | { | 148 | { |
247 | int index; | 149 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
248 | struct irq_2_iommu *irq_iommu; | ||
249 | unsigned long flags; | 150 | unsigned long flags; |
151 | int index; | ||
250 | 152 | ||
251 | spin_lock_irqsave(&irq_2_ir_lock, flags); | 153 | if (!irq_iommu) |
252 | irq_iommu = valid_irq_2_iommu(irq); | ||
253 | if (!irq_iommu) { | ||
254 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
255 | return -1; | 154 | return -1; |
256 | } | ||
257 | 155 | ||
156 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
258 | *sub_handle = irq_iommu->sub_handle; | 157 | *sub_handle = irq_iommu->sub_handle; |
259 | index = irq_iommu->irte_index; | 158 | index = irq_iommu->irte_index; |
260 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | 159 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); |
@@ -263,18 +162,13 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle) | |||
263 | 162 | ||
264 | int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) | 163 | int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) |
265 | { | 164 | { |
266 | struct irq_2_iommu *irq_iommu; | 165 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
267 | unsigned long flags; | 166 | unsigned long flags; |
268 | 167 | ||
269 | spin_lock_irqsave(&irq_2_ir_lock, flags); | 168 | if (!irq_iommu) |
270 | |||
271 | irq_iommu = irq_2_iommu_alloc(irq); | ||
272 | |||
273 | if (!irq_iommu) { | ||
274 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
275 | printk(KERN_ERR "can't allocate irq_2_iommu\n"); | ||
276 | return -1; | 169 | return -1; |
277 | } | 170 | |
171 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
278 | 172 | ||
279 | irq_iommu->iommu = iommu; | 173 | irq_iommu->iommu = iommu; |
280 | irq_iommu->irte_index = index; | 174 | irq_iommu->irte_index = index; |
@@ -286,43 +180,18 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) | |||
286 | return 0; | 180 | return 0; |
287 | } | 181 | } |
288 | 182 | ||
289 | int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index) | ||
290 | { | ||
291 | struct irq_2_iommu *irq_iommu; | ||
292 | unsigned long flags; | ||
293 | |||
294 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
295 | irq_iommu = valid_irq_2_iommu(irq); | ||
296 | if (!irq_iommu) { | ||
297 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
298 | return -1; | ||
299 | } | ||
300 | |||
301 | irq_iommu->iommu = NULL; | ||
302 | irq_iommu->irte_index = 0; | ||
303 | irq_iommu->sub_handle = 0; | ||
304 | irq_2_iommu(irq)->irte_mask = 0; | ||
305 | |||
306 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | int modify_irte(int irq, struct irte *irte_modified) | 183 | int modify_irte(int irq, struct irte *irte_modified) |
312 | { | 184 | { |
313 | int rc; | 185 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
314 | int index; | ||
315 | struct irte *irte; | ||
316 | struct intel_iommu *iommu; | 186 | struct intel_iommu *iommu; |
317 | struct irq_2_iommu *irq_iommu; | ||
318 | unsigned long flags; | 187 | unsigned long flags; |
188 | struct irte *irte; | ||
189 | int rc, index; | ||
319 | 190 | ||
320 | spin_lock_irqsave(&irq_2_ir_lock, flags); | 191 | if (!irq_iommu) |
321 | irq_iommu = valid_irq_2_iommu(irq); | ||
322 | if (!irq_iommu) { | ||
323 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
324 | return -1; | 192 | return -1; |
325 | } | 193 | |
194 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
326 | 195 | ||
327 | iommu = irq_iommu->iommu; | 196 | iommu = irq_iommu->iommu; |
328 | 197 | ||
@@ -339,31 +208,6 @@ int modify_irte(int irq, struct irte *irte_modified) | |||
339 | return rc; | 208 | return rc; |
340 | } | 209 | } |
341 | 210 | ||
342 | int flush_irte(int irq) | ||
343 | { | ||
344 | int rc; | ||
345 | int index; | ||
346 | struct intel_iommu *iommu; | ||
347 | struct irq_2_iommu *irq_iommu; | ||
348 | unsigned long flags; | ||
349 | |||
350 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
351 | irq_iommu = valid_irq_2_iommu(irq); | ||
352 | if (!irq_iommu) { | ||
353 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
354 | return -1; | ||
355 | } | ||
356 | |||
357 | iommu = irq_iommu->iommu; | ||
358 | |||
359 | index = irq_iommu->irte_index + irq_iommu->sub_handle; | ||
360 | |||
361 | rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); | ||
362 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
363 | |||
364 | return rc; | ||
365 | } | ||
366 | |||
367 | struct intel_iommu *map_hpet_to_ir(u8 hpet_id) | 211 | struct intel_iommu *map_hpet_to_ir(u8 hpet_id) |
368 | { | 212 | { |
369 | int i; | 213 | int i; |
@@ -420,16 +264,14 @@ static int clear_entries(struct irq_2_iommu *irq_iommu) | |||
420 | 264 | ||
421 | int free_irte(int irq) | 265 | int free_irte(int irq) |
422 | { | 266 | { |
423 | int rc = 0; | 267 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
424 | struct irq_2_iommu *irq_iommu; | ||
425 | unsigned long flags; | 268 | unsigned long flags; |
269 | int rc; | ||
426 | 270 | ||
427 | spin_lock_irqsave(&irq_2_ir_lock, flags); | 271 | if (!irq_iommu) |
428 | irq_iommu = valid_irq_2_iommu(irq); | ||
429 | if (!irq_iommu) { | ||
430 | spin_unlock_irqrestore(&irq_2_ir_lock, flags); | ||
431 | return -1; | 272 | return -1; |
432 | } | 273 | |
274 | spin_lock_irqsave(&irq_2_ir_lock, flags); | ||
433 | 275 | ||
434 | rc = clear_entries(irq_iommu); | 276 | rc = clear_entries(irq_iommu); |
435 | 277 | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 69b7be33b3a2..5fcf5aec680f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -170,33 +170,31 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag) | |||
170 | desc->masked = __msix_mask_irq(desc, flag); | 170 | desc->masked = __msix_mask_irq(desc, flag); |
171 | } | 171 | } |
172 | 172 | ||
173 | static void msi_set_mask_bit(unsigned irq, u32 flag) | 173 | static void msi_set_mask_bit(struct irq_data *data, u32 flag) |
174 | { | 174 | { |
175 | struct msi_desc *desc = get_irq_msi(irq); | 175 | struct msi_desc *desc = irq_data_get_msi(data); |
176 | 176 | ||
177 | if (desc->msi_attrib.is_msix) { | 177 | if (desc->msi_attrib.is_msix) { |
178 | msix_mask_irq(desc, flag); | 178 | msix_mask_irq(desc, flag); |
179 | readl(desc->mask_base); /* Flush write to device */ | 179 | readl(desc->mask_base); /* Flush write to device */ |
180 | } else { | 180 | } else { |
181 | unsigned offset = irq - desc->dev->irq; | 181 | unsigned offset = data->irq - desc->dev->irq; |
182 | msi_mask_irq(desc, 1 << offset, flag << offset); | 182 | msi_mask_irq(desc, 1 << offset, flag << offset); |
183 | } | 183 | } |
184 | } | 184 | } |
185 | 185 | ||
186 | void mask_msi_irq(unsigned int irq) | 186 | void mask_msi_irq(struct irq_data *data) |
187 | { | 187 | { |
188 | msi_set_mask_bit(irq, 1); | 188 | msi_set_mask_bit(data, 1); |
189 | } | 189 | } |
190 | 190 | ||
191 | void unmask_msi_irq(unsigned int irq) | 191 | void unmask_msi_irq(struct irq_data *data) |
192 | { | 192 | { |
193 | msi_set_mask_bit(irq, 0); | 193 | msi_set_mask_bit(data, 0); |
194 | } | 194 | } |
195 | 195 | ||
196 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 196 | void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
197 | { | 197 | { |
198 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
199 | |||
200 | BUG_ON(entry->dev->current_state != PCI_D0); | 198 | BUG_ON(entry->dev->current_state != PCI_D0); |
201 | 199 | ||
202 | if (entry->msi_attrib.is_msix) { | 200 | if (entry->msi_attrib.is_msix) { |
@@ -227,15 +225,13 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
227 | 225 | ||
228 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) | 226 | void read_msi_msg(unsigned int irq, struct msi_msg *msg) |
229 | { | 227 | { |
230 | struct irq_desc *desc = irq_to_desc(irq); | 228 | struct msi_desc *entry = get_irq_msi(irq); |
231 | 229 | ||
232 | read_msi_msg_desc(desc, msg); | 230 | __read_msi_msg(entry, msg); |
233 | } | 231 | } |
234 | 232 | ||
235 | void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 233 | void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
236 | { | 234 | { |
237 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
238 | |||
239 | /* Assert that the cache is valid, assuming that | 235 | /* Assert that the cache is valid, assuming that |
240 | * valid messages are not all-zeroes. */ | 236 | * valid messages are not all-zeroes. */ |
241 | BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | | 237 | BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo | |
@@ -246,15 +242,13 @@ void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
246 | 242 | ||
247 | void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) | 243 | void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg) |
248 | { | 244 | { |
249 | struct irq_desc *desc = irq_to_desc(irq); | 245 | struct msi_desc *entry = get_irq_msi(irq); |
250 | 246 | ||
251 | get_cached_msi_msg_desc(desc, msg); | 247 | __get_cached_msi_msg(entry, msg); |
252 | } | 248 | } |
253 | 249 | ||
254 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 250 | void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) |
255 | { | 251 | { |
256 | struct msi_desc *entry = get_irq_desc_msi(desc); | ||
257 | |||
258 | if (entry->dev->current_state != PCI_D0) { | 252 | if (entry->dev->current_state != PCI_D0) { |
259 | /* Don't touch the hardware now */ | 253 | /* Don't touch the hardware now */ |
260 | } else if (entry->msi_attrib.is_msix) { | 254 | } else if (entry->msi_attrib.is_msix) { |
@@ -292,9 +286,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
292 | 286 | ||
293 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) | 287 | void write_msi_msg(unsigned int irq, struct msi_msg *msg) |
294 | { | 288 | { |
295 | struct irq_desc *desc = irq_to_desc(irq); | 289 | struct msi_desc *entry = get_irq_msi(irq); |
296 | 290 | ||
297 | write_msi_msg_desc(desc, msg); | 291 | __write_msi_msg(entry, msg); |
298 | } | 292 | } |
299 | 293 | ||
300 | static void free_msi_irqs(struct pci_dev *dev) | 294 | static void free_msi_irqs(struct pci_dev *dev) |
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 88c4c4098789..95dd7c62741f 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c | |||
@@ -441,14 +441,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, | |||
441 | 441 | ||
442 | 442 | ||
443 | out_err: | 443 | out_err: |
444 | flush_scheduled_work(); | ||
445 | ops->hw_shutdown(skt); | 444 | ops->hw_shutdown(skt); |
446 | while (i-- > 0) { | 445 | while (i-- > 0) { |
447 | skt = PCMCIA_SOCKET(i); | 446 | skt = PCMCIA_SOCKET(i); |
448 | 447 | ||
449 | del_timer_sync(&skt->poll_timer); | 448 | del_timer_sync(&skt->poll_timer); |
450 | pcmcia_unregister_socket(&skt->socket); | 449 | pcmcia_unregister_socket(&skt->socket); |
451 | flush_scheduled_work(); | ||
452 | if (i == 0) { | 450 | if (i == 0) { |
453 | iounmap(skt->virt_io + (u32)mips_io_port_base); | 451 | iounmap(skt->virt_io + (u32)mips_io_port_base); |
454 | skt->virt_io = NULL; | 452 | skt->virt_io = NULL; |
@@ -480,7 +478,6 @@ int au1x00_drv_pcmcia_remove(struct platform_device *dev) | |||
480 | 478 | ||
481 | del_timer_sync(&skt->poll_timer); | 479 | del_timer_sync(&skt->poll_timer); |
482 | pcmcia_unregister_socket(&skt->socket); | 480 | pcmcia_unregister_socket(&skt->socket); |
483 | flush_scheduled_work(); | ||
484 | skt->ops->hw_shutdown(skt); | 481 | skt->ops->hw_shutdown(skt); |
485 | au1x00_pcmcia_config_skt(skt, &dead_socket); | 482 | au1x00_pcmcia_config_skt(skt, &dead_socket); |
486 | iounmap(skt->virt_io + (u32)mips_io_port_base); | 483 | iounmap(skt->virt_io + (u32)mips_io_port_base); |
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index 67530cefcf3c..5c36bda2963b 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | /* include the world */ | 24 | /* include the world */ |
25 | 25 | ||
26 | #include <pcmcia/cs.h> | ||
27 | #include <pcmcia/ss.h> | 26 | #include <pcmcia/ss.h> |
28 | #include <pcmcia/cistpl.h> | 27 | #include <pcmcia/cistpl.h> |
29 | #include "cs_internal.h" | 28 | #include "cs_internal.h" |
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index 807f2d75dad3..b2396647a165 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | 33 | ||
34 | #include <pcmcia/cs.h> | ||
35 | #include <pcmcia/ss.h> | 34 | #include <pcmcia/ss.h> |
36 | #include <pcmcia/cistpl.h> | 35 | #include <pcmcia/cistpl.h> |
37 | 36 | ||
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 91414a0ddc44..884a984216fe 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
29 | 29 | ||
30 | #include <pcmcia/ss.h> | 30 | #include <pcmcia/ss.h> |
31 | #include <pcmcia/cs.h> | ||
32 | #include <pcmcia/cisreg.h> | 31 | #include <pcmcia/cisreg.h> |
33 | #include <pcmcia/cistpl.h> | 32 | #include <pcmcia/cistpl.h> |
34 | #include "cs_internal.h" | 33 | #include "cs_internal.h" |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 2ec8ac97445c..d9ea192c4001 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
34 | 34 | ||
35 | #include <pcmcia/ss.h> | 35 | #include <pcmcia/ss.h> |
36 | #include <pcmcia/cs.h> | ||
37 | #include <pcmcia/cistpl.h> | 36 | #include <pcmcia/cistpl.h> |
38 | #include <pcmcia/cisreg.h> | 37 | #include <pcmcia/cisreg.h> |
39 | #include <pcmcia/ds.h> | 38 | #include <pcmcia/ds.h> |
@@ -845,7 +844,7 @@ static int pcmcia_socket_dev_resume_noirq(struct device *dev) | |||
845 | return __pcmcia_pm_op(dev, socket_early_resume); | 844 | return __pcmcia_pm_op(dev, socket_early_resume); |
846 | } | 845 | } |
847 | 846 | ||
848 | static int pcmcia_socket_dev_resume(struct device *dev) | 847 | static int __used pcmcia_socket_dev_resume(struct device *dev) |
849 | { | 848 | { |
850 | return __pcmcia_pm_op(dev, socket_late_resume); | 849 | return __pcmcia_pm_op(dev, socket_late_resume); |
851 | } | 850 | } |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index da055dc14d98..7f1953f78b12 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -33,18 +33,9 @@ | |||
33 | typedef struct config_t { | 33 | typedef struct config_t { |
34 | struct kref ref; | 34 | struct kref ref; |
35 | unsigned int state; | 35 | unsigned int state; |
36 | unsigned int Attributes; | ||
37 | unsigned int IntType; | ||
38 | unsigned int ConfigBase; | ||
39 | unsigned char Status, Pin, Copy, Option, ExtStatus; | ||
40 | unsigned int CardValues; | ||
41 | 36 | ||
42 | struct resource io[MAX_IO_WIN]; /* io ports */ | 37 | struct resource io[MAX_IO_WIN]; /* io ports */ |
43 | struct resource mem[MAX_WIN]; /* mem areas */ | 38 | struct resource mem[MAX_WIN]; /* mem areas */ |
44 | |||
45 | struct { | ||
46 | u_int Attributes; | ||
47 | } irq; | ||
48 | } config_t; | 39 | } config_t; |
49 | 40 | ||
50 | 41 | ||
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 55570d9e1e4c..100c4412457d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | 28 | ||
29 | #include <pcmcia/cs.h> | ||
30 | #include <pcmcia/cistpl.h> | 29 | #include <pcmcia/cistpl.h> |
31 | #include <pcmcia/ds.h> | 30 | #include <pcmcia/ds.h> |
32 | #include <pcmcia/ss.h> | 31 | #include <pcmcia/ss.h> |
@@ -52,7 +51,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) | |||
52 | 51 | ||
53 | if (!p_drv->probe || !p_drv->remove) | 52 | if (!p_drv->probe || !p_drv->remove) |
54 | printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " | 53 | printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " |
55 | "function\n", p_drv->drv.name); | 54 | "function\n", p_drv->name); |
56 | 55 | ||
57 | while (did && did->match_flags) { | 56 | while (did && did->match_flags) { |
58 | for (i = 0; i < 4; i++) { | 57 | for (i = 0; i < 4; i++) { |
@@ -65,7 +64,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) | |||
65 | 64 | ||
66 | printk(KERN_DEBUG "pcmcia: %s: invalid hash for " | 65 | printk(KERN_DEBUG "pcmcia: %s: invalid hash for " |
67 | "product string \"%s\": is 0x%x, should " | 66 | "product string \"%s\": is 0x%x, should " |
68 | "be 0x%x\n", p_drv->drv.name, did->prod_id[i], | 67 | "be 0x%x\n", p_drv->name, did->prod_id[i], |
69 | did->prod_id_hash[i], hash); | 68 | did->prod_id_hash[i], hash); |
70 | printk(KERN_DEBUG "pcmcia: see " | 69 | printk(KERN_DEBUG "pcmcia: see " |
71 | "Documentation/pcmcia/devicetable.txt for " | 70 | "Documentation/pcmcia/devicetable.txt for " |
@@ -180,10 +179,11 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) | |||
180 | /* initialize common fields */ | 179 | /* initialize common fields */ |
181 | driver->drv.bus = &pcmcia_bus_type; | 180 | driver->drv.bus = &pcmcia_bus_type; |
182 | driver->drv.owner = driver->owner; | 181 | driver->drv.owner = driver->owner; |
182 | driver->drv.name = driver->name; | ||
183 | mutex_init(&driver->dynids.lock); | 183 | mutex_init(&driver->dynids.lock); |
184 | INIT_LIST_HEAD(&driver->dynids.list); | 184 | INIT_LIST_HEAD(&driver->dynids.list); |
185 | 185 | ||
186 | pr_debug("registering driver %s\n", driver->drv.name); | 186 | pr_debug("registering driver %s\n", driver->name); |
187 | 187 | ||
188 | error = driver_register(&driver->drv); | 188 | error = driver_register(&driver->drv); |
189 | if (error < 0) | 189 | if (error < 0) |
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); | |||
203 | */ | 203 | */ |
204 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) | 204 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) |
205 | { | 205 | { |
206 | pr_debug("unregistering driver %s\n", driver->drv.name); | 206 | pr_debug("unregistering driver %s\n", driver->name); |
207 | driver_unregister(&driver->drv); | 207 | driver_unregister(&driver->drv); |
208 | pcmcia_free_dynids(driver); | 208 | pcmcia_free_dynids(driver); |
209 | } | 209 | } |
@@ -264,7 +264,7 @@ static int pcmcia_device_probe(struct device *dev) | |||
264 | p_drv = to_pcmcia_drv(dev->driver); | 264 | p_drv = to_pcmcia_drv(dev->driver); |
265 | s = p_dev->socket; | 265 | s = p_dev->socket; |
266 | 266 | ||
267 | dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name); | 267 | dev_dbg(dev, "trying to bind to %s\n", p_drv->name); |
268 | 268 | ||
269 | if ((!p_drv->probe) || (!p_dev->function_config) || | 269 | if ((!p_drv->probe) || (!p_dev->function_config) || |
270 | (!try_module_get(p_drv->owner))) { | 270 | (!try_module_get(p_drv->owner))) { |
@@ -276,21 +276,28 @@ static int pcmcia_device_probe(struct device *dev) | |||
276 | ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG, | 276 | ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG, |
277 | &cis_config); | 277 | &cis_config); |
278 | if (!ret) { | 278 | if (!ret) { |
279 | p_dev->conf.ConfigBase = cis_config.base; | 279 | p_dev->config_base = cis_config.base; |
280 | p_dev->conf.Present = cis_config.rmask[0]; | 280 | p_dev->config_regs = cis_config.rmask[0]; |
281 | dev_dbg(dev, "base %x, regs %x", p_dev->config_base, | ||
282 | p_dev->config_regs); | ||
281 | } else { | 283 | } else { |
282 | dev_printk(KERN_INFO, dev, | 284 | dev_printk(KERN_INFO, dev, |
283 | "pcmcia: could not parse base and rmask0 of CIS\n"); | 285 | "pcmcia: could not parse base and rmask0 of CIS\n"); |
284 | p_dev->conf.ConfigBase = 0; | 286 | p_dev->config_base = 0; |
285 | p_dev->conf.Present = 0; | 287 | p_dev->config_regs = 0; |
286 | } | 288 | } |
287 | 289 | ||
288 | ret = p_drv->probe(p_dev); | 290 | ret = p_drv->probe(p_dev); |
289 | if (ret) { | 291 | if (ret) { |
290 | dev_dbg(dev, "binding to %s failed with %d\n", | 292 | dev_dbg(dev, "binding to %s failed with %d\n", |
291 | p_drv->drv.name, ret); | 293 | p_drv->name, ret); |
292 | goto put_module; | 294 | goto put_module; |
293 | } | 295 | } |
296 | dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name, | ||
297 | p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq); | ||
298 | dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR", | ||
299 | p_dev->resource[0], p_dev->resource[1], p_dev->resource[2], | ||
300 | p_dev->resource[3], p_dev->resource[4]); | ||
294 | 301 | ||
295 | mutex_lock(&s->ops_mutex); | 302 | mutex_lock(&s->ops_mutex); |
296 | if ((s->pcmcia_pfc) && | 303 | if ((s->pcmcia_pfc) && |
@@ -374,13 +381,13 @@ static int pcmcia_device_remove(struct device *dev) | |||
374 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) | 381 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) |
375 | dev_printk(KERN_INFO, dev, | 382 | dev_printk(KERN_INFO, dev, |
376 | "pcmcia: driver %s did not release config properly\n", | 383 | "pcmcia: driver %s did not release config properly\n", |
377 | p_drv->drv.name); | 384 | p_drv->name); |
378 | 385 | ||
379 | for (i = 0; i < MAX_WIN; i++) | 386 | for (i = 0; i < MAX_WIN; i++) |
380 | if (p_dev->_win & CLIENT_WIN_REQ(i)) | 387 | if (p_dev->_win & CLIENT_WIN_REQ(i)) |
381 | dev_printk(KERN_INFO, dev, | 388 | dev_printk(KERN_INFO, dev, |
382 | "pcmcia: driver %s did not release window properly\n", | 389 | "pcmcia: driver %s did not release window properly\n", |
383 | p_drv->drv.name); | 390 | p_drv->name); |
384 | 391 | ||
385 | /* references from pcmcia_probe_device */ | 392 | /* references from pcmcia_probe_device */ |
386 | pcmcia_put_dev(p_dev); | 393 | pcmcia_put_dev(p_dev); |
@@ -1136,7 +1143,7 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
1136 | dev_printk(KERN_ERR, dev, | 1143 | dev_printk(KERN_ERR, dev, |
1137 | "pcmcia: device %s (driver %s) did " | 1144 | "pcmcia: device %s (driver %s) did " |
1138 | "not want to go to sleep (%d)\n", | 1145 | "not want to go to sleep (%d)\n", |
1139 | p_dev->devname, p_drv->drv.name, ret); | 1146 | p_dev->devname, p_drv->name, ret); |
1140 | mutex_lock(&p_dev->socket->ops_mutex); | 1147 | mutex_lock(&p_dev->socket->ops_mutex); |
1141 | p_dev->suspended = 0; | 1148 | p_dev->suspended = 0; |
1142 | mutex_unlock(&p_dev->socket->ops_mutex); | 1149 | mutex_unlock(&p_dev->socket->ops_mutex); |
@@ -1178,7 +1185,7 @@ static int pcmcia_dev_resume(struct device *dev) | |||
1178 | 1185 | ||
1179 | if (p_dev->device_no == p_dev->func) { | 1186 | if (p_dev->device_no == p_dev->func) { |
1180 | dev_dbg(dev, "requesting configuration\n"); | 1187 | dev_dbg(dev, "requesting configuration\n"); |
1181 | ret = pcmcia_request_configuration(p_dev, &p_dev->conf); | 1188 | ret = pcmcia_enable_device(p_dev); |
1182 | if (ret) | 1189 | if (ret) |
1183 | goto out; | 1190 | goto out; |
1184 | } | 1191 | } |
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 05d0879ce935..fc7906eaf228 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | 17 | ||
18 | #include <pcmcia/ss.h> | 18 | #include <pcmcia/ss.h> |
19 | #include <pcmcia/cs.h> | ||
20 | 19 | ||
21 | #include <asm/system.h> | 20 | #include <asm/system.h> |
22 | #include <asm/io.h> | 21 | #include <asm/io.h> |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 61746bd598b3..72a033a2acdb 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <asm/system.h> | 51 | #include <asm/system.h> |
52 | 52 | ||
53 | #include <pcmcia/ss.h> | 53 | #include <pcmcia/ss.h> |
54 | #include <pcmcia/cs.h> | ||
55 | 54 | ||
56 | #include <linux/isapnp.h> | 55 | #include <linux/isapnp.h> |
57 | 56 | ||
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 24de49925863..2adb0106a039 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/system.h> | 27 | #include <asm/system.h> |
28 | 28 | ||
29 | #include <pcmcia/ss.h> | 29 | #include <pcmcia/ss.h> |
30 | #include <pcmcia/cs.h> | ||
31 | 30 | ||
32 | #undef MAX_IO_WIN /* FIXME */ | 31 | #undef MAX_IO_WIN /* FIXME */ |
33 | #define MAX_IO_WIN 1 | 32 | #define MAX_IO_WIN 1 |
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 8e4723844ad3..1511ff71c87b 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/addrspace.h> | 28 | #include <asm/addrspace.h> |
29 | 29 | ||
30 | #include <pcmcia/ss.h> | 30 | #include <pcmcia/ss.h> |
31 | #include <pcmcia/cs.h> | ||
32 | 31 | ||
33 | /* XXX: should be moved into asm/irq.h */ | 32 | /* XXX: should be moved into asm/irq.h */ |
34 | #define PCC0_IRQ 24 | 33 | #define PCC0_IRQ 24 |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index f0ecad99ce81..99d4f23cb435 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <asm/irq.h> | 59 | #include <asm/irq.h> |
60 | #include <asm/fs_pd.h> | 60 | #include <asm/fs_pd.h> |
61 | 61 | ||
62 | #include <pcmcia/cs.h> | ||
63 | #include <pcmcia/ss.h> | 62 | #include <pcmcia/ss.h> |
64 | 63 | ||
65 | #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args) | 64 | #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args) |
diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index e74bebac2695..5096e92c7a4c 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h | |||
@@ -153,14 +153,14 @@ static int o2micro_override(struct yenta_socket *socket) | |||
153 | 153 | ||
154 | if (use_speedup) { | 154 | if (use_speedup) { |
155 | dev_info(&socket->dev->dev, | 155 | dev_info(&socket->dev->dev, |
156 | "O2: enabling read prefetch/write burst\n"); | 156 | "O2: enabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=off'\n"); |
157 | config_writeb(socket, O2_RESERVED1, | 157 | config_writeb(socket, O2_RESERVED1, |
158 | a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); | 158 | a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); |
159 | config_writeb(socket, O2_RESERVED2, | 159 | config_writeb(socket, O2_RESERVED2, |
160 | b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); | 160 | b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST); |
161 | } else { | 161 | } else { |
162 | dev_info(&socket->dev->dev, | 162 | dev_info(&socket->dev->dev, |
163 | "O2: disabling read prefetch/write burst\n"); | 163 | "O2: disabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=on'\n"); |
164 | config_writeb(socket, O2_RESERVED1, | 164 | config_writeb(socket, O2_RESERVED1, |
165 | a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST)); | 165 | a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST)); |
166 | config_writeb(socket, O2_RESERVED2, | 166 | config_writeb(socket, O2_RESERVED2, |
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c index 0ac54da15885..e2c92415b892 100644 --- a/drivers/pcmcia/pcmcia_cis.c +++ b/drivers/pcmcia/pcmcia_cis.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
7 | * | 7 | * |
8 | * Copyright (C) 1999 David A. Hinds | 8 | * Copyright (C) 1999 David A. Hinds |
9 | * Copyright (C) 2004-2009 Dominik Brodowski | 9 | * Copyright (C) 2004-2010 Dominik Brodowski |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -22,7 +22,6 @@ | |||
22 | #include <pcmcia/cisreg.h> | 22 | #include <pcmcia/cisreg.h> |
23 | #include <pcmcia/cistpl.h> | 23 | #include <pcmcia/cistpl.h> |
24 | #include <pcmcia/ss.h> | 24 | #include <pcmcia/ss.h> |
25 | #include <pcmcia/cs.h> | ||
26 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
27 | #include "cs_internal.h" | 26 | #include "cs_internal.h" |
28 | 27 | ||
@@ -126,14 +125,24 @@ next_entry: | |||
126 | return ret; | 125 | return ret; |
127 | } | 126 | } |
128 | 127 | ||
128 | |||
129 | /** | ||
130 | * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter | ||
131 | */ | ||
132 | static int pcmcia_io_cfg_data_width(unsigned int flags) | ||
133 | { | ||
134 | if (!(flags & CISTPL_IO_8BIT)) | ||
135 | return IO_DATA_PATH_WIDTH_16; | ||
136 | if (!(flags & CISTPL_IO_16BIT)) | ||
137 | return IO_DATA_PATH_WIDTH_8; | ||
138 | return IO_DATA_PATH_WIDTH_AUTO; | ||
139 | } | ||
140 | |||
141 | |||
129 | struct pcmcia_cfg_mem { | 142 | struct pcmcia_cfg_mem { |
130 | struct pcmcia_device *p_dev; | 143 | struct pcmcia_device *p_dev; |
144 | int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data); | ||
131 | void *priv_data; | 145 | void *priv_data; |
132 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
133 | cistpl_cftable_entry_t *cfg, | ||
134 | cistpl_cftable_entry_t *dflt, | ||
135 | unsigned int vcc, | ||
136 | void *priv_data); | ||
137 | cisparse_t parse; | 146 | cisparse_t parse; |
138 | cistpl_cftable_entry_t dflt; | 147 | cistpl_cftable_entry_t dflt; |
139 | }; | 148 | }; |
@@ -147,25 +156,102 @@ struct pcmcia_cfg_mem { | |||
147 | */ | 156 | */ |
148 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | 157 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) |
149 | { | 158 | { |
150 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
151 | struct pcmcia_cfg_mem *cfg_mem = priv; | 159 | struct pcmcia_cfg_mem *cfg_mem = priv; |
160 | struct pcmcia_device *p_dev = cfg_mem->p_dev; | ||
161 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
162 | cistpl_cftable_entry_t *dflt = &cfg_mem->dflt; | ||
163 | unsigned int flags = p_dev->config_flags; | ||
164 | unsigned int vcc = p_dev->socket->socket.Vcc; | ||
165 | |||
166 | dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n", | ||
167 | cfg->index, flags); | ||
152 | 168 | ||
153 | /* default values */ | 169 | /* default values */ |
154 | cfg_mem->p_dev->conf.ConfigIndex = cfg->index; | 170 | cfg_mem->p_dev->config_index = cfg->index; |
155 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 171 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
156 | cfg_mem->dflt = *cfg; | 172 | cfg_mem->dflt = *cfg; |
157 | 173 | ||
158 | return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, | 174 | /* check for matching Vcc? */ |
159 | cfg_mem->p_dev->socket->socket.Vcc, | 175 | if (flags & CONF_AUTO_CHECK_VCC) { |
160 | cfg_mem->priv_data); | 176 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { |
177 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
178 | return -ENODEV; | ||
179 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
180 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) | ||
181 | return -ENODEV; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* set Vpp? */ | ||
186 | if (flags & CONF_AUTO_SET_VPP) { | ||
187 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
188 | p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
189 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
190 | p_dev->vpp = | ||
191 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
192 | } | ||
193 | |||
194 | /* enable audio? */ | ||
195 | if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO)) | ||
196 | p_dev->config_flags |= CONF_ENABLE_SPKR; | ||
197 | |||
198 | |||
199 | /* IO window settings? */ | ||
200 | if (flags & CONF_AUTO_SET_IO) { | ||
201 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
202 | int i = 0; | ||
203 | |||
204 | p_dev->resource[0]->start = p_dev->resource[0]->end = 0; | ||
205 | p_dev->resource[1]->start = p_dev->resource[1]->end = 0; | ||
206 | if (io->nwin == 0) | ||
207 | return -ENODEV; | ||
208 | |||
209 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
210 | p_dev->resource[0]->flags |= | ||
211 | pcmcia_io_cfg_data_width(io->flags); | ||
212 | if (io->nwin > 1) { | ||
213 | /* For multifunction cards, by convention, we | ||
214 | * configure the network function with window 0, | ||
215 | * and serial with window 1 */ | ||
216 | i = (io->win[1].len > io->win[0].len); | ||
217 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
218 | p_dev->resource[1]->start = io->win[1-i].base; | ||
219 | p_dev->resource[1]->end = io->win[1-i].len; | ||
220 | } | ||
221 | p_dev->resource[0]->start = io->win[i].base; | ||
222 | p_dev->resource[0]->end = io->win[i].len; | ||
223 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
224 | } | ||
225 | |||
226 | /* MEM window settings? */ | ||
227 | if (flags & CONF_AUTO_SET_IOMEM) { | ||
228 | /* so far, we only set one memory window */ | ||
229 | cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; | ||
230 | |||
231 | p_dev->resource[2]->start = p_dev->resource[2]->end = 0; | ||
232 | if (mem->nwin == 0) | ||
233 | return -ENODEV; | ||
234 | |||
235 | p_dev->resource[2]->start = mem->win[0].host_addr; | ||
236 | p_dev->resource[2]->end = mem->win[0].len; | ||
237 | if (p_dev->resource[2]->end < 0x1000) | ||
238 | p_dev->resource[2]->end = 0x1000; | ||
239 | p_dev->card_addr = mem->win[0].card_addr; | ||
240 | } | ||
241 | |||
242 | dev_dbg(&p_dev->dev, | ||
243 | "checking configuration %x: %pr %pr %pr (%d lines)\n", | ||
244 | p_dev->config_index, p_dev->resource[0], p_dev->resource[1], | ||
245 | p_dev->resource[2], p_dev->io_lines); | ||
246 | |||
247 | return cfg_mem->conf_check(p_dev, cfg_mem->priv_data); | ||
161 | } | 248 | } |
162 | 249 | ||
163 | /** | 250 | /** |
164 | * pcmcia_loop_config() - loop over configuration options | 251 | * pcmcia_loop_config() - loop over configuration options |
165 | * @p_dev: the struct pcmcia_device which we need to loop for. | 252 | * @p_dev: the struct pcmcia_device which we need to loop for. |
166 | * @conf_check: function to call for each configuration option. | 253 | * @conf_check: function to call for each configuration option. |
167 | * It gets passed the struct pcmcia_device, the CIS data | 254 | * It gets passed the struct pcmcia_device and private data |
168 | * describing the configuration option, and private data | ||
169 | * being passed to pcmcia_loop_config() | 255 | * being passed to pcmcia_loop_config() |
170 | * @priv_data: private data to be passed to the conf_check function. | 256 | * @priv_data: private data to be passed to the conf_check function. |
171 | * | 257 | * |
@@ -175,9 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | |||
175 | */ | 261 | */ |
176 | int pcmcia_loop_config(struct pcmcia_device *p_dev, | 262 | int pcmcia_loop_config(struct pcmcia_device *p_dev, |
177 | int (*conf_check) (struct pcmcia_device *p_dev, | 263 | int (*conf_check) (struct pcmcia_device *p_dev, |
178 | cistpl_cftable_entry_t *cfg, | ||
179 | cistpl_cftable_entry_t *dflt, | ||
180 | unsigned int vcc, | ||
181 | void *priv_data), | 264 | void *priv_data), |
182 | void *priv_data) | 265 | void *priv_data) |
183 | { | 266 | { |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 9ba4dade69a4..a9af0d784426 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
7 | * | 7 | * |
8 | * Copyright (C) 1999 David A. Hinds | 8 | * Copyright (C) 1999 David A. Hinds |
9 | * Copyright (C) 2004-2005 Dominik Brodowski | 9 | * Copyright (C) 2004-2010 Dominik Brodowski |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -26,7 +26,6 @@ | |||
26 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | 27 | ||
28 | #include <pcmcia/ss.h> | 28 | #include <pcmcia/ss.h> |
29 | #include <pcmcia/cs.h> | ||
30 | #include <pcmcia/cistpl.h> | 29 | #include <pcmcia/cistpl.h> |
31 | #include <pcmcia/cisreg.h> | 30 | #include <pcmcia/cisreg.h> |
32 | #include <pcmcia/ds.h> | 31 | #include <pcmcia/ds.h> |
@@ -56,6 +55,12 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | |||
56 | } | 55 | } |
57 | 56 | ||
58 | 57 | ||
58 | /** | ||
59 | * release_io_space() - release IO ports allocated with alloc_io_space() | ||
60 | * @s: pcmcia socket | ||
61 | * @res: resource to release | ||
62 | * | ||
63 | */ | ||
59 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | 64 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) |
60 | { | 65 | { |
61 | resource_size_t num = resource_size(res); | 66 | resource_size_t num = resource_size(res); |
@@ -81,9 +86,14 @@ static void release_io_space(struct pcmcia_socket *s, struct resource *res) | |||
81 | } | 86 | } |
82 | } | 87 | } |
83 | } | 88 | } |
84 | } /* release_io_space */ | 89 | } |
90 | |||
85 | 91 | ||
86 | /** alloc_io_space | 92 | /** |
93 | * alloc_io_space() - allocate IO ports for use by a PCMCIA device | ||
94 | * @s: pcmcia socket | ||
95 | * @res: resource to allocate (begin: begin, end: size) | ||
96 | * @lines: number of IO lines decoded by the PCMCIA card | ||
87 | * | 97 | * |
88 | * Special stuff for managing IO windows, because they are scarce | 98 | * Special stuff for managing IO windows, because they are scarce |
89 | */ | 99 | */ |
@@ -135,7 +145,7 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res, | |||
135 | } | 145 | } |
136 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); | 146 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); |
137 | return ret; | 147 | return ret; |
138 | } /* alloc_io_space */ | 148 | } |
139 | 149 | ||
140 | 150 | ||
141 | /** | 151 | /** |
@@ -168,14 +178,14 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, | |||
168 | return -EACCES; | 178 | return -EACCES; |
169 | } | 179 | } |
170 | 180 | ||
171 | addr = (c->ConfigBase + where) >> 1; | 181 | addr = (p_dev->config_base + where) >> 1; |
172 | 182 | ||
173 | ret = accessf(s, 1, addr, 1, val); | 183 | ret = accessf(s, 1, addr, 1, val); |
174 | 184 | ||
175 | mutex_unlock(&s->ops_mutex); | 185 | mutex_unlock(&s->ops_mutex); |
176 | 186 | ||
177 | return ret; | 187 | return ret; |
178 | } /* pcmcia_access_config */ | 188 | } |
179 | 189 | ||
180 | 190 | ||
181 | /** | 191 | /** |
@@ -204,11 +214,20 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val) | |||
204 | EXPORT_SYMBOL(pcmcia_write_config_byte); | 214 | EXPORT_SYMBOL(pcmcia_write_config_byte); |
205 | 215 | ||
206 | 216 | ||
207 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | 217 | /** |
218 | * pcmcia_map_mem_page() - modify iomem window to point to a different offset | ||
219 | * @p_dev: pcmcia device | ||
220 | * @res: iomem resource already enabled by pcmcia_request_window() | ||
221 | * @offset: card_offset to map | ||
222 | * | ||
223 | * pcmcia_map_mem_page() modifies what can be read and written by accessing | ||
224 | * an iomem range previously enabled by pcmcia_request_window(), by setting | ||
225 | * the card_offset value to @offset. | ||
226 | */ | ||
227 | int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res, | ||
208 | unsigned int offset) | 228 | unsigned int offset) |
209 | { | 229 | { |
210 | struct pcmcia_socket *s = p_dev->socket; | 230 | struct pcmcia_socket *s = p_dev->socket; |
211 | struct resource *res = wh; | ||
212 | unsigned int w; | 231 | unsigned int w; |
213 | int ret; | 232 | int ret; |
214 | 233 | ||
@@ -223,98 +242,111 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
223 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); | 242 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); |
224 | mutex_unlock(&s->ops_mutex); | 243 | mutex_unlock(&s->ops_mutex); |
225 | return ret; | 244 | return ret; |
226 | } /* pcmcia_map_mem_page */ | 245 | } |
227 | EXPORT_SYMBOL(pcmcia_map_mem_page); | 246 | EXPORT_SYMBOL(pcmcia_map_mem_page); |
228 | 247 | ||
229 | 248 | ||
230 | /** pcmcia_modify_configuration | 249 | /** |
250 | * pcmcia_fixup_iowidth() - reduce io width to 8bit | ||
251 | * @p_dev: pcmcia device | ||
231 | * | 252 | * |
232 | * Modify a locked socket configuration | 253 | * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the |
254 | * IO width to 8bit after having called pcmcia_enable_device() | ||
255 | * previously. | ||
233 | */ | 256 | */ |
234 | int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | 257 | int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev) |
235 | modconf_t *mod) | ||
236 | { | 258 | { |
237 | struct pcmcia_socket *s; | 259 | struct pcmcia_socket *s = p_dev->socket; |
238 | config_t *c; | 260 | pccard_io_map io_off = { 0, 0, 0, 0, 1 }; |
239 | int ret; | 261 | pccard_io_map io_on; |
240 | 262 | int i, ret = 0; | |
241 | s = p_dev->socket; | ||
242 | 263 | ||
243 | mutex_lock(&s->ops_mutex); | 264 | mutex_lock(&s->ops_mutex); |
244 | c = p_dev->function_config; | ||
245 | 265 | ||
246 | if (!(s->state & SOCKET_PRESENT)) { | 266 | dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n"); |
247 | dev_dbg(&p_dev->dev, "No card present\n"); | 267 | |
248 | ret = -ENODEV; | 268 | if (!(s->state & SOCKET_PRESENT) || |
249 | goto unlock; | 269 | !(p_dev->function_config->state & CONFIG_LOCKED)) { |
250 | } | 270 | dev_dbg(&p_dev->dev, "No card? Config not locked?\n"); |
251 | if (!(c->state & CONFIG_LOCKED)) { | ||
252 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); | ||
253 | ret = -EACCES; | 271 | ret = -EACCES; |
254 | goto unlock; | 272 | goto unlock; |
255 | } | 273 | } |
256 | 274 | ||
257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { | 275 | io_on.speed = io_speed; |
258 | dev_dbg(&p_dev->dev, | 276 | for (i = 0; i < MAX_IO_WIN; i++) { |
259 | "changing Vcc or IRQ is not allowed at this time\n"); | 277 | if (!s->io[i].res) |
260 | ret = -EINVAL; | 278 | continue; |
261 | goto unlock; | 279 | io_off.map = i; |
262 | } | 280 | io_on.map = i; |
263 | 281 | ||
264 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | 282 | io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; |
265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 283 | io_on.start = s->io[i].res->start; |
266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 284 | io_on.stop = s->io[i].res->end; |
267 | if (mod->Vpp1 != mod->Vpp2) { | 285 | |
268 | dev_dbg(&p_dev->dev, | 286 | s->ops->set_io_map(s, &io_off); |
269 | "Vpp1 and Vpp2 must be the same\n"); | 287 | mdelay(40); |
270 | ret = -EINVAL; | 288 | s->ops->set_io_map(s, &io_on); |
271 | goto unlock; | ||
272 | } | ||
273 | s->socket.Vpp = mod->Vpp1; | ||
274 | if (s->ops->set_socket(s, &s->socket)) { | ||
275 | dev_printk(KERN_WARNING, &p_dev->dev, | ||
276 | "Unable to set VPP\n"); | ||
277 | ret = -EIO; | ||
278 | goto unlock; | ||
279 | } | ||
280 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | ||
281 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | ||
282 | dev_dbg(&p_dev->dev, | ||
283 | "changing Vcc is not allowed at this time\n"); | ||
284 | ret = -EINVAL; | ||
285 | goto unlock; | ||
286 | } | 289 | } |
290 | unlock: | ||
291 | mutex_unlock(&s->ops_mutex); | ||
292 | |||
293 | return ret; | ||
294 | } | ||
295 | EXPORT_SYMBOL(pcmcia_fixup_iowidth); | ||
296 | |||
297 | |||
298 | /** | ||
299 | * pcmcia_fixup_vpp() - set Vpp to a new voltage level | ||
300 | * @p_dev: pcmcia device | ||
301 | * @new_vpp: new Vpp voltage | ||
302 | * | ||
303 | * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to | ||
304 | * a new voltage level between calls to pcmcia_enable_device() | ||
305 | * and pcmcia_disable_device(). | ||
306 | */ | ||
307 | int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp) | ||
308 | { | ||
309 | struct pcmcia_socket *s = p_dev->socket; | ||
310 | int ret = 0; | ||
287 | 311 | ||
288 | if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { | 312 | mutex_lock(&s->ops_mutex); |
289 | pccard_io_map io_off = { 0, 0, 0, 0, 1 }; | ||
290 | pccard_io_map io_on; | ||
291 | int i; | ||
292 | 313 | ||
293 | io_on.speed = io_speed; | 314 | dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp); |
294 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
295 | if (!s->io[i].res) | ||
296 | continue; | ||
297 | io_off.map = i; | ||
298 | io_on.map = i; | ||
299 | 315 | ||
300 | io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; | 316 | if (!(s->state & SOCKET_PRESENT) || |
301 | io_on.start = s->io[i].res->start; | 317 | !(p_dev->function_config->state & CONFIG_LOCKED)) { |
302 | io_on.stop = s->io[i].res->end; | 318 | dev_dbg(&p_dev->dev, "No card? Config not locked?\n"); |
319 | ret = -EACCES; | ||
320 | goto unlock; | ||
321 | } | ||
303 | 322 | ||
304 | s->ops->set_io_map(s, &io_off); | 323 | s->socket.Vpp = new_vpp; |
305 | mdelay(40); | 324 | if (s->ops->set_socket(s, &s->socket)) { |
306 | s->ops->set_io_map(s, &io_on); | 325 | dev_warn(&p_dev->dev, "Unable to set VPP\n"); |
307 | } | 326 | ret = -EIO; |
327 | goto unlock; | ||
308 | } | 328 | } |
309 | ret = 0; | 329 | p_dev->vpp = new_vpp; |
330 | |||
310 | unlock: | 331 | unlock: |
311 | mutex_unlock(&s->ops_mutex); | 332 | mutex_unlock(&s->ops_mutex); |
312 | 333 | ||
313 | return ret; | 334 | return ret; |
314 | } /* modify_configuration */ | 335 | } |
315 | EXPORT_SYMBOL(pcmcia_modify_configuration); | 336 | EXPORT_SYMBOL(pcmcia_fixup_vpp); |
316 | 337 | ||
317 | 338 | ||
339 | /** | ||
340 | * pcmcia_release_configuration() - physically disable a PCMCIA device | ||
341 | * @p_dev: pcmcia device | ||
342 | * | ||
343 | * pcmcia_release_configuration() is the 1:1 counterpart to | ||
344 | * pcmcia_enable_device(): If a PCMCIA device is no longer used by any | ||
345 | * driver, the Vpp voltage is set to 0, IRQs will no longer be generated, | ||
346 | * and I/O ranges will be disabled. As pcmcia_release_io() and | ||
347 | * pcmcia_release_window() still need to be called, device drivers are | ||
348 | * expected to call pcmcia_disable_device() instead. | ||
349 | */ | ||
318 | int pcmcia_release_configuration(struct pcmcia_device *p_dev) | 350 | int pcmcia_release_configuration(struct pcmcia_device *p_dev) |
319 | { | 351 | { |
320 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 352 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
@@ -327,7 +359,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
327 | if (p_dev->_locked) { | 359 | if (p_dev->_locked) { |
328 | p_dev->_locked = 0; | 360 | p_dev->_locked = 0; |
329 | if (--(s->lock_count) == 0) { | 361 | if (--(s->lock_count) == 0) { |
330 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | 362 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ |
331 | s->socket.Vpp = 0; | 363 | s->socket.Vpp = 0; |
332 | s->socket.io_irq = 0; | 364 | s->socket.io_irq = 0; |
333 | s->ops->set_socket(s, &s->socket); | 365 | s->ops->set_socket(s, &s->socket); |
@@ -349,16 +381,18 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
349 | mutex_unlock(&s->ops_mutex); | 381 | mutex_unlock(&s->ops_mutex); |
350 | 382 | ||
351 | return 0; | 383 | return 0; |
352 | } /* pcmcia_release_configuration */ | 384 | } |
353 | 385 | ||
354 | 386 | ||
355 | /** pcmcia_release_io | 387 | /** |
388 | * pcmcia_release_io() - release I/O allocated by a PCMCIA device | ||
389 | * @p_dev: pcmcia device | ||
356 | * | 390 | * |
357 | * Release_io() releases the I/O ranges allocated by a client. This | 391 | * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA |
358 | * may be invoked some time after a card ejection has already dumped | 392 | * device. This may be invoked some time after a card ejection has |
359 | * the actual socket configuration, so if the client is "stale", we | 393 | * already dumped the actual socket configuration, so if the client is |
360 | * don't bother checking the port ranges against the current socket | 394 | * "stale", we don't bother checking the port ranges against the |
361 | * values. | 395 | * current socket values. |
362 | */ | 396 | */ |
363 | static int pcmcia_release_io(struct pcmcia_device *p_dev) | 397 | static int pcmcia_release_io(struct pcmcia_device *p_dev) |
364 | { | 398 | { |
@@ -387,6 +421,14 @@ out: | |||
387 | } /* pcmcia_release_io */ | 421 | } /* pcmcia_release_io */ |
388 | 422 | ||
389 | 423 | ||
424 | /** | ||
425 | * pcmcia_release_window() - release reserved iomem for PCMCIA devices | ||
426 | * @p_dev: pcmcia device | ||
427 | * @res: iomem resource to release | ||
428 | * | ||
429 | * pcmcia_release_window() releases &struct resource *res which was | ||
430 | * previously reserved by calling pcmcia_request_window(). | ||
431 | */ | ||
390 | int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | 432 | int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) |
391 | { | 433 | { |
392 | struct pcmcia_socket *s = p_dev->socket; | 434 | struct pcmcia_socket *s = p_dev->socket; |
@@ -420,6 +462,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
420 | kfree(win->res); | 462 | kfree(win->res); |
421 | win->res = NULL; | 463 | win->res = NULL; |
422 | } | 464 | } |
465 | res->start = res->end = 0; | ||
466 | res->flags = IORESOURCE_MEM; | ||
423 | p_dev->_win &= ~CLIENT_WIN_REQ(w); | 467 | p_dev->_win &= ~CLIENT_WIN_REQ(w); |
424 | mutex_unlock(&s->ops_mutex); | 468 | mutex_unlock(&s->ops_mutex); |
425 | 469 | ||
@@ -428,23 +472,30 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
428 | EXPORT_SYMBOL(pcmcia_release_window); | 472 | EXPORT_SYMBOL(pcmcia_release_window); |
429 | 473 | ||
430 | 474 | ||
431 | int pcmcia_request_configuration(struct pcmcia_device *p_dev, | 475 | /** |
432 | config_req_t *req) | 476 | * pcmcia_enable_device() - set up and activate a PCMCIA device |
477 | * @p_dev: the associated PCMCIA device | ||
478 | * | ||
479 | * pcmcia_enable_device() physically enables a PCMCIA device. It parses | ||
480 | * the flags passed to in @flags and stored in @p_dev->flags and sets up | ||
481 | * the Vpp voltage, enables the speaker line, I/O ports and store proper | ||
482 | * values to configuration registers. | ||
483 | */ | ||
484 | int pcmcia_enable_device(struct pcmcia_device *p_dev) | ||
433 | { | 485 | { |
434 | int i; | 486 | int i; |
435 | u_int base; | 487 | unsigned int base; |
436 | struct pcmcia_socket *s = p_dev->socket; | 488 | struct pcmcia_socket *s = p_dev->socket; |
437 | config_t *c; | 489 | config_t *c; |
438 | pccard_io_map iomap; | 490 | pccard_io_map iomap; |
491 | unsigned char status = 0; | ||
492 | unsigned char ext_status = 0; | ||
493 | unsigned char option = 0; | ||
494 | unsigned int flags = p_dev->config_flags; | ||
439 | 495 | ||
440 | if (!(s->state & SOCKET_PRESENT)) | 496 | if (!(s->state & SOCKET_PRESENT)) |
441 | return -ENODEV; | 497 | return -ENODEV; |
442 | 498 | ||
443 | if (req->IntType & INT_CARDBUS) { | ||
444 | dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | mutex_lock(&s->ops_mutex); | 499 | mutex_lock(&s->ops_mutex); |
449 | c = p_dev->function_config; | 500 | c = p_dev->function_config; |
450 | if (c->state & CONFIG_LOCKED) { | 501 | if (c->state & CONFIG_LOCKED) { |
@@ -454,7 +505,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
454 | } | 505 | } |
455 | 506 | ||
456 | /* Do power control. We don't allow changes in Vcc. */ | 507 | /* Do power control. We don't allow changes in Vcc. */ |
457 | s->socket.Vpp = req->Vpp; | 508 | s->socket.Vpp = p_dev->vpp; |
458 | if (s->ops->set_socket(s, &s->socket)) { | 509 | if (s->ops->set_socket(s, &s->socket)) { |
459 | mutex_unlock(&s->ops_mutex); | 510 | mutex_unlock(&s->ops_mutex); |
460 | dev_printk(KERN_WARNING, &p_dev->dev, | 511 | dev_printk(KERN_WARNING, &p_dev->dev, |
@@ -463,64 +514,72 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
463 | } | 514 | } |
464 | 515 | ||
465 | /* Pick memory or I/O card, DMA mode, interrupt */ | 516 | /* Pick memory or I/O card, DMA mode, interrupt */ |
466 | c->IntType = req->IntType; | 517 | if (p_dev->_io) |
467 | c->Attributes = req->Attributes; | ||
468 | if (req->IntType & INT_MEMORY_AND_IO) | ||
469 | s->socket.flags |= SS_IOCARD; | 518 | s->socket.flags |= SS_IOCARD; |
470 | if (req->IntType & INT_ZOOMED_VIDEO) | 519 | if (flags & CONF_ENABLE_SPKR) { |
471 | s->socket.flags |= SS_ZVCARD | SS_IOCARD; | ||
472 | if (req->Attributes & CONF_ENABLE_DMA) | ||
473 | s->socket.flags |= SS_DMA_MODE; | ||
474 | if (req->Attributes & CONF_ENABLE_SPKR) | ||
475 | s->socket.flags |= SS_SPKR_ENA; | 520 | s->socket.flags |= SS_SPKR_ENA; |
476 | if (req->Attributes & CONF_ENABLE_IRQ) | 521 | status = CCSR_AUDIO_ENA; |
522 | if (!(p_dev->config_regs & PRESENT_STATUS)) | ||
523 | dev_warn(&p_dev->dev, "speaker requested, but " | ||
524 | "PRESENT_STATUS not set!\n"); | ||
525 | } | ||
526 | if (flags & CONF_ENABLE_IRQ) | ||
477 | s->socket.io_irq = s->pcmcia_irq; | 527 | s->socket.io_irq = s->pcmcia_irq; |
478 | else | 528 | else |
479 | s->socket.io_irq = 0; | 529 | s->socket.io_irq = 0; |
530 | if (flags & CONF_ENABLE_ESR) { | ||
531 | p_dev->config_regs |= PRESENT_EXT_STATUS; | ||
532 | ext_status = ESR_REQ_ATTN_ENA; | ||
533 | } | ||
480 | s->ops->set_socket(s, &s->socket); | 534 | s->ops->set_socket(s, &s->socket); |
481 | s->lock_count++; | 535 | s->lock_count++; |
482 | 536 | ||
537 | dev_dbg(&p_dev->dev, | ||
538 | "enable_device: V %d, flags %x, base %x, regs %x, idx %x\n", | ||
539 | p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs, | ||
540 | p_dev->config_index); | ||
541 | |||
483 | /* Set up CIS configuration registers */ | 542 | /* Set up CIS configuration registers */ |
484 | base = c->ConfigBase = req->ConfigBase; | 543 | base = p_dev->config_base; |
485 | c->CardValues = req->Present; | 544 | if (p_dev->config_regs & PRESENT_COPY) { |
486 | if (req->Present & PRESENT_COPY) { | 545 | u16 tmp = 0; |
487 | c->Copy = req->Copy; | 546 | dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n"); |
488 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); | 547 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp); |
489 | } | 548 | } |
490 | if (req->Present & PRESENT_OPTION) { | 549 | if (p_dev->config_regs & PRESENT_PIN_REPLACE) { |
550 | u16 tmp = 0; | ||
551 | dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n"); | ||
552 | pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp); | ||
553 | } | ||
554 | if (p_dev->config_regs & PRESENT_OPTION) { | ||
491 | if (s->functions == 1) { | 555 | if (s->functions == 1) { |
492 | c->Option = req->ConfigIndex & COR_CONFIG_MASK; | 556 | option = p_dev->config_index & COR_CONFIG_MASK; |
493 | } else { | 557 | } else { |
494 | c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; | 558 | option = p_dev->config_index & COR_MFC_CONFIG_MASK; |
495 | c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; | 559 | option |= COR_FUNC_ENA|COR_IREQ_ENA; |
496 | if (req->Present & PRESENT_IOBASE_0) | 560 | if (p_dev->config_regs & PRESENT_IOBASE_0) |
497 | c->Option |= COR_ADDR_DECODE; | 561 | option |= COR_ADDR_DECODE; |
498 | } | 562 | } |
499 | if ((req->Attributes & CONF_ENABLE_IRQ) && | 563 | if ((flags & CONF_ENABLE_IRQ) && |
500 | !(req->Attributes & CONF_ENABLE_PULSE_IRQ)) | 564 | !(flags & CONF_ENABLE_PULSE_IRQ)) |
501 | c->Option |= COR_LEVEL_REQ; | 565 | option |= COR_LEVEL_REQ; |
502 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | 566 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option); |
503 | mdelay(40); | 567 | mdelay(40); |
504 | } | 568 | } |
505 | if (req->Present & PRESENT_STATUS) { | 569 | if (p_dev->config_regs & PRESENT_STATUS) |
506 | c->Status = req->Status; | 570 | pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status); |
507 | pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); | 571 | |
508 | } | 572 | if (p_dev->config_regs & PRESENT_EXT_STATUS) |
509 | if (req->Present & PRESENT_PIN_REPLACE) { | 573 | pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, |
510 | c->Pin = req->Pin; | 574 | &ext_status); |
511 | pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); | 575 | |
512 | } | 576 | if (p_dev->config_regs & PRESENT_IOBASE_0) { |
513 | if (req->Present & PRESENT_EXT_STATUS) { | ||
514 | c->ExtStatus = req->ExtStatus; | ||
515 | pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); | ||
516 | } | ||
517 | if (req->Present & PRESENT_IOBASE_0) { | ||
518 | u8 b = c->io[0].start & 0xff; | 577 | u8 b = c->io[0].start & 0xff; |
519 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); | 578 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); |
520 | b = (c->io[0].start >> 8) & 0xff; | 579 | b = (c->io[0].start >> 8) & 0xff; |
521 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); | 580 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); |
522 | } | 581 | } |
523 | if (req->Present & PRESENT_IOSIZE) { | 582 | if (p_dev->config_regs & PRESENT_IOSIZE) { |
524 | u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1; | 583 | u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1; |
525 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); | 584 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); |
526 | } | 585 | } |
@@ -551,14 +610,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
551 | p_dev->_locked = 1; | 610 | p_dev->_locked = 1; |
552 | mutex_unlock(&s->ops_mutex); | 611 | mutex_unlock(&s->ops_mutex); |
553 | return 0; | 612 | return 0; |
554 | } /* pcmcia_request_configuration */ | 613 | } /* pcmcia_enable_device */ |
555 | EXPORT_SYMBOL(pcmcia_request_configuration); | 614 | EXPORT_SYMBOL(pcmcia_enable_device); |
556 | 615 | ||
557 | 616 | ||
558 | /** | 617 | /** |
559 | * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices | 618 | * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices |
619 | * @p_dev: the associated PCMCIA device | ||
560 | * | 620 | * |
561 | * pcmcia_request_io() attepts to reserve the IO port ranges specified in | 621 | * pcmcia_request_io() attempts to reserve the IO port ranges specified in |
562 | * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The | 622 | * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The |
563 | * "start" value is the requested start of the IO port resource; "end" | 623 | * "start" value is the requested start of the IO port resource; "end" |
564 | * reflects the number of ports requested. The number of IO lines requested | 624 | * reflects the number of ports requested. The number of IO lines requested |
@@ -622,11 +682,13 @@ EXPORT_SYMBOL(pcmcia_request_io); | |||
622 | 682 | ||
623 | /** | 683 | /** |
624 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device | 684 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device |
685 | * @p_dev: the associated PCMCIA device | ||
686 | * @handler: IRQ handler to register | ||
625 | * | 687 | * |
626 | * pcmcia_request_irq() is a wrapper around request_irq which will allow | 688 | * pcmcia_request_irq() is a wrapper around request_irq() which allows |
627 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). | 689 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). |
628 | * Drivers are free to use request_irq() directly, but then they need to | 690 | * Drivers are free to use request_irq() directly, but then they need to |
629 | * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ | 691 | * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ |
630 | * handlers are allowed. | 692 | * handlers are allowed. |
631 | */ | 693 | */ |
632 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, | 694 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, |
@@ -649,12 +711,14 @@ EXPORT_SYMBOL(pcmcia_request_irq); | |||
649 | 711 | ||
650 | /** | 712 | /** |
651 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first | 713 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first |
714 | * @p_dev: the associated PCMCIA device | ||
715 | * @handler: IRQ handler to register | ||
652 | * | 716 | * |
653 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq which | 717 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which |
654 | * attempts first to request an exclusive IRQ. If it fails, it also accepts | 718 | * attempts first to request an exclusive IRQ. If it fails, it also accepts |
655 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for | 719 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for |
656 | * IRQ sharing and either use request_irq directly (then they need to call | 720 | * IRQ sharing and either use request_irq directly (then they need to call |
657 | * free_irq themselves, too), or the pcmcia_request_irq() function. | 721 | * free_irq() themselves, too), or the pcmcia_request_irq() function. |
658 | */ | 722 | */ |
659 | int __must_check | 723 | int __must_check |
660 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, | 724 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, |
@@ -795,38 +859,47 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev) | |||
795 | } | 859 | } |
796 | 860 | ||
797 | 861 | ||
798 | /** pcmcia_request_window | 862 | /** |
863 | * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices | ||
864 | * @p_dev: the associated PCMCIA device | ||
865 | * @res: &struct resource pointing to p_dev->resource[2..5] | ||
866 | * @speed: access speed | ||
799 | * | 867 | * |
800 | * Request_window() establishes a mapping between card memory space | 868 | * pcmcia_request_window() attepts to reserve an iomem ranges specified in |
801 | * and system memory space. | 869 | * &struct resource @res pointing to one of the entries in |
870 | * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the | ||
871 | * requested start of the IO mem resource; "end" reflects the size | ||
872 | * requested. | ||
802 | */ | 873 | */ |
803 | int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh) | 874 | int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res, |
875 | unsigned int speed) | ||
804 | { | 876 | { |
805 | struct pcmcia_socket *s = p_dev->socket; | 877 | struct pcmcia_socket *s = p_dev->socket; |
806 | pccard_mem_map *win; | 878 | pccard_mem_map *win; |
807 | u_long align; | 879 | u_long align; |
808 | struct resource *res; | ||
809 | int w; | 880 | int w; |
810 | 881 | ||
882 | dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed); | ||
883 | |||
811 | if (!(s->state & SOCKET_PRESENT)) { | 884 | if (!(s->state & SOCKET_PRESENT)) { |
812 | dev_dbg(&p_dev->dev, "No card present\n"); | 885 | dev_dbg(&p_dev->dev, "No card present\n"); |
813 | return -ENODEV; | 886 | return -ENODEV; |
814 | } | 887 | } |
815 | 888 | ||
816 | /* Window size defaults to smallest available */ | 889 | /* Window size defaults to smallest available */ |
817 | if (req->Size == 0) | 890 | if (res->end == 0) |
818 | req->Size = s->map_size; | 891 | res->end = s->map_size; |
819 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; | 892 | align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size; |
820 | if (req->Size & (s->map_size-1)) { | 893 | if (res->end & (s->map_size-1)) { |
821 | dev_dbg(&p_dev->dev, "invalid map size\n"); | 894 | dev_dbg(&p_dev->dev, "invalid map size\n"); |
822 | return -EINVAL; | 895 | return -EINVAL; |
823 | } | 896 | } |
824 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | 897 | if ((res->start && (s->features & SS_CAP_STATIC_MAP)) || |
825 | (req->Base & (align-1))) { | 898 | (res->start & (align-1))) { |
826 | dev_dbg(&p_dev->dev, "invalid base address\n"); | 899 | dev_dbg(&p_dev->dev, "invalid base address\n"); |
827 | return -EINVAL; | 900 | return -EINVAL; |
828 | } | 901 | } |
829 | if (req->Base) | 902 | if (res->start) |
830 | align = 0; | 903 | align = 0; |
831 | 904 | ||
832 | /* Allocate system memory window */ | 905 | /* Allocate system memory window */ |
@@ -843,7 +916,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
843 | win = &s->win[w]; | 916 | win = &s->win[w]; |
844 | 917 | ||
845 | if (!(s->features & SS_CAP_STATIC_MAP)) { | 918 | if (!(s->features & SS_CAP_STATIC_MAP)) { |
846 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, | 919 | win->res = pcmcia_find_mem_region(res->start, res->end, align, |
847 | 0, s); | 920 | 0, s); |
848 | if (!win->res) { | 921 | if (!win->res) { |
849 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); | 922 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); |
@@ -855,8 +928,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
855 | 928 | ||
856 | /* Configure the socket controller */ | 929 | /* Configure the socket controller */ |
857 | win->map = w+1; | 930 | win->map = w+1; |
858 | win->flags = req->Attributes; | 931 | win->flags = res->flags & WIN_FLAGS_MAP; |
859 | win->speed = req->AccessSpeed; | 932 | win->speed = speed; |
860 | win->card_start = 0; | 933 | win->card_start = 0; |
861 | 934 | ||
862 | if (s->ops->set_mem_map(s, win) != 0) { | 935 | if (s->ops->set_mem_map(s, win) != 0) { |
@@ -868,17 +941,14 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
868 | 941 | ||
869 | /* Return window handle */ | 942 | /* Return window handle */ |
870 | if (s->features & SS_CAP_STATIC_MAP) | 943 | if (s->features & SS_CAP_STATIC_MAP) |
871 | req->Base = win->static_start; | 944 | res->start = win->static_start; |
872 | else | 945 | else |
873 | req->Base = win->res->start; | 946 | res->start = win->res->start; |
874 | 947 | ||
875 | /* convert to new-style resources */ | 948 | /* convert to new-style resources */ |
876 | res = p_dev->resource[w + MAX_IO_WIN]; | 949 | res->end += res->start - 1; |
877 | res->start = req->Base; | 950 | res->flags &= ~WIN_FLAGS_REQ; |
878 | res->end = req->Base + req->Size - 1; | 951 | res->flags |= (win->map << 2) | IORESOURCE_MEM; |
879 | res->flags &= ~IORESOURCE_BITS; | ||
880 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); | ||
881 | res->flags |= IORESOURCE_MEM; | ||
882 | res->parent = win->res; | 952 | res->parent = win->res; |
883 | if (win->res) | 953 | if (win->res) |
884 | request_resource(&iomem_resource, res); | 954 | request_resource(&iomem_resource, res); |
@@ -886,15 +956,30 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
886 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); | 956 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); |
887 | 957 | ||
888 | mutex_unlock(&s->ops_mutex); | 958 | mutex_unlock(&s->ops_mutex); |
889 | *wh = res; | ||
890 | 959 | ||
891 | return 0; | 960 | return 0; |
892 | } /* pcmcia_request_window */ | 961 | } /* pcmcia_request_window */ |
893 | EXPORT_SYMBOL(pcmcia_request_window); | 962 | EXPORT_SYMBOL(pcmcia_request_window); |
894 | 963 | ||
964 | |||
965 | /** | ||
966 | * pcmcia_disable_device() - disable and clean up a PCMCIA device | ||
967 | * @p_dev: the associated PCMCIA device | ||
968 | * | ||
969 | * pcmcia_disable_device() is the driver-callable counterpart to | ||
970 | * pcmcia_enable_device(): If a PCMCIA device is no longer used, | ||
971 | * drivers are expected to clean up and disable the device by calling | ||
972 | * this function. Any I/O ranges (iomem and ioports) will be released, | ||
973 | * the Vpp voltage will be set to 0, and IRQs will no longer be | ||
974 | * generated -- at least if there is no other card function (of | ||
975 | * multifunction devices) being used. | ||
976 | */ | ||
895 | void pcmcia_disable_device(struct pcmcia_device *p_dev) | 977 | void pcmcia_disable_device(struct pcmcia_device *p_dev) |
896 | { | 978 | { |
897 | int i; | 979 | int i; |
980 | |||
981 | dev_dbg(&p_dev->dev, "disabling device\n"); | ||
982 | |||
898 | for (i = 0; i < MAX_WIN; i++) { | 983 | for (i = 0; i < MAX_WIN; i++) { |
899 | struct resource *res = p_dev->resource[MAX_IO_WIN + i]; | 984 | struct resource *res = p_dev->resource[MAX_IO_WIN + i]; |
900 | if (res->flags & WIN_FLAGS_REQ) | 985 | if (res->flags & WIN_FLAGS_REQ) |
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index deef6656ab7b..8cbfa067171f 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | 19 | ||
20 | #include <pcmcia/ss.h> | 20 | #include <pcmcia/ss.h> |
21 | #include <pcmcia/cs.h> | ||
22 | 21 | ||
23 | #include <asm/system.h> | 22 | #include <asm/system.h> |
24 | 23 | ||
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c index 8510c35d2952..523eb691c30b 100644 --- a/drivers/pcmcia/rsrc_iodyn.c +++ b/drivers/pcmcia/rsrc_iodyn.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | 18 | ||
19 | #include <pcmcia/ss.h> | 19 | #include <pcmcia/ss.h> |
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/cistpl.h> | 20 | #include <pcmcia/cistpl.h> |
22 | #include "cs_internal.h" | 21 | #include "cs_internal.h" |
23 | 22 | ||
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 4e80421fd908..aa628ed0e9f4 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | 18 | ||
19 | #include <pcmcia/ss.h> | 19 | #include <pcmcia/ss.h> |
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/cistpl.h> | 20 | #include <pcmcia/cistpl.h> |
22 | #include "cs_internal.h" | 21 | #include "cs_internal.h" |
23 | 22 | ||
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 96f348b35fde..b187555d4388 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
30 | 30 | ||
31 | #include <pcmcia/ss.h> | 31 | #include <pcmcia/ss.h> |
32 | #include <pcmcia/cs.h> | ||
33 | #include <pcmcia/cistpl.h> | 32 | #include <pcmcia/cistpl.h> |
34 | #include "cs_internal.h" | 33 | #include "cs_internal.h" |
35 | 34 | ||
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index e09851480295..945857f8c284 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | 37 | ||
38 | #include <pcmcia/cs.h> | ||
39 | #include <pcmcia/ss.h> | 38 | #include <pcmcia/ss.h> |
40 | 39 | ||
41 | #include <asm/hardware/scoop.h> | 40 | #include <asm/hardware/scoop.h> |
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 6f1a86b43c60..689e3c02edb8 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c | |||
@@ -627,8 +627,6 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) | |||
627 | 627 | ||
628 | pcmcia_unregister_socket(&skt->socket); | 628 | pcmcia_unregister_socket(&skt->socket); |
629 | 629 | ||
630 | flush_scheduled_work(); | ||
631 | |||
632 | skt->ops->hw_shutdown(skt); | 630 | skt->ops->hw_shutdown(skt); |
633 | 631 | ||
634 | soc_common_pcmcia_config_skt(skt, &dead_socket); | 632 | soc_common_pcmcia_config_skt(skt, &dead_socket); |
@@ -720,8 +718,6 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) | |||
720 | pcmcia_unregister_socket(&skt->socket); | 718 | pcmcia_unregister_socket(&skt->socket); |
721 | 719 | ||
722 | out_err_7: | 720 | out_err_7: |
723 | flush_scheduled_work(); | ||
724 | |||
725 | skt->ops->hw_shutdown(skt); | 721 | skt->ops->hw_shutdown(skt); |
726 | out_err_6: | 722 | out_err_6: |
727 | list_del(&skt->node); | 723 | list_del(&skt->node); |
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index 3fba3a679128..bbcd5385a221 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | /* include the world */ | 12 | /* include the world */ |
13 | #include <linux/cpufreq.h> | 13 | #include <linux/cpufreq.h> |
14 | #include <pcmcia/cs.h> | ||
15 | #include <pcmcia/ss.h> | 14 | #include <pcmcia/ss.h> |
16 | #include <pcmcia/cistpl.h> | 15 | #include <pcmcia/cistpl.h> |
17 | 16 | ||
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index cb0d3ace18bd..71aeed93037c 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
28 | 28 | ||
29 | #include <pcmcia/ss.h> | 29 | #include <pcmcia/ss.h> |
30 | #include <pcmcia/cs.h> | ||
31 | #include <pcmcia/cistpl.h> | 30 | #include <pcmcia/cistpl.h> |
32 | #include <pcmcia/cisreg.h> | 31 | #include <pcmcia/cisreg.h> |
33 | #include <pcmcia/ds.h> | 32 | #include <pcmcia/ds.h> |
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index be0d841c7ebd..310160bffe38 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <asm/io.h> | 49 | #include <asm/io.h> |
50 | #include <asm/system.h> | 50 | #include <asm/system.h> |
51 | 51 | ||
52 | #include <pcmcia/cs.h> | ||
53 | #include <pcmcia/ss.h> | 52 | #include <pcmcia/ss.h> |
54 | #include "tcic.h" | 53 | #include "tcic.h" |
55 | 54 | ||
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 9b3c15827e5c..c6d36b3a6ce8 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c | |||
@@ -461,7 +461,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev, | |||
461 | { | 461 | { |
462 | vrc4173_socket_t *socket; | 462 | vrc4173_socket_t *socket; |
463 | unsigned long start, len, flags; | 463 | unsigned long start, len, flags; |
464 | int slot, err; | 464 | int slot, err, ret; |
465 | 465 | ||
466 | slot = vrc4173_cardu_slots++; | 466 | slot = vrc4173_cardu_slots++; |
467 | socket = &cardu_sockets[slot]; | 467 | socket = &cardu_sockets[slot]; |
@@ -474,43 +474,63 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev, | |||
474 | return err; | 474 | return err; |
475 | 475 | ||
476 | start = pci_resource_start(dev, 0); | 476 | start = pci_resource_start(dev, 0); |
477 | if (start == 0) | 477 | if (start == 0) { |
478 | return -ENODEV; | 478 | ret = -ENODEV; |
479 | goto disable; | ||
480 | } | ||
479 | 481 | ||
480 | len = pci_resource_len(dev, 0); | 482 | len = pci_resource_len(dev, 0); |
481 | if (len == 0) | 483 | if (len == 0) { |
482 | return -ENODEV; | 484 | ret = -ENODEV; |
485 | goto disable; | ||
486 | } | ||
483 | 487 | ||
484 | if (((flags = pci_resource_flags(dev, 0)) & IORESOURCE_MEM) == 0) | 488 | flags = pci_resource_flags(dev, 0); |
485 | return -EBUSY; | 489 | if ((flags & IORESOURCE_MEM) == 0) { |
490 | ret = -EBUSY; | ||
491 | goto disable; | ||
492 | } | ||
486 | 493 | ||
487 | if ((err = pci_request_regions(dev, socket->name)) < 0) | 494 | err = pci_request_regions(dev, socket->name); |
488 | return err; | 495 | if (err < 0) { |
496 | ret = err; | ||
497 | goto disable; | ||
498 | } | ||
489 | 499 | ||
490 | socket->base = ioremap(start, len); | 500 | socket->base = ioremap(start, len); |
491 | if (socket->base == NULL) | 501 | if (socket->base == NULL) { |
492 | return -ENODEV; | 502 | ret = -ENODEV; |
503 | goto release; | ||
504 | } | ||
493 | 505 | ||
494 | socket->dev = dev; | 506 | socket->dev = dev; |
495 | 507 | ||
496 | socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1); | 508 | socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1); |
497 | if (socket->pcmcia_socket == NULL) { | 509 | if (socket->pcmcia_socket == NULL) { |
498 | iounmap(socket->base); | 510 | ret = -ENOMEM; |
499 | socket->base = NULL; | 511 | goto unmap; |
500 | return -ENOMEM; | ||
501 | } | 512 | } |
502 | 513 | ||
503 | if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) { | 514 | if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) { |
504 | pcmcia_unregister_socket(socket->pcmcia_socket); | 515 | ret = -EBUSY; |
505 | socket->pcmcia_socket = NULL; | 516 | goto unregister; |
506 | iounmap(socket->base); | ||
507 | socket->base = NULL; | ||
508 | return -EBUSY; | ||
509 | } | 517 | } |
510 | 518 | ||
511 | printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq); | 519 | printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq); |
512 | 520 | ||
513 | return 0; | 521 | return 0; |
522 | |||
523 | unregister: | ||
524 | pcmcia_unregister_socket(socket->pcmcia_socket); | ||
525 | socket->pcmcia_socket = NULL; | ||
526 | unmap: | ||
527 | iounmap(socket->base); | ||
528 | socket->base = NULL; | ||
529 | release: | ||
530 | pci_release_regions(dev); | ||
531 | disable: | ||
532 | pci_disable_device(dev); | ||
533 | return ret; | ||
514 | } | 534 | } |
515 | 535 | ||
516 | static int __devinit vrc4173_cardu_setup(char *options) | 536 | static int __devinit vrc4173_cardu_setup(char *options) |
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c index fa88c360c37a..3b67a1b6a197 100644 --- a/drivers/pcmcia/xxs1500_ss.c +++ b/drivers/pcmcia/xxs1500_ss.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | 19 | ||
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/ss.h> | 20 | #include <pcmcia/ss.h> |
22 | #include <pcmcia/cistpl.h> | 21 | #include <pcmcia/cistpl.h> |
23 | 22 | ||
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 414d9a6f9a32..408dbaa080a1 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | 21 | ||
22 | #include <pcmcia/ss.h> | 22 | #include <pcmcia/ss.h> |
23 | #include <pcmcia/cs.h> | ||
24 | 23 | ||
25 | #include "yenta_socket.h" | 24 | #include "yenta_socket.h" |
26 | #include "i82365.h" | 25 | #include "i82365.h" |
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 9024480a8228..c44a5e8b8b82 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
@@ -51,7 +51,6 @@ | |||
51 | * TODO: | 51 | * TODO: |
52 | * - handle CPU hotplug | 52 | * - handle CPU hotplug |
53 | * - provide turbo enable/disable api | 53 | * - provide turbo enable/disable api |
54 | * - make sure we can write turbo enable/disable reg based on MISC_EN | ||
55 | * | 54 | * |
56 | * Related documents: | 55 | * Related documents: |
57 | * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 | 56 | * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 |
@@ -230,7 +229,7 @@ | |||
230 | #define THM_TC2 0xac | 229 | #define THM_TC2 0xac |
231 | #define THM_DTV 0xb0 | 230 | #define THM_DTV 0xb0 |
232 | #define THM_ITV 0xd8 | 231 | #define THM_ITV 0xd8 |
233 | #define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */ | 232 | #define ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */ |
234 | #define ITV_ME_SEQNO_SHIFT (16) | 233 | #define ITV_ME_SEQNO_SHIFT (16) |
235 | #define ITV_MCH_TEMP_MASK 0x0000ff00 | 234 | #define ITV_MCH_TEMP_MASK 0x0000ff00 |
236 | #define ITV_MCH_TEMP_SHIFT (8) | 235 | #define ITV_MCH_TEMP_SHIFT (8) |
@@ -325,6 +324,7 @@ struct ips_driver { | |||
325 | bool gpu_preferred; | 324 | bool gpu_preferred; |
326 | bool poll_turbo_status; | 325 | bool poll_turbo_status; |
327 | bool second_cpu; | 326 | bool second_cpu; |
327 | bool turbo_toggle_allowed; | ||
328 | struct ips_mcp_limits *limits; | 328 | struct ips_mcp_limits *limits; |
329 | 329 | ||
330 | /* Optional MCH interfaces for if i915 is in use */ | 330 | /* Optional MCH interfaces for if i915 is in use */ |
@@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips) | |||
415 | new_limit = cur_limit - 8; /* 1W decrease */ | 415 | new_limit = cur_limit - 8; /* 1W decrease */ |
416 | 416 | ||
417 | /* Clamp to SKU TDP limit */ | 417 | /* Clamp to SKU TDP limit */ |
418 | if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK)) | 418 | if (new_limit < (ips->orig_turbo_limit & TURBO_TDP_MASK)) |
419 | new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; | 419 | new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; |
420 | 420 | ||
421 | thm_writew(THM_MPCPC, (new_limit * 10) / 8); | 421 | thm_writew(THM_MPCPC, (new_limit * 10) / 8); |
@@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips) | |||
461 | if (ips->__cpu_turbo_on) | 461 | if (ips->__cpu_turbo_on) |
462 | return; | 462 | return; |
463 | 463 | ||
464 | on_each_cpu(do_enable_cpu_turbo, ips, 1); | 464 | if (ips->turbo_toggle_allowed) |
465 | on_each_cpu(do_enable_cpu_turbo, ips, 1); | ||
465 | 466 | ||
466 | ips->__cpu_turbo_on = true; | 467 | ips->__cpu_turbo_on = true; |
467 | } | 468 | } |
@@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips) | |||
498 | if (!ips->__cpu_turbo_on) | 499 | if (!ips->__cpu_turbo_on) |
499 | return; | 500 | return; |
500 | 501 | ||
501 | on_each_cpu(do_disable_cpu_turbo, ips, 1); | 502 | if (ips->turbo_toggle_allowed) |
503 | on_each_cpu(do_disable_cpu_turbo, ips, 1); | ||
502 | 504 | ||
503 | ips->__cpu_turbo_on = false; | 505 | ips->__cpu_turbo_on = false; |
504 | } | 506 | } |
@@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips) | |||
598 | { | 600 | { |
599 | unsigned long flags; | 601 | unsigned long flags; |
600 | bool ret = false; | 602 | bool ret = false; |
603 | u32 temp_limit; | ||
604 | u32 avg_power; | ||
605 | const char *msg = "MCP limit exceeded: "; | ||
601 | 606 | ||
602 | spin_lock_irqsave(&ips->turbo_status_lock, flags); | 607 | spin_lock_irqsave(&ips->turbo_status_lock, flags); |
603 | if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100)) | 608 | |
604 | ret = true; | 609 | temp_limit = ips->mcp_temp_limit * 100; |
605 | if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit) | 610 | if (ips->mcp_avg_temp > temp_limit) { |
611 | dev_info(&ips->dev->dev, | ||
612 | "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp, | ||
613 | temp_limit); | ||
606 | ret = true; | 614 | ret = true; |
607 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); | 615 | } |
608 | 616 | ||
609 | if (ret) | 617 | avg_power = ips->cpu_avg_power + ips->mch_avg_power; |
618 | if (avg_power > ips->mcp_power_limit) { | ||
610 | dev_info(&ips->dev->dev, | 619 | dev_info(&ips->dev->dev, |
611 | "MCP power or thermal limit exceeded\n"); | 620 | "%sAvg power %u, limit %u\n", msg, avg_power, |
621 | ips->mcp_power_limit); | ||
622 | ret = true; | ||
623 | } | ||
624 | |||
625 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); | ||
612 | 626 | ||
613 | return ret; | 627 | return ret; |
614 | } | 628 | } |
@@ -663,6 +677,27 @@ static bool mch_exceeded(struct ips_driver *ips) | |||
663 | } | 677 | } |
664 | 678 | ||
665 | /** | 679 | /** |
680 | * verify_limits - verify BIOS provided limits | ||
681 | * @ips: IPS structure | ||
682 | * | ||
683 | * BIOS can optionally provide non-default limits for power and temp. Check | ||
684 | * them here and use the defaults if the BIOS values are not provided or | ||
685 | * are otherwise unusable. | ||
686 | */ | ||
687 | static void verify_limits(struct ips_driver *ips) | ||
688 | { | ||
689 | if (ips->mcp_power_limit < ips->limits->mcp_power_limit || | ||
690 | ips->mcp_power_limit > 35000) | ||
691 | ips->mcp_power_limit = ips->limits->mcp_power_limit; | ||
692 | |||
693 | if (ips->mcp_temp_limit < ips->limits->core_temp_limit || | ||
694 | ips->mcp_temp_limit < ips->limits->mch_temp_limit || | ||
695 | ips->mcp_temp_limit > 150) | ||
696 | ips->mcp_temp_limit = min(ips->limits->core_temp_limit, | ||
697 | ips->limits->mch_temp_limit); | ||
698 | } | ||
699 | |||
700 | /** | ||
666 | * update_turbo_limits - get various limits & settings from regs | 701 | * update_turbo_limits - get various limits & settings from regs |
667 | * @ips: IPS driver struct | 702 | * @ips: IPS driver struct |
668 | * | 703 | * |
@@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips) | |||
680 | u32 hts = thm_readl(THM_HTS); | 715 | u32 hts = thm_readl(THM_HTS); |
681 | 716 | ||
682 | ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); | 717 | ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); |
683 | ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); | 718 | /* |
719 | * Disable turbo for now, until we can figure out why the power figures | ||
720 | * are wrong | ||
721 | */ | ||
722 | ips->cpu_turbo_enabled = false; | ||
723 | |||
724 | if (ips->gpu_busy) | ||
725 | ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); | ||
726 | |||
684 | ips->core_power_limit = thm_readw(THM_MPCPC); | 727 | ips->core_power_limit = thm_readw(THM_MPCPC); |
685 | ips->mch_power_limit = thm_readw(THM_MMGPC); | 728 | ips->mch_power_limit = thm_readw(THM_MMGPC); |
686 | ips->mcp_temp_limit = thm_readw(THM_PTL); | 729 | ips->mcp_temp_limit = thm_readw(THM_PTL); |
687 | ips->mcp_power_limit = thm_readw(THM_MPPC); | 730 | ips->mcp_power_limit = thm_readw(THM_MPPC); |
688 | 731 | ||
732 | verify_limits(ips); | ||
689 | /* Ignore BIOS CPU vs GPU pref */ | 733 | /* Ignore BIOS CPU vs GPU pref */ |
690 | } | 734 | } |
691 | 735 | ||
@@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period) | |||
858 | ret = (ret * 1000) / 65535; | 902 | ret = (ret * 1000) / 65535; |
859 | *last = val; | 903 | *last = val; |
860 | 904 | ||
861 | return ret; | 905 | return 0; |
862 | } | 906 | } |
863 | 907 | ||
864 | static const u16 temp_decay_factor = 2; | 908 | static const u16 temp_decay_factor = 2; |
@@ -940,7 +984,6 @@ static int ips_monitor(void *data) | |||
940 | kfree(mch_samples); | 984 | kfree(mch_samples); |
941 | kfree(cpu_samples); | 985 | kfree(cpu_samples); |
942 | kfree(mchp_samples); | 986 | kfree(mchp_samples); |
943 | kthread_stop(ips->adjust); | ||
944 | return -ENOMEM; | 987 | return -ENOMEM; |
945 | } | 988 | } |
946 | 989 | ||
@@ -948,7 +991,7 @@ static int ips_monitor(void *data) | |||
948 | ITV_ME_SEQNO_SHIFT; | 991 | ITV_ME_SEQNO_SHIFT; |
949 | seqno_timestamp = get_jiffies_64(); | 992 | seqno_timestamp = get_jiffies_64(); |
950 | 993 | ||
951 | old_cpu_power = thm_readl(THM_CEC) / 65535; | 994 | old_cpu_power = thm_readl(THM_CEC); |
952 | schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); | 995 | schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); |
953 | 996 | ||
954 | /* Collect an initial average */ | 997 | /* Collect an initial average */ |
@@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) | |||
1150 | STS_GPL_SHIFT; | 1193 | STS_GPL_SHIFT; |
1151 | /* ignore EC CPU vs GPU pref */ | 1194 | /* ignore EC CPU vs GPU pref */ |
1152 | ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); | 1195 | ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); |
1153 | ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); | 1196 | /* |
1197 | * Disable turbo for now, until we can figure | ||
1198 | * out why the power figures are wrong | ||
1199 | */ | ||
1200 | ips->cpu_turbo_enabled = false; | ||
1201 | if (ips->gpu_busy) | ||
1202 | ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); | ||
1154 | ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> | 1203 | ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> |
1155 | STS_PTL_SHIFT; | 1204 | STS_PTL_SHIFT; |
1156 | ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> | 1205 | ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> |
1157 | STS_PPL_SHIFT; | 1206 | STS_PPL_SHIFT; |
1207 | verify_limits(ips); | ||
1158 | spin_unlock(&ips->turbo_status_lock); | 1208 | spin_unlock(&ips->turbo_status_lock); |
1159 | 1209 | ||
1160 | thm_writeb(THM_SEC, SEC_ACK); | 1210 | thm_writeb(THM_SEC, SEC_ACK); |
@@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) | |||
1333 | * turbo manually or we'll get an illegal MSR access, even though | 1383 | * turbo manually or we'll get an illegal MSR access, even though |
1334 | * turbo will still be available. | 1384 | * turbo will still be available. |
1335 | */ | 1385 | */ |
1336 | if (!(misc_en & IA32_MISC_TURBO_EN)) | 1386 | if (misc_en & IA32_MISC_TURBO_EN) |
1337 | ; /* add turbo MSR write allowed flag if necessary */ | 1387 | ips->turbo_toggle_allowed = true; |
1388 | else | ||
1389 | ips->turbo_toggle_allowed = false; | ||
1338 | 1390 | ||
1339 | if (strstr(boot_cpu_data.x86_model_id, "CPU M")) | 1391 | if (strstr(boot_cpu_data.x86_model_id, "CPU M")) |
1340 | limits = &ips_sv_limits; | 1392 | limits = &ips_sv_limits; |
@@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) | |||
1351 | tdp = turbo_power & TURBO_TDP_MASK; | 1403 | tdp = turbo_power & TURBO_TDP_MASK; |
1352 | 1404 | ||
1353 | /* Sanity check TDP against CPU */ | 1405 | /* Sanity check TDP against CPU */ |
1354 | if (limits->mcp_power_limit != (tdp / 8) * 1000) { | 1406 | if (limits->core_power_limit != (tdp / 8) * 1000) { |
1355 | dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n", | 1407 | dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n", |
1356 | tdp / 8, limits->mcp_power_limit / 1000); | 1408 | tdp / 8, limits->core_power_limit / 1000); |
1409 | limits->core_power_limit = (tdp / 8) * 1000; | ||
1357 | } | 1410 | } |
1358 | 1411 | ||
1359 | out: | 1412 | out: |
@@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips) | |||
1390 | return true; | 1443 | return true; |
1391 | 1444 | ||
1392 | out_put_busy: | 1445 | out_put_busy: |
1393 | symbol_put(i915_gpu_turbo_disable); | 1446 | symbol_put(i915_gpu_busy); |
1394 | out_put_lower: | 1447 | out_put_lower: |
1395 | symbol_put(i915_gpu_lower); | 1448 | symbol_put(i915_gpu_lower); |
1396 | out_put_raise: | 1449 | out_put_raise: |
@@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1532 | /* Save turbo limits & ratios */ | 1585 | /* Save turbo limits & ratios */ |
1533 | rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); | 1586 | rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); |
1534 | 1587 | ||
1535 | ips_enable_cpu_turbo(ips); | 1588 | ips_disable_cpu_turbo(ips); |
1536 | ips->cpu_turbo_enabled = true; | 1589 | ips->cpu_turbo_enabled = false; |
1537 | 1590 | ||
1538 | /* Set up the work queue and monitor/adjust threads */ | 1591 | /* Create thermal adjust thread */ |
1539 | ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); | 1592 | ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); |
1540 | if (IS_ERR(ips->monitor)) { | 1593 | if (IS_ERR(ips->adjust)) { |
1541 | dev_err(&dev->dev, | 1594 | dev_err(&dev->dev, |
1542 | "failed to create thermal monitor thread, aborting\n"); | 1595 | "failed to create thermal adjust thread, aborting\n"); |
1543 | ret = -ENOMEM; | 1596 | ret = -ENOMEM; |
1544 | goto error_free_irq; | 1597 | goto error_free_irq; |
1598 | |||
1545 | } | 1599 | } |
1546 | 1600 | ||
1547 | ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); | 1601 | /* |
1548 | if (IS_ERR(ips->adjust)) { | 1602 | * Set up the work queue and monitor thread. The monitor thread |
1603 | * will wake up ips_adjust thread. | ||
1604 | */ | ||
1605 | ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); | ||
1606 | if (IS_ERR(ips->monitor)) { | ||
1549 | dev_err(&dev->dev, | 1607 | dev_err(&dev->dev, |
1550 | "failed to create thermal adjust thread, aborting\n"); | 1608 | "failed to create thermal monitor thread, aborting\n"); |
1551 | ret = -ENOMEM; | 1609 | ret = -ENOMEM; |
1552 | goto error_thread_cleanup; | 1610 | goto error_thread_cleanup; |
1553 | } | 1611 | } |
@@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1566 | return ret; | 1624 | return ret; |
1567 | 1625 | ||
1568 | error_thread_cleanup: | 1626 | error_thread_cleanup: |
1569 | kthread_stop(ips->monitor); | 1627 | kthread_stop(ips->adjust); |
1570 | error_free_irq: | 1628 | error_free_irq: |
1571 | free_irq(ips->dev->irq, ips); | 1629 | free_irq(ips->dev->irq, ips); |
1572 | error_unmap: | 1630 | error_unmap: |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index f6d72e1f2a38..5707a80b96b6 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -468,7 +468,7 @@ sclp_sync_wait(void) | |||
468 | cr0_sync &= 0xffff00a0; | 468 | cr0_sync &= 0xffff00a0; |
469 | cr0_sync |= 0x00000200; | 469 | cr0_sync |= 0x00000200; |
470 | __ctl_load(cr0_sync, 0, 0); | 470 | __ctl_load(cr0_sync, 0, 0); |
471 | __raw_local_irq_stosm(0x01); | 471 | __arch_local_irq_stosm(0x01); |
472 | /* Loop until driver state indicates finished request */ | 472 | /* Loop until driver state indicates finished request */ |
473 | while (sclp_running_state != sclp_running_state_idle) { | 473 | while (sclp_running_state != sclp_running_state_idle) { |
474 | /* Check for expired request timer */ | 474 | /* Check for expired request timer */ |
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 61f49bdcc0c2..e77dd02eccdd 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <scsi/scsi_host.h> | 49 | #include <scsi/scsi_host.h> |
50 | #include "aha152x.h" | 50 | #include "aha152x.h" |
51 | 51 | ||
52 | #include <pcmcia/cs.h> | ||
53 | #include <pcmcia/cistpl.h> | 52 | #include <pcmcia/cistpl.h> |
54 | #include <pcmcia/ds.h> | 53 | #include <pcmcia/ds.h> |
55 | 54 | ||
@@ -86,8 +85,6 @@ static void aha152x_release_cs(struct pcmcia_device *link); | |||
86 | static void aha152x_detach(struct pcmcia_device *p_dev); | 85 | static void aha152x_detach(struct pcmcia_device *p_dev); |
87 | static int aha152x_config_cs(struct pcmcia_device *link); | 86 | static int aha152x_config_cs(struct pcmcia_device *link); |
88 | 87 | ||
89 | static struct pcmcia_device *dev_list; | ||
90 | |||
91 | static int aha152x_probe(struct pcmcia_device *link) | 88 | static int aha152x_probe(struct pcmcia_device *link) |
92 | { | 89 | { |
93 | scsi_info_t *info; | 90 | scsi_info_t *info; |
@@ -100,11 +97,8 @@ static int aha152x_probe(struct pcmcia_device *link) | |||
100 | info->p_dev = link; | 97 | info->p_dev = link; |
101 | link->priv = info; | 98 | link->priv = info; |
102 | 99 | ||
103 | link->resource[0]->end = 0x20; | 100 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
104 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 101 | link->config_regs = PRESENT_OPTION; |
105 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
106 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
107 | link->conf.Present = PRESENT_OPTION; | ||
108 | 102 | ||
109 | return aha152x_config_cs(link); | 103 | return aha152x_config_cs(link); |
110 | } /* aha152x_attach */ | 104 | } /* aha152x_attach */ |
@@ -123,25 +117,24 @@ static void aha152x_detach(struct pcmcia_device *link) | |||
123 | 117 | ||
124 | /*====================================================================*/ | 118 | /*====================================================================*/ |
125 | 119 | ||
126 | static int aha152x_config_check(struct pcmcia_device *p_dev, | 120 | static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data) |
127 | cistpl_cftable_entry_t *cfg, | ||
128 | cistpl_cftable_entry_t *dflt, | ||
129 | unsigned int vcc, | ||
130 | void *priv_data) | ||
131 | { | 121 | { |
132 | p_dev->io_lines = 10; | 122 | p_dev->io_lines = 10; |
123 | |||
133 | /* For New Media T&J, look for a SCSI window */ | 124 | /* For New Media T&J, look for a SCSI window */ |
134 | if (cfg->io.win[0].len >= 0x20) | 125 | if ((p_dev->resource[0]->end < 0x20) && |
135 | p_dev->resource[0]->start = cfg->io.win[0].base; | 126 | (p_dev->resource[1]->end >= 0x20)) |
136 | else if ((cfg->io.nwin > 1) && | 127 | p_dev->resource[0]->start = p_dev->resource[1]->start; |
137 | (cfg->io.win[1].len >= 0x20)) | 128 | |
138 | p_dev->resource[0]->start = cfg->io.win[1].base; | 129 | if (p_dev->resource[0]->start >= 0xffff) |
139 | if ((cfg->io.nwin > 0) && | 130 | return -EINVAL; |
140 | (p_dev->resource[0]->start < 0xffff)) { | 131 | |
141 | if (!pcmcia_request_io(p_dev)) | 132 | p_dev->resource[1]->start = p_dev->resource[1]->end = 0; |
142 | return 0; | 133 | p_dev->resource[0]->end = 0x20; |
143 | } | 134 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
144 | return -EINVAL; | 135 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
136 | |||
137 | return pcmcia_request_io(p_dev); | ||
145 | } | 138 | } |
146 | 139 | ||
147 | static int aha152x_config_cs(struct pcmcia_device *link) | 140 | static int aha152x_config_cs(struct pcmcia_device *link) |
@@ -160,7 +153,7 @@ static int aha152x_config_cs(struct pcmcia_device *link) | |||
160 | if (!link->irq) | 153 | if (!link->irq) |
161 | goto failed; | 154 | goto failed; |
162 | 155 | ||
163 | ret = pcmcia_request_configuration(link, &link->conf); | 156 | ret = pcmcia_enable_device(link); |
164 | if (ret) | 157 | if (ret) |
165 | goto failed; | 158 | goto failed; |
166 | 159 | ||
@@ -221,9 +214,7 @@ MODULE_DEVICE_TABLE(pcmcia, aha152x_ids); | |||
221 | 214 | ||
222 | static struct pcmcia_driver aha152x_cs_driver = { | 215 | static struct pcmcia_driver aha152x_cs_driver = { |
223 | .owner = THIS_MODULE, | 216 | .owner = THIS_MODULE, |
224 | .drv = { | 217 | .name = "aha152x_cs", |
225 | .name = "aha152x_cs", | ||
226 | }, | ||
227 | .probe = aha152x_probe, | 218 | .probe = aha152x_probe, |
228 | .remove = aha152x_detach, | 219 | .remove = aha152x_detach, |
229 | .id_table = aha152x_ids, | 220 | .id_table = aha152x_ids, |
@@ -238,7 +229,6 @@ static int __init init_aha152x_cs(void) | |||
238 | static void __exit exit_aha152x_cs(void) | 229 | static void __exit exit_aha152x_cs(void) |
239 | { | 230 | { |
240 | pcmcia_unregister_driver(&aha152x_cs_driver); | 231 | pcmcia_unregister_driver(&aha152x_cs_driver); |
241 | BUG_ON(dev_list != NULL); | ||
242 | } | 232 | } |
243 | 233 | ||
244 | module_init(init_aha152x_cs); | 234 | module_init(init_aha152x_cs); |
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 13dbe5c48492..cd69c2670f81 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <scsi/scsi_host.h> | 46 | #include <scsi/scsi_host.h> |
47 | #include "fdomain.h" | 47 | #include "fdomain.h" |
48 | 48 | ||
49 | #include <pcmcia/cs.h> | ||
50 | #include <pcmcia/cistpl.h> | 49 | #include <pcmcia/cistpl.h> |
51 | #include <pcmcia/ds.h> | 50 | #include <pcmcia/ds.h> |
52 | 51 | ||
@@ -83,11 +82,8 @@ static int fdomain_probe(struct pcmcia_device *link) | |||
83 | 82 | ||
84 | info->p_dev = link; | 83 | info->p_dev = link; |
85 | link->priv = info; | 84 | link->priv = info; |
86 | link->resource[0]->end = 0x10; | 85 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
87 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 86 | link->config_regs = PRESENT_OPTION; |
88 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
89 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
90 | link->conf.Present = PRESENT_OPTION; | ||
91 | 87 | ||
92 | return fdomain_config(link); | 88 | return fdomain_config(link); |
93 | } /* fdomain_attach */ | 89 | } /* fdomain_attach */ |
@@ -105,14 +101,12 @@ static void fdomain_detach(struct pcmcia_device *link) | |||
105 | 101 | ||
106 | /*====================================================================*/ | 102 | /*====================================================================*/ |
107 | 103 | ||
108 | static int fdomain_config_check(struct pcmcia_device *p_dev, | 104 | static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data) |
109 | cistpl_cftable_entry_t *cfg, | ||
110 | cistpl_cftable_entry_t *dflt, | ||
111 | unsigned int vcc, | ||
112 | void *priv_data) | ||
113 | { | 105 | { |
114 | p_dev->io_lines = 10; | 106 | p_dev->io_lines = 10; |
115 | p_dev->resource[0]->start = cfg->io.win[0].base; | 107 | p_dev->resource[0]->end = 0x10; |
108 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
109 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
116 | return pcmcia_request_io(p_dev); | 110 | return pcmcia_request_io(p_dev); |
117 | } | 111 | } |
118 | 112 | ||
@@ -132,7 +126,7 @@ static int fdomain_config(struct pcmcia_device *link) | |||
132 | 126 | ||
133 | if (!link->irq) | 127 | if (!link->irq) |
134 | goto failed; | 128 | goto failed; |
135 | ret = pcmcia_request_configuration(link, &link->conf); | 129 | ret = pcmcia_enable_device(link); |
136 | if (ret) | 130 | if (ret) |
137 | goto failed; | 131 | goto failed; |
138 | 132 | ||
@@ -194,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); | |||
194 | 188 | ||
195 | static struct pcmcia_driver fdomain_cs_driver = { | 189 | static struct pcmcia_driver fdomain_cs_driver = { |
196 | .owner = THIS_MODULE, | 190 | .owner = THIS_MODULE, |
197 | .drv = { | 191 | .name = "fdomain_cs", |
198 | .name = "fdomain_cs", | ||
199 | }, | ||
200 | .probe = fdomain_probe, | 192 | .probe = fdomain_probe, |
201 | .remove = fdomain_detach, | 193 | .remove = fdomain_detach, |
202 | .id_table = fdomain_ids, | 194 | .id_table = fdomain_ids, |
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index dd9b40306f3d..9326c2c14880 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <scsi/scsi.h> | 47 | #include <scsi/scsi.h> |
48 | #include <scsi/scsi_ioctl.h> | 48 | #include <scsi/scsi_ioctl.h> |
49 | 49 | ||
50 | #include <pcmcia/cs.h> | ||
51 | #include <pcmcia/cistpl.h> | 50 | #include <pcmcia/cistpl.h> |
52 | #include <pcmcia/cisreg.h> | 51 | #include <pcmcia/cisreg.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
@@ -1531,15 +1530,6 @@ static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt) | |||
1531 | PCMCIA functions | 1530 | PCMCIA functions |
1532 | **********************************************************************/ | 1531 | **********************************************************************/ |
1533 | 1532 | ||
1534 | /*====================================================================== | ||
1535 | nsp_cs_attach() creates an "instance" of the driver, allocating | ||
1536 | local data structures for one device. The device is registered | ||
1537 | with Card Services. | ||
1538 | |||
1539 | The dev_link structure is initialized, but we don't actually | ||
1540 | configure the card at this point -- we wait until we receive a | ||
1541 | card insertion event. | ||
1542 | ======================================================================*/ | ||
1543 | static int nsp_cs_probe(struct pcmcia_device *link) | 1533 | static int nsp_cs_probe(struct pcmcia_device *link) |
1544 | { | 1534 | { |
1545 | scsi_info_t *info; | 1535 | scsi_info_t *info; |
@@ -1557,14 +1547,6 @@ static int nsp_cs_probe(struct pcmcia_device *link) | |||
1557 | 1547 | ||
1558 | nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); | 1548 | nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); |
1559 | 1549 | ||
1560 | /* The io structure describes IO port mapping */ | ||
1561 | link->resource[0]->end = 0x10; | ||
1562 | link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO; | ||
1563 | |||
1564 | /* General socket configuration */ | ||
1565 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
1566 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1567 | |||
1568 | ret = nsp_cs_config(link); | 1550 | ret = nsp_cs_config(link); |
1569 | 1551 | ||
1570 | nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); | 1552 | nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); |
@@ -1572,12 +1554,6 @@ static int nsp_cs_probe(struct pcmcia_device *link) | |||
1572 | } /* nsp_cs_attach */ | 1554 | } /* nsp_cs_attach */ |
1573 | 1555 | ||
1574 | 1556 | ||
1575 | /*====================================================================== | ||
1576 | This deletes a driver "instance". The device is de-registered | ||
1577 | with Card Services. If it has been released, all local data | ||
1578 | structures are freed. Otherwise, the structures will be freed | ||
1579 | when the device is released. | ||
1580 | ======================================================================*/ | ||
1581 | static void nsp_cs_detach(struct pcmcia_device *link) | 1557 | static void nsp_cs_detach(struct pcmcia_device *link) |
1582 | { | 1558 | { |
1583 | nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); | 1559 | nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); |
@@ -1590,98 +1566,36 @@ static void nsp_cs_detach(struct pcmcia_device *link) | |||
1590 | } /* nsp_cs_detach */ | 1566 | } /* nsp_cs_detach */ |
1591 | 1567 | ||
1592 | 1568 | ||
1593 | /*====================================================================== | 1569 | static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) |
1594 | nsp_cs_config() is scheduled to run after a CARD_INSERTION event | ||
1595 | is received, to configure the PCMCIA socket, and to make the | ||
1596 | ethernet device available to the system. | ||
1597 | ======================================================================*/ | ||
1598 | |||
1599 | struct nsp_cs_configdata { | ||
1600 | nsp_hw_data *data; | ||
1601 | win_req_t req; | ||
1602 | }; | ||
1603 | |||
1604 | static int nsp_cs_config_check(struct pcmcia_device *p_dev, | ||
1605 | cistpl_cftable_entry_t *cfg, | ||
1606 | cistpl_cftable_entry_t *dflt, | ||
1607 | unsigned int vcc, | ||
1608 | void *priv_data) | ||
1609 | { | 1570 | { |
1610 | struct nsp_cs_configdata *cfg_mem = priv_data; | 1571 | nsp_hw_data *data = priv_data; |
1611 | 1572 | ||
1612 | if (cfg->index == 0) | 1573 | if (p_dev->config_index == 0) |
1613 | return -ENODEV; | 1574 | return -ENODEV; |
1614 | 1575 | ||
1615 | /* Does this card need audio output? */ | 1576 | /* This reserves IO space but doesn't actually enable it */ |
1616 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | 1577 | if (pcmcia_request_io(p_dev) != 0) |
1617 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | 1578 | goto next_entry; |
1618 | p_dev->conf.Status = CCSR_AUDIO_ENA; | 1579 | |
1619 | } | 1580 | if (resource_size(p_dev->resource[2])) { |
1620 | 1581 | p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 | | |
1621 | /* Use power settings for Vcc and Vpp if present */ | 1582 | WIN_MEMORY_TYPE_CM | |
1622 | /* Note that the CIS values need to be rescaled */ | 1583 | WIN_ENABLE); |
1623 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | 1584 | if (p_dev->resource[2]->end < 0x1000) |
1624 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) | 1585 | p_dev->resource[2]->end = 0x1000; |
1625 | return -ENODEV; | 1586 | if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0) |
1626 | else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) { | 1587 | goto next_entry; |
1627 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000) | 1588 | if (pcmcia_map_mem_page(p_dev, p_dev->resource[2], |
1628 | return -ENODEV; | 1589 | p_dev->card_addr) != 0) |
1629 | } | 1590 | goto next_entry; |
1630 | 1591 | ||
1631 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { | 1592 | data->MmioAddress = (unsigned long) |
1632 | p_dev->conf.Vpp = | 1593 | ioremap_nocache(p_dev->resource[2]->start, |
1633 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 1594 | resource_size(p_dev->resource[2])); |
1634 | } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) { | 1595 | data->MmioLength = resource_size(p_dev->resource[2]); |
1635 | p_dev->conf.Vpp = | ||
1636 | dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
1637 | } | ||
1638 | |||
1639 | /* Do we need to allocate an interrupt? */ | ||
1640 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
1641 | |||
1642 | /* IO window settings */ | ||
1643 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
1644 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
1645 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
1646 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
1647 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
1648 | p_dev->resource[0]->flags |= | ||
1649 | pcmcia_io_cfg_data_width(io->flags); | ||
1650 | p_dev->resource[0]->start = io->win[0].base; | ||
1651 | p_dev->resource[0]->end = io->win[0].len; | ||
1652 | if (io->nwin > 1) { | ||
1653 | p_dev->resource[1]->flags = | ||
1654 | p_dev->resource[0]->flags; | ||
1655 | p_dev->resource[1]->start = io->win[1].base; | ||
1656 | p_dev->resource[1]->end = io->win[1].len; | ||
1657 | } | ||
1658 | /* This reserves IO space but doesn't actually enable it */ | ||
1659 | if (pcmcia_request_io(p_dev) != 0) | ||
1660 | goto next_entry; | ||
1661 | } | ||
1662 | |||
1663 | if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { | ||
1664 | cistpl_mem_t *mem = | ||
1665 | (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; | ||
1666 | cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; | ||
1667 | cfg_mem->req.Attributes |= WIN_ENABLE; | ||
1668 | cfg_mem->req.Base = mem->win[0].host_addr; | ||
1669 | cfg_mem->req.Size = mem->win[0].len; | ||
1670 | if (cfg_mem->req.Size < 0x1000) | ||
1671 | cfg_mem->req.Size = 0x1000; | ||
1672 | cfg_mem->req.AccessSpeed = 0; | ||
1673 | if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0) | ||
1674 | goto next_entry; | ||
1675 | if (pcmcia_map_mem_page(p_dev, p_dev->win, | ||
1676 | mem->win[0].card_addr) != 0) | ||
1677 | goto next_entry; | ||
1678 | |||
1679 | cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size); | ||
1680 | cfg_mem->data->MmioLength = cfg_mem->req.Size; | ||
1681 | } | ||
1682 | /* If we got this far, we're cool! */ | ||
1683 | return 0; | ||
1684 | } | 1596 | } |
1597 | /* If we got this far, we're cool! */ | ||
1598 | return 0; | ||
1685 | 1599 | ||
1686 | next_entry: | 1600 | next_entry: |
1687 | nsp_dbg(NSP_DEBUG_INIT, "next"); | 1601 | nsp_dbg(NSP_DEBUG_INIT, "next"); |
@@ -1693,25 +1607,23 @@ static int nsp_cs_config(struct pcmcia_device *link) | |||
1693 | { | 1607 | { |
1694 | int ret; | 1608 | int ret; |
1695 | scsi_info_t *info = link->priv; | 1609 | scsi_info_t *info = link->priv; |
1696 | struct nsp_cs_configdata *cfg_mem; | ||
1697 | struct Scsi_Host *host; | 1610 | struct Scsi_Host *host; |
1698 | nsp_hw_data *data = &nsp_data_base; | 1611 | nsp_hw_data *data = &nsp_data_base; |
1699 | 1612 | ||
1700 | nsp_dbg(NSP_DEBUG_INIT, "in"); | 1613 | nsp_dbg(NSP_DEBUG_INIT, "in"); |
1701 | 1614 | ||
1702 | cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL); | 1615 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC | |
1703 | if (!cfg_mem) | 1616 | CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM | |
1704 | return -ENOMEM; | 1617 | CONF_AUTO_SET_IO; |
1705 | cfg_mem->data = data; | ||
1706 | 1618 | ||
1707 | ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem); | 1619 | ret = pcmcia_loop_config(link, nsp_cs_config_check, data); |
1708 | if (ret) | 1620 | if (ret) |
1709 | goto cs_failed; | 1621 | goto cs_failed; |
1710 | 1622 | ||
1711 | if (pcmcia_request_irq(link, nspintr)) | 1623 | if (pcmcia_request_irq(link, nspintr)) |
1712 | goto cs_failed; | 1624 | goto cs_failed; |
1713 | 1625 | ||
1714 | ret = pcmcia_request_configuration(link, &link->conf); | 1626 | ret = pcmcia_enable_device(link); |
1715 | if (ret) | 1627 | if (ret) |
1716 | goto cs_failed; | 1628 | goto cs_failed; |
1717 | 1629 | ||
@@ -1754,41 +1666,16 @@ static int nsp_cs_config(struct pcmcia_device *link) | |||
1754 | 1666 | ||
1755 | info->host = host; | 1667 | info->host = host; |
1756 | 1668 | ||
1757 | /* Finally, report what we've done */ | ||
1758 | printk(KERN_INFO "nsp_cs: index 0x%02x: ", | ||
1759 | link->conf.ConfigIndex); | ||
1760 | if (link->conf.Vpp) { | ||
1761 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); | ||
1762 | } | ||
1763 | if (link->conf.Attributes & CONF_ENABLE_IRQ) { | ||
1764 | printk(", irq %d", link->irq); | ||
1765 | } | ||
1766 | if (link->resource[0]) | ||
1767 | printk(", io %pR", link->resource[0]); | ||
1768 | if (link->resource[1]) | ||
1769 | printk(" & %pR", link->resource[1]); | ||
1770 | if (link->win) | ||
1771 | printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base, | ||
1772 | cfg_mem->req.Base+cfg_mem->req.Size-1); | ||
1773 | printk("\n"); | ||
1774 | |||
1775 | kfree(cfg_mem); | ||
1776 | return 0; | 1669 | return 0; |
1777 | 1670 | ||
1778 | cs_failed: | 1671 | cs_failed: |
1779 | nsp_dbg(NSP_DEBUG_INIT, "config fail"); | 1672 | nsp_dbg(NSP_DEBUG_INIT, "config fail"); |
1780 | nsp_cs_release(link); | 1673 | nsp_cs_release(link); |
1781 | kfree(cfg_mem); | ||
1782 | 1674 | ||
1783 | return -ENODEV; | 1675 | return -ENODEV; |
1784 | } /* nsp_cs_config */ | 1676 | } /* nsp_cs_config */ |
1785 | 1677 | ||
1786 | 1678 | ||
1787 | /*====================================================================== | ||
1788 | After a card is removed, nsp_cs_release() will unregister the net | ||
1789 | device, and release the PCMCIA configuration. If the device is | ||
1790 | still open, this will be postponed until it is closed. | ||
1791 | ======================================================================*/ | ||
1792 | static void nsp_cs_release(struct pcmcia_device *link) | 1679 | static void nsp_cs_release(struct pcmcia_device *link) |
1793 | { | 1680 | { |
1794 | scsi_info_t *info = link->priv; | 1681 | scsi_info_t *info = link->priv; |
@@ -1807,7 +1694,7 @@ static void nsp_cs_release(struct pcmcia_device *link) | |||
1807 | scsi_remove_host(info->host); | 1694 | scsi_remove_host(info->host); |
1808 | } | 1695 | } |
1809 | 1696 | ||
1810 | if (link->win) { | 1697 | if (resource_size(link->resource[2])) { |
1811 | if (data != NULL) { | 1698 | if (data != NULL) { |
1812 | iounmap((void *)(data->MmioAddress)); | 1699 | iounmap((void *)(data->MmioAddress)); |
1813 | } | 1700 | } |
@@ -1877,9 +1764,7 @@ MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids); | |||
1877 | 1764 | ||
1878 | static struct pcmcia_driver nsp_driver = { | 1765 | static struct pcmcia_driver nsp_driver = { |
1879 | .owner = THIS_MODULE, | 1766 | .owner = THIS_MODULE, |
1880 | .drv = { | 1767 | .name = "nsp_cs", |
1881 | .name = "nsp_cs", | ||
1882 | }, | ||
1883 | .probe = nsp_cs_probe, | 1768 | .probe = nsp_cs_probe, |
1884 | .remove = nsp_cs_detach, | 1769 | .remove = nsp_cs_detach, |
1885 | .id_table = nsp_cs_ids, | 1770 | .id_table = nsp_cs_ids, |
@@ -1889,14 +1774,11 @@ static struct pcmcia_driver nsp_driver = { | |||
1889 | 1774 | ||
1890 | static int __init nsp_cs_init(void) | 1775 | static int __init nsp_cs_init(void) |
1891 | { | 1776 | { |
1892 | nsp_msg(KERN_INFO, "loading..."); | ||
1893 | |||
1894 | return pcmcia_register_driver(&nsp_driver); | 1777 | return pcmcia_register_driver(&nsp_driver); |
1895 | } | 1778 | } |
1896 | 1779 | ||
1897 | static void __exit nsp_cs_exit(void) | 1780 | static void __exit nsp_cs_exit(void) |
1898 | { | 1781 | { |
1899 | nsp_msg(KERN_INFO, "unloading..."); | ||
1900 | pcmcia_unregister_driver(&nsp_driver); | 1782 | pcmcia_unregister_driver(&nsp_driver); |
1901 | } | 1783 | } |
1902 | 1784 | ||
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index eb775f1a523c..9c96ca889ec9 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include <scsi/scsi_host.h> | 48 | #include <scsi/scsi_host.h> |
49 | #include "../qlogicfas408.h" | 49 | #include "../qlogicfas408.h" |
50 | 50 | ||
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
54 | #include <pcmcia/ciscode.h> | 53 | #include <pcmcia/ciscode.h> |
@@ -156,11 +155,8 @@ static int qlogic_probe(struct pcmcia_device *link) | |||
156 | return -ENOMEM; | 155 | return -ENOMEM; |
157 | info->p_dev = link; | 156 | info->p_dev = link; |
158 | link->priv = info; | 157 | link->priv = info; |
159 | link->resource[0]->end = 16; | 158 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
160 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 159 | link->config_regs = PRESENT_OPTION; |
161 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
162 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
163 | link->conf.Present = PRESENT_OPTION; | ||
164 | 160 | ||
165 | return qlogic_config(link); | 161 | return qlogic_config(link); |
166 | } /* qlogic_attach */ | 162 | } /* qlogic_attach */ |
@@ -178,15 +174,11 @@ static void qlogic_detach(struct pcmcia_device *link) | |||
178 | 174 | ||
179 | /*====================================================================*/ | 175 | /*====================================================================*/ |
180 | 176 | ||
181 | static int qlogic_config_check(struct pcmcia_device *p_dev, | 177 | static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data) |
182 | cistpl_cftable_entry_t *cfg, | ||
183 | cistpl_cftable_entry_t *dflt, | ||
184 | unsigned int vcc, | ||
185 | void *priv_data) | ||
186 | { | 178 | { |
187 | p_dev->io_lines = 10; | 179 | p_dev->io_lines = 10; |
188 | p_dev->resource[0]->start = cfg->io.win[0].base; | 180 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
189 | p_dev->resource[0]->end = cfg->io.win[0].len; | 181 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
190 | 182 | ||
191 | if (p_dev->resource[0]->start == 0) | 183 | if (p_dev->resource[0]->start == 0) |
192 | return -ENODEV; | 184 | return -ENODEV; |
@@ -209,7 +201,7 @@ static int qlogic_config(struct pcmcia_device * link) | |||
209 | if (!link->irq) | 201 | if (!link->irq) |
210 | goto failed; | 202 | goto failed; |
211 | 203 | ||
212 | ret = pcmcia_request_configuration(link, &link->conf); | 204 | ret = pcmcia_enable_device(link); |
213 | if (ret) | 205 | if (ret) |
214 | goto failed; | 206 | goto failed; |
215 | 207 | ||
@@ -264,7 +256,7 @@ static int qlogic_resume(struct pcmcia_device *link) | |||
264 | { | 256 | { |
265 | scsi_info_t *info = link->priv; | 257 | scsi_info_t *info = link->priv; |
266 | 258 | ||
267 | pcmcia_request_configuration(link, &link->conf); | 259 | pcmcia_enable_device(link); |
268 | if ((info->manf_id == MANFID_MACNICA) || | 260 | if ((info->manf_id == MANFID_MACNICA) || |
269 | (info->manf_id == MANFID_PIONEER) || | 261 | (info->manf_id == MANFID_PIONEER) || |
270 | (info->manf_id == 0x0098)) { | 262 | (info->manf_id == 0x0098)) { |
@@ -302,9 +294,7 @@ MODULE_DEVICE_TABLE(pcmcia, qlogic_ids); | |||
302 | 294 | ||
303 | static struct pcmcia_driver qlogic_cs_driver = { | 295 | static struct pcmcia_driver qlogic_cs_driver = { |
304 | .owner = THIS_MODULE, | 296 | .owner = THIS_MODULE, |
305 | .drv = { | ||
306 | .name = "qlogic_cs", | 297 | .name = "qlogic_cs", |
307 | }, | ||
308 | .probe = qlogic_probe, | 298 | .probe = qlogic_probe, |
309 | .remove = qlogic_detach, | 299 | .remove = qlogic_detach, |
310 | .id_table = qlogic_ids, | 300 | .id_table = qlogic_ids, |
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 321e390c9120..0ae27cb5cd6f 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c | |||
@@ -71,7 +71,6 @@ | |||
71 | #include <scsi/scsi.h> | 71 | #include <scsi/scsi.h> |
72 | #include <scsi/scsi_host.h> | 72 | #include <scsi/scsi_host.h> |
73 | 73 | ||
74 | #include <pcmcia/cs.h> | ||
75 | #include <pcmcia/cistpl.h> | 74 | #include <pcmcia/cistpl.h> |
76 | #include <pcmcia/ds.h> | 75 | #include <pcmcia/ds.h> |
77 | #include <pcmcia/ciscode.h> | 76 | #include <pcmcia/ciscode.h> |
@@ -684,15 +683,11 @@ static struct scsi_host_template sym53c500_driver_template = { | |||
684 | .shost_attrs = SYM53C500_shost_attrs | 683 | .shost_attrs = SYM53C500_shost_attrs |
685 | }; | 684 | }; |
686 | 685 | ||
687 | static int SYM53C500_config_check(struct pcmcia_device *p_dev, | 686 | static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data) |
688 | cistpl_cftable_entry_t *cfg, | ||
689 | cistpl_cftable_entry_t *dflt, | ||
690 | unsigned int vcc, | ||
691 | void *priv_data) | ||
692 | { | 687 | { |
693 | p_dev->io_lines = 10; | 688 | p_dev->io_lines = 10; |
694 | p_dev->resource[0]->start = cfg->io.win[0].base; | 689 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
695 | p_dev->resource[0]->end = cfg->io.win[0].len; | 690 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
696 | 691 | ||
697 | if (p_dev->resource[0]->start == 0) | 692 | if (p_dev->resource[0]->start == 0) |
698 | return -ENODEV; | 693 | return -ENODEV; |
@@ -721,7 +716,7 @@ SYM53C500_config(struct pcmcia_device *link) | |||
721 | if (!link->irq) | 716 | if (!link->irq) |
722 | goto failed; | 717 | goto failed; |
723 | 718 | ||
724 | ret = pcmcia_request_configuration(link, &link->conf); | 719 | ret = pcmcia_enable_device(link); |
725 | if (ret) | 720 | if (ret) |
726 | goto failed; | 721 | goto failed; |
727 | 722 | ||
@@ -859,10 +854,7 @@ SYM53C500_probe(struct pcmcia_device *link) | |||
859 | return -ENOMEM; | 854 | return -ENOMEM; |
860 | info->p_dev = link; | 855 | info->p_dev = link; |
861 | link->priv = info; | 856 | link->priv = info; |
862 | link->resource[0]->end = 16; | 857 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
863 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | ||
864 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
865 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
866 | 858 | ||
867 | return SYM53C500_config(link); | 859 | return SYM53C500_config(link); |
868 | } /* SYM53C500_attach */ | 860 | } /* SYM53C500_attach */ |
@@ -881,9 +873,7 @@ MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids); | |||
881 | 873 | ||
882 | static struct pcmcia_driver sym53c500_cs_driver = { | 874 | static struct pcmcia_driver sym53c500_cs_driver = { |
883 | .owner = THIS_MODULE, | 875 | .owner = THIS_MODULE, |
884 | .drv = { | 876 | .name = "sym53c500_cs", |
885 | .name = "sym53c500_cs", | ||
886 | }, | ||
887 | .probe = SYM53C500_probe, | 877 | .probe = SYM53C500_probe, |
888 | .remove = SYM53C500_detach, | 878 | .remove = SYM53C500_detach, |
889 | .id_table = sym53c500_ids, | 879 | .id_table = sym53c500_ids, |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ad0ed212db4a..348fba0a8976 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -1046,13 +1046,13 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, | |||
1046 | 1046 | ||
1047 | /* If the user actually wanted this page, we can skip the rest */ | 1047 | /* If the user actually wanted this page, we can skip the rest */ |
1048 | if (page == 0) | 1048 | if (page == 0) |
1049 | return -EINVAL; | 1049 | return 0; |
1050 | 1050 | ||
1051 | for (i = 0; i < min((int)buf[3], buf_len - 4); i++) | 1051 | for (i = 0; i < min((int)buf[3], buf_len - 4); i++) |
1052 | if (buf[i + 4] == page) | 1052 | if (buf[i + 4] == page) |
1053 | goto found; | 1053 | goto found; |
1054 | 1054 | ||
1055 | if (i < buf[3] && i > buf_len) | 1055 | if (i < buf[3] && i >= buf_len - 4) |
1056 | /* ran off the end of the buffer, give us benefit of doubt */ | 1056 | /* ran off the end of the buffer, give us benefit of doubt */ |
1057 | goto found; | 1057 | goto found; |
1058 | /* The device claims it doesn't support the requested page */ | 1058 | /* The device claims it doesn't support the requested page */ |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 12900f7083b0..3198c5335f0b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -458,6 +458,7 @@ config SERIAL_SAMSUNG_UARTS | |||
458 | int | 458 | int |
459 | depends on ARM && PLAT_SAMSUNG | 459 | depends on ARM && PLAT_SAMSUNG |
460 | default 2 if ARCH_S3C2400 | 460 | default 2 if ARCH_S3C2400 |
461 | default 6 if ARCH_S5P6450 | ||
461 | default 4 if SERIAL_SAMSUNG_UARTS_4 | 462 | default 4 if SERIAL_SAMSUNG_UARTS_4 |
462 | default 3 | 463 | default 3 |
463 | help | 464 | help |
@@ -526,12 +527,12 @@ config SERIAL_S3C24A0 | |||
526 | Serial port support for the Samsung S3C24A0 SoC | 527 | Serial port support for the Samsung S3C24A0 SoC |
527 | 528 | ||
528 | config SERIAL_S3C6400 | 529 | config SERIAL_S3C6400 |
529 | tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support" | 530 | tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" |
530 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100) | 531 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) |
531 | select SERIAL_SAMSUNG_UARTS_4 | 532 | select SERIAL_SAMSUNG_UARTS_4 |
532 | default y | 533 | default y |
533 | help | 534 | help |
534 | Serial port support for the Samsung S3C6400, S3C6410, S5P6440 | 535 | Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 |
535 | and S5PC100 SoCs | 536 | and S5PC100 SoCs |
536 | 537 | ||
537 | config SERIAL_S5PV210 | 538 | config SERIAL_S5PV210 |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 93de907b1208..ee43efc7bdcc 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -2017,6 +2017,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2017 | struct ioc3_port *port; | 2017 | struct ioc3_port *port; |
2018 | struct ioc3_port *ports[PORTS_PER_CARD]; | 2018 | struct ioc3_port *ports[PORTS_PER_CARD]; |
2019 | int phys_port; | 2019 | int phys_port; |
2020 | int cnt; | ||
2020 | 2021 | ||
2021 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd)); | 2022 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd)); |
2022 | 2023 | ||
@@ -2044,6 +2045,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2044 | if (!port) { | 2045 | if (!port) { |
2045 | printk(KERN_WARNING | 2046 | printk(KERN_WARNING |
2046 | "IOC3 serial memory not available for port\n"); | 2047 | "IOC3 serial memory not available for port\n"); |
2048 | ret = -ENOMEM; | ||
2047 | goto out4; | 2049 | goto out4; |
2048 | } | 2050 | } |
2049 | spin_lock_init(&port->ip_lock); | 2051 | spin_lock_init(&port->ip_lock); |
@@ -2146,6 +2148,9 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2146 | 2148 | ||
2147 | /* error exits that give back resources */ | 2149 | /* error exits that give back resources */ |
2148 | out4: | 2150 | out4: |
2151 | for (cnt = 0; cnt < phys_port; cnt++) | ||
2152 | kfree(ports[cnt]); | ||
2153 | |||
2149 | kfree(card_ptr); | 2154 | kfree(card_ptr); |
2150 | return ret; | 2155 | return ret; |
2151 | } | 2156 | } |
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index b1156ba8ad14..7ac2bf5167cd 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -1101,7 +1101,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | |||
1101 | dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); | 1101 | dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); |
1102 | 1102 | ||
1103 | port->mapbase = res->start; | 1103 | port->mapbase = res->start; |
1104 | port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); | 1104 | port->membase = S3C_VA_UART + (res->start & 0xfffff); |
1105 | ret = platform_get_irq(platdev, 0); | 1105 | ret = platform_get_irq(platdev, 0); |
1106 | if (ret < 0) | 1106 | if (ret < 0) |
1107 | port->irq = 0; | 1107 | port->irq = 0; |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7d475b2a79e8..93760b2ea172 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | 47 | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | 48 | #include <pcmcia/cistpl.h> |
50 | #include <pcmcia/ciscode.h> | 49 | #include <pcmcia/ciscode.h> |
51 | #include <pcmcia/ds.h> | 50 | #include <pcmcia/ds.h> |
@@ -183,10 +182,8 @@ static void quirk_config_socket(struct pcmcia_device *link) | |||
183 | { | 182 | { |
184 | struct serial_info *info = link->priv; | 183 | struct serial_info *info = link->priv; |
185 | 184 | ||
186 | if (info->multi) { | 185 | if (info->multi) |
187 | link->conf.Present |= PRESENT_EXT_STATUS; | 186 | link->config_flags |= CONF_ENABLE_ESR; |
188 | link->conf.ExtStatus = ESR_REQ_ATTN_ENA; | ||
189 | } | ||
190 | } | 187 | } |
191 | 188 | ||
192 | static const struct serial_quirk quirks[] = { | 189 | static const struct serial_quirk quirks[] = { |
@@ -265,13 +262,6 @@ static const struct serial_quirk quirks[] = { | |||
265 | static int serial_config(struct pcmcia_device * link); | 262 | static int serial_config(struct pcmcia_device * link); |
266 | 263 | ||
267 | 264 | ||
268 | /*====================================================================== | ||
269 | |||
270 | After a card is removed, serial_remove() will unregister | ||
271 | the serial device(s), and release the PCMCIA configuration. | ||
272 | |||
273 | ======================================================================*/ | ||
274 | |||
275 | static void serial_remove(struct pcmcia_device *link) | 265 | static void serial_remove(struct pcmcia_device *link) |
276 | { | 266 | { |
277 | struct serial_info *info = link->priv; | 267 | struct serial_info *info = link->priv; |
@@ -314,14 +304,6 @@ static int serial_resume(struct pcmcia_device *link) | |||
314 | return 0; | 304 | return 0; |
315 | } | 305 | } |
316 | 306 | ||
317 | /*====================================================================== | ||
318 | |||
319 | serial_attach() creates an "instance" of the driver, allocating | ||
320 | local data structures for one device. The device is registered | ||
321 | with Card Services. | ||
322 | |||
323 | ======================================================================*/ | ||
324 | |||
325 | static int serial_probe(struct pcmcia_device *link) | 307 | static int serial_probe(struct pcmcia_device *link) |
326 | { | 308 | { |
327 | struct serial_info *info; | 309 | struct serial_info *info; |
@@ -335,25 +317,13 @@ static int serial_probe(struct pcmcia_device *link) | |||
335 | info->p_dev = link; | 317 | info->p_dev = link; |
336 | link->priv = info; | 318 | link->priv = info; |
337 | 319 | ||
338 | link->conf.Attributes = CONF_ENABLE_IRQ; | 320 | link->config_flags |= CONF_ENABLE_IRQ; |
339 | if (do_sound) { | 321 | if (do_sound) |
340 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 322 | link->config_flags |= CONF_ENABLE_SPKR; |
341 | link->conf.Status = CCSR_AUDIO_ENA; | ||
342 | } | ||
343 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
344 | 323 | ||
345 | return serial_config(link); | 324 | return serial_config(link); |
346 | } | 325 | } |
347 | 326 | ||
348 | /*====================================================================== | ||
349 | |||
350 | This deletes a driver "instance". The device is de-registered | ||
351 | with Card Services. If it has been released, all local data | ||
352 | structures are freed. Otherwise, the structures will be freed | ||
353 | when the device is released. | ||
354 | |||
355 | ======================================================================*/ | ||
356 | |||
357 | static void serial_detach(struct pcmcia_device *link) | 327 | static void serial_detach(struct pcmcia_device *link) |
358 | { | 328 | { |
359 | struct serial_info *info = link->priv; | 329 | struct serial_info *info = link->priv; |
@@ -361,11 +331,6 @@ static void serial_detach(struct pcmcia_device *link) | |||
361 | dev_dbg(&link->dev, "serial_detach\n"); | 331 | dev_dbg(&link->dev, "serial_detach\n"); |
362 | 332 | ||
363 | /* | 333 | /* |
364 | * Ensure any outstanding scheduled tasks are completed. | ||
365 | */ | ||
366 | flush_scheduled_work(); | ||
367 | |||
368 | /* | ||
369 | * Ensure that the ports have been released. | 334 | * Ensure that the ports have been released. |
370 | */ | 335 | */ |
371 | serial_remove(link); | 336 | serial_remove(link); |
@@ -430,47 +395,45 @@ static int pfc_config(struct pcmcia_device *p_dev) | |||
430 | return -ENODEV; | 395 | return -ENODEV; |
431 | } | 396 | } |
432 | 397 | ||
433 | static int simple_config_check(struct pcmcia_device *p_dev, | 398 | static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data) |
434 | cistpl_cftable_entry_t *cf, | ||
435 | cistpl_cftable_entry_t *dflt, | ||
436 | unsigned int vcc, | ||
437 | void *priv_data) | ||
438 | { | 399 | { |
439 | static const int size_table[2] = { 8, 16 }; | 400 | static const int size_table[2] = { 8, 16 }; |
440 | int *try = priv_data; | 401 | int *try = priv_data; |
441 | 402 | ||
442 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 403 | if (p_dev->resource[0]->start == 0) |
443 | p_dev->conf.Vpp = | 404 | return -ENODEV; |
444 | cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
445 | 405 | ||
446 | p_dev->io_lines = ((*try & 0x1) == 0) ? | 406 | if ((*try & 0x1) == 0) |
447 | 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | 407 | p_dev->io_lines = 16; |
448 | 408 | ||
449 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)]) | 409 | if (p_dev->resource[0]->end != size_table[(*try >> 1)]) |
450 | && (cf->io.win[0].base != 0)) { | 410 | return -ENODEV; |
451 | p_dev->resource[0]->start = cf->io.win[0].base; | 411 | |
452 | if (!pcmcia_request_io(p_dev)) | 412 | p_dev->resource[0]->end = 8; |
453 | return 0; | 413 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
454 | } | 414 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
455 | return -EINVAL; | 415 | |
416 | return pcmcia_request_io(p_dev); | ||
456 | } | 417 | } |
457 | 418 | ||
458 | static int simple_config_check_notpicky(struct pcmcia_device *p_dev, | 419 | static int simple_config_check_notpicky(struct pcmcia_device *p_dev, |
459 | cistpl_cftable_entry_t *cf, | ||
460 | cistpl_cftable_entry_t *dflt, | ||
461 | unsigned int vcc, | ||
462 | void *priv_data) | 420 | void *priv_data) |
463 | { | 421 | { |
464 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | 422 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
465 | int j; | 423 | int j; |
466 | 424 | ||
467 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | 425 | if (p_dev->io_lines > 3) |
468 | for (j = 0; j < 5; j++) { | 426 | return -ENODEV; |
469 | p_dev->resource[0]->start = base[j]; | 427 | |
470 | p_dev->io_lines = base[j] ? 16 : 3; | 428 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
471 | if (!pcmcia_request_io(p_dev)) | 429 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
472 | return 0; | 430 | p_dev->resource[0]->end = 8; |
473 | } | 431 | |
432 | for (j = 0; j < 5; j++) { | ||
433 | p_dev->resource[0]->start = base[j]; | ||
434 | p_dev->io_lines = base[j] ? 16 : 3; | ||
435 | if (!pcmcia_request_io(p_dev)) | ||
436 | return 0; | ||
474 | } | 437 | } |
475 | return -ENODEV; | 438 | return -ENODEV; |
476 | } | 439 | } |
@@ -480,11 +443,9 @@ static int simple_config(struct pcmcia_device *link) | |||
480 | struct serial_info *info = link->priv; | 443 | struct serial_info *info = link->priv; |
481 | int i = -ENODEV, try; | 444 | int i = -ENODEV, try; |
482 | 445 | ||
483 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
484 | link->resource[0]->end = 8; | ||
485 | |||
486 | /* First pass: look for a config entry that looks normal. | 446 | /* First pass: look for a config entry that looks normal. |
487 | * Two tries: without IO aliases, then with aliases */ | 447 | * Two tries: without IO aliases, then with aliases */ |
448 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO; | ||
488 | for (try = 0; try < 4; try++) | 449 | for (try = 0; try < 4; try++) |
489 | if (!pcmcia_loop_config(link, simple_config_check, &try)) | 450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) |
490 | goto found_port; | 451 | goto found_port; |
@@ -500,7 +461,7 @@ static int simple_config(struct pcmcia_device *link) | |||
500 | 461 | ||
501 | found_port: | 462 | found_port: |
502 | if (info->multi && (info->manfid == MANFID_3COM)) | 463 | if (info->multi && (info->manfid == MANFID_3COM)) |
503 | link->conf.ConfigIndex &= ~(0x08); | 464 | link->config_index &= ~(0x08); |
504 | 465 | ||
505 | /* | 466 | /* |
506 | * Apply any configuration quirks. | 467 | * Apply any configuration quirks. |
@@ -508,51 +469,50 @@ found_port: | |||
508 | if (info->quirk && info->quirk->config) | 469 | if (info->quirk && info->quirk->config) |
509 | info->quirk->config(link); | 470 | info->quirk->config(link); |
510 | 471 | ||
511 | i = pcmcia_request_configuration(link, &link->conf); | 472 | i = pcmcia_enable_device(link); |
512 | if (i != 0) | 473 | if (i != 0) |
513 | return -1; | 474 | return -1; |
514 | return setup_serial(link, info, link->resource[0]->start, link->irq); | 475 | return setup_serial(link, info, link->resource[0]->start, link->irq); |
515 | } | 476 | } |
516 | 477 | ||
517 | static int multi_config_check(struct pcmcia_device *p_dev, | 478 | static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data) |
518 | cistpl_cftable_entry_t *cf, | ||
519 | cistpl_cftable_entry_t *dflt, | ||
520 | unsigned int vcc, | ||
521 | void *priv_data) | ||
522 | { | 479 | { |
523 | int *base2 = priv_data; | 480 | int *multi = priv_data; |
481 | |||
482 | if (p_dev->resource[1]->end) | ||
483 | return -EINVAL; | ||
524 | 484 | ||
525 | /* The quad port cards have bad CIS's, so just look for a | 485 | /* The quad port cards have bad CIS's, so just look for a |
526 | window larger than 8 ports and assume it will be right */ | 486 | window larger than 8 ports and assume it will be right */ |
527 | if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { | 487 | if (p_dev->resource[0]->end <= 8) |
528 | p_dev->resource[0]->start = cf->io.win[0].base; | 488 | return -EINVAL; |
529 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 489 | |
530 | if (!pcmcia_request_io(p_dev)) { | 490 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
531 | *base2 = p_dev->resource[0]->start + 8; | 491 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
532 | return 0; | 492 | p_dev->resource[0]->end = *multi * 8; |
533 | } | 493 | |
534 | } | 494 | if (pcmcia_request_io(p_dev)) |
535 | return -ENODEV; | 495 | return -ENODEV; |
496 | return 0; | ||
536 | } | 497 | } |
537 | 498 | ||
538 | static int multi_config_check_notpicky(struct pcmcia_device *p_dev, | 499 | static int multi_config_check_notpicky(struct pcmcia_device *p_dev, |
539 | cistpl_cftable_entry_t *cf, | ||
540 | cistpl_cftable_entry_t *dflt, | ||
541 | unsigned int vcc, | ||
542 | void *priv_data) | 500 | void *priv_data) |
543 | { | 501 | { |
544 | int *base2 = priv_data; | 502 | int *base2 = priv_data; |
545 | 503 | ||
546 | if (cf->io.nwin == 2) { | 504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end) |
547 | p_dev->resource[0]->start = cf->io.win[0].base; | 505 | return -ENODEV; |
548 | p_dev->resource[1]->start = cf->io.win[1].base; | 506 | |
549 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 507 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; |
550 | if (!pcmcia_request_io(p_dev)) { | 508 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
551 | *base2 = p_dev->resource[1]->start; | 509 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
552 | return 0; | 510 | |
553 | } | 511 | if (pcmcia_request_io(p_dev)) |
554 | } | 512 | return -ENODEV; |
555 | return -ENODEV; | 513 | |
514 | *base2 = p_dev->resource[0]->start + 8; | ||
515 | return 0; | ||
556 | } | 516 | } |
557 | 517 | ||
558 | static int multi_config(struct pcmcia_device *link) | 518 | static int multi_config(struct pcmcia_device *link) |
@@ -560,12 +520,12 @@ static int multi_config(struct pcmcia_device *link) | |||
560 | struct serial_info *info = link->priv; | 520 | struct serial_info *info = link->priv; |
561 | int i, base2 = 0; | 521 | int i, base2 = 0; |
562 | 522 | ||
523 | link->config_flags |= CONF_AUTO_SET_IO; | ||
563 | /* First, look for a generic full-sized window */ | 524 | /* First, look for a generic full-sized window */ |
564 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) |
565 | link->resource[0]->end = info->multi * 8; | 526 | base2 = link->resource[0]->start + 8; |
566 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { | 527 | else { |
567 | /* If that didn't work, look for two windows */ | 528 | /* If that didn't work, look for two windows */ |
568 | link->resource[0]->end = link->resource[1]->end = 8; | ||
569 | info->multi = 2; | 529 | info->multi = 2; |
570 | if (pcmcia_loop_config(link, multi_config_check_notpicky, | 530 | if (pcmcia_loop_config(link, multi_config_check_notpicky, |
571 | &base2)) { | 531 | &base2)) { |
@@ -584,7 +544,7 @@ static int multi_config(struct pcmcia_device *link) | |||
584 | if (info->quirk && info->quirk->config) | 544 | if (info->quirk && info->quirk->config) |
585 | info->quirk->config(link); | 545 | info->quirk->config(link); |
586 | 546 | ||
587 | i = pcmcia_request_configuration(link, &link->conf); | 547 | i = pcmcia_enable_device(link); |
588 | if (i != 0) | 548 | if (i != 0) |
589 | return -ENODEV; | 549 | return -ENODEV; |
590 | 550 | ||
@@ -596,11 +556,11 @@ static int multi_config(struct pcmcia_device *link) | |||
596 | info->prodid == PRODID_POSSIO_GCC)) { | 556 | info->prodid == PRODID_POSSIO_GCC)) { |
597 | int err; | 557 | int err; |
598 | 558 | ||
599 | if (link->conf.ConfigIndex == 1 || | 559 | if (link->config_index == 1 || |
600 | link->conf.ConfigIndex == 3) { | 560 | link->config_index == 3) { |
601 | err = setup_serial(link, info, base2, | 561 | err = setup_serial(link, info, base2, |
602 | link->irq); | 562 | link->irq); |
603 | base2 = link->resource[0]->start;; | 563 | base2 = link->resource[0]->start; |
604 | } else { | 564 | } else { |
605 | err = setup_serial(link, info, link->resource[0]->start, | 565 | err = setup_serial(link, info, link->resource[0]->start, |
606 | link->irq); | 566 | link->irq); |
@@ -624,33 +584,24 @@ static int multi_config(struct pcmcia_device *link) | |||
624 | return 0; | 584 | return 0; |
625 | } | 585 | } |
626 | 586 | ||
627 | static int serial_check_for_multi(struct pcmcia_device *p_dev, | 587 | static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data) |
628 | cistpl_cftable_entry_t *cf, | ||
629 | cistpl_cftable_entry_t *dflt, | ||
630 | unsigned int vcc, | ||
631 | void *priv_data) | ||
632 | { | 588 | { |
633 | struct serial_info *info = p_dev->priv; | 589 | struct serial_info *info = p_dev->priv; |
634 | 590 | ||
635 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | 591 | if (!p_dev->resource[0]->end) |
636 | info->multi = cf->io.win[0].len >> 3; | 592 | return -EINVAL; |
593 | |||
594 | if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0)) | ||
595 | info->multi = p_dev->resource[0]->end >> 3; | ||
637 | 596 | ||
638 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | 597 | if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8) |
639 | (cf->io.win[1].len == 8)) | 598 | && (p_dev->resource[1]->end == 8)) |
640 | info->multi = 2; | 599 | info->multi = 2; |
641 | 600 | ||
642 | return 0; /* break */ | 601 | return 0; /* break */ |
643 | } | 602 | } |
644 | 603 | ||
645 | 604 | ||
646 | /*====================================================================== | ||
647 | |||
648 | serial_config() is scheduled to run after a CARD_INSERTION event | ||
649 | is received, to configure the PCMCIA socket, and to make the | ||
650 | serial device available to the system. | ||
651 | |||
652 | ======================================================================*/ | ||
653 | |||
654 | static int serial_config(struct pcmcia_device * link) | 605 | static int serial_config(struct pcmcia_device * link) |
655 | { | 606 | { |
656 | struct serial_info *info = link->priv; | 607 | struct serial_info *info = link->priv; |
@@ -894,9 +845,7 @@ MODULE_FIRMWARE("cis/RS-COM-2P.cis"); | |||
894 | 845 | ||
895 | static struct pcmcia_driver serial_cs_driver = { | 846 | static struct pcmcia_driver serial_cs_driver = { |
896 | .owner = THIS_MODULE, | 847 | .owner = THIS_MODULE, |
897 | .drv = { | 848 | .name = "serial_cs", |
898 | .name = "serial_cs", | ||
899 | }, | ||
900 | .probe = serial_probe, | 849 | .probe = serial_probe, |
901 | .remove = serial_detach, | 850 | .remove = serial_detach, |
902 | .id_table = serial_ids, | 851 | .id_table = serial_ids, |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 91c2f4f3af10..4b9eec68fad6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -143,10 +143,26 @@ config SPI_GPIO | |||
143 | GPIO operations, you should be able to leverage that for better | 143 | GPIO operations, you should be able to leverage that for better |
144 | speed with a custom version of this driver; see the source code. | 144 | speed with a custom version of this driver; see the source code. |
145 | 145 | ||
146 | config SPI_IMX_VER_IMX1 | ||
147 | def_bool y if SOC_IMX1 | ||
148 | |||
149 | config SPI_IMX_VER_0_0 | ||
150 | def_bool y if SOC_IMX21 || SOC_IMX27 | ||
151 | |||
152 | config SPI_IMX_VER_0_4 | ||
153 | def_bool y if ARCH_MX31 | ||
154 | |||
155 | config SPI_IMX_VER_0_7 | ||
156 | def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51 | ||
157 | |||
158 | config SPI_IMX_VER_2_3 | ||
159 | def_bool y if ARCH_MX51 | ||
160 | |||
146 | config SPI_IMX | 161 | config SPI_IMX |
147 | tristate "Freescale i.MX SPI controllers" | 162 | tristate "Freescale i.MX SPI controllers" |
148 | depends on ARCH_MXC | 163 | depends on ARCH_MXC |
149 | select SPI_BITBANG | 164 | select SPI_BITBANG |
165 | default m if IMX_HAVE_PLATFORM_SPI_IMX | ||
150 | help | 166 | help |
151 | This enables using the Freescale i.MX SPI controllers in master | 167 | This enables using the Freescale i.MX SPI controllers in master |
152 | mode. | 168 | mode. |
@@ -182,12 +198,27 @@ config SPI_MPC512x_PSC | |||
182 | This enables using the Freescale MPC5121 Programmable Serial | 198 | This enables using the Freescale MPC5121 Programmable Serial |
183 | Controller in SPI master mode. | 199 | Controller in SPI master mode. |
184 | 200 | ||
185 | config SPI_MPC8xxx | 201 | config SPI_FSL_LIB |
186 | tristate "Freescale MPC8xxx SPI controller" | 202 | tristate |
203 | depends on FSL_SOC | ||
204 | |||
205 | config SPI_FSL_SPI | ||
206 | tristate "Freescale SPI controller" | ||
187 | depends on FSL_SOC | 207 | depends on FSL_SOC |
208 | select SPI_FSL_LIB | ||
188 | help | 209 | help |
189 | This enables using the Freescale MPC8xxx SPI controllers in master | 210 | This enables using the Freescale SPI controllers in master mode. |
190 | mode. | 211 | MPC83xx platform uses the controller in cpu mode or CPM/QE mode. |
212 | MPC8569 uses the controller in QE mode, MPC8610 in cpu mode. | ||
213 | |||
214 | config SPI_FSL_ESPI | ||
215 | tristate "Freescale eSPI controller" | ||
216 | depends on FSL_SOC | ||
217 | select SPI_FSL_LIB | ||
218 | help | ||
219 | This enables using the Freescale eSPI controllers in master mode. | ||
220 | From MPC8536, 85xx platform uses the controller, and all P10xx, | ||
221 | P20xx, P30xx,P40xx, P50xx uses this controller. | ||
191 | 222 | ||
192 | config SPI_OMAP_UWIRE | 223 | config SPI_OMAP_UWIRE |
193 | tristate "OMAP1 MicroWire" | 224 | tristate "OMAP1 MicroWire" |
@@ -298,6 +329,13 @@ config SPI_STMP3XXX | |||
298 | help | 329 | help |
299 | SPI driver for Freescale STMP37xx/378x SoC SSP interface | 330 | SPI driver for Freescale STMP37xx/378x SoC SSP interface |
300 | 331 | ||
332 | config SPI_TOPCLIFF_PCH | ||
333 | tristate "Topcliff PCH SPI Controller" | ||
334 | depends on PCI | ||
335 | help | ||
336 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus | ||
337 | used in some x86 embedded processors. | ||
338 | |||
301 | config SPI_TXX9 | 339 | config SPI_TXX9 |
302 | tristate "Toshiba TXx9 SPI controller" | 340 | tristate "Toshiba TXx9 SPI controller" |
303 | depends on GENERIC_GPIO && CPU_TX49XX | 341 | depends on GENERIC_GPIO && CPU_TX49XX |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index e9cbd18217a0..557aaadf56b2 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -2,9 +2,7 @@ | |||
2 | # Makefile for kernel SPI drivers. | 2 | # Makefile for kernel SPI drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifeq ($(CONFIG_SPI_DEBUG),y) | 5 | ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG |
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | 6 | ||
9 | # small core, mostly translating board-specific | 7 | # small core, mostly translating board-specific |
10 | # config declarations into driver model code | 8 | # config declarations into driver model code |
@@ -34,11 +32,14 @@ obj-$(CONFIG_SPI_PL022) += amba-pl022.o | |||
34 | obj-$(CONFIG_SPI_MPC512x_PSC) += mpc512x_psc_spi.o | 32 | obj-$(CONFIG_SPI_MPC512x_PSC) += mpc512x_psc_spi.o |
35 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o | 33 | obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o |
36 | obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o | 34 | obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o |
37 | obj-$(CONFIG_SPI_MPC8xxx) += spi_mpc8xxx.o | 35 | obj-$(CONFIG_SPI_FSL_LIB) += spi_fsl_lib.o |
36 | obj-$(CONFIG_SPI_FSL_ESPI) += spi_fsl_espi.o | ||
37 | obj-$(CONFIG_SPI_FSL_SPI) += spi_fsl_spi.o | ||
38 | obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o | 38 | obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o |
39 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | 39 | obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o |
40 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o | 40 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o |
41 | obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o | 41 | obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o |
42 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o | ||
42 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 43 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
43 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 44 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
44 | obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o | 45 | obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 4c37c4e28647..fb3d1b31772d 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -27,7 +27,6 @@ | |||
27 | /* | 27 | /* |
28 | * TODO: | 28 | * TODO: |
29 | * - add timeout on polled transfers | 29 | * - add timeout on polled transfers |
30 | * - add generic DMA framework support | ||
31 | */ | 30 | */ |
32 | 31 | ||
33 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -45,6 +44,9 @@ | |||
45 | #include <linux/amba/pl022.h> | 44 | #include <linux/amba/pl022.h> |
46 | #include <linux/io.h> | 45 | #include <linux/io.h> |
47 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <linux/dmaengine.h> | ||
48 | #include <linux/dma-mapping.h> | ||
49 | #include <linux/scatterlist.h> | ||
48 | 50 | ||
49 | /* | 51 | /* |
50 | * This macro is used to define some register default values. | 52 | * This macro is used to define some register default values. |
@@ -381,6 +383,14 @@ struct pl022 { | |||
381 | enum ssp_reading read; | 383 | enum ssp_reading read; |
382 | enum ssp_writing write; | 384 | enum ssp_writing write; |
383 | u32 exp_fifo_level; | 385 | u32 exp_fifo_level; |
386 | /* DMA settings */ | ||
387 | #ifdef CONFIG_DMA_ENGINE | ||
388 | struct dma_chan *dma_rx_channel; | ||
389 | struct dma_chan *dma_tx_channel; | ||
390 | struct sg_table sgt_rx; | ||
391 | struct sg_table sgt_tx; | ||
392 | char *dummypage; | ||
393 | #endif | ||
384 | }; | 394 | }; |
385 | 395 | ||
386 | /** | 396 | /** |
@@ -406,7 +416,7 @@ struct chip_data { | |||
406 | u16 dmacr; | 416 | u16 dmacr; |
407 | u16 cpsr; | 417 | u16 cpsr; |
408 | u8 n_bytes; | 418 | u8 n_bytes; |
409 | u8 enable_dma:1; | 419 | bool enable_dma; |
410 | enum ssp_reading read; | 420 | enum ssp_reading read; |
411 | enum ssp_writing write; | 421 | enum ssp_writing write; |
412 | void (*cs_control) (u32 command); | 422 | void (*cs_control) (u32 command); |
@@ -763,6 +773,371 @@ static void *next_transfer(struct pl022 *pl022) | |||
763 | } | 773 | } |
764 | return STATE_DONE; | 774 | return STATE_DONE; |
765 | } | 775 | } |
776 | |||
777 | /* | ||
778 | * This DMA functionality is only compiled in if we have | ||
779 | * access to the generic DMA devices/DMA engine. | ||
780 | */ | ||
781 | #ifdef CONFIG_DMA_ENGINE | ||
782 | static void unmap_free_dma_scatter(struct pl022 *pl022) | ||
783 | { | ||
784 | /* Unmap and free the SG tables */ | ||
785 | dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl, | ||
786 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | ||
787 | dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl, | ||
788 | pl022->sgt_rx.nents, DMA_FROM_DEVICE); | ||
789 | sg_free_table(&pl022->sgt_rx); | ||
790 | sg_free_table(&pl022->sgt_tx); | ||
791 | } | ||
792 | |||
793 | static void dma_callback(void *data) | ||
794 | { | ||
795 | struct pl022 *pl022 = data; | ||
796 | struct spi_message *msg = pl022->cur_msg; | ||
797 | |||
798 | BUG_ON(!pl022->sgt_rx.sgl); | ||
799 | |||
800 | #ifdef VERBOSE_DEBUG | ||
801 | /* | ||
802 | * Optionally dump out buffers to inspect contents, this is | ||
803 | * good if you want to convince yourself that the loopback | ||
804 | * read/write contents are the same, when adopting to a new | ||
805 | * DMA engine. | ||
806 | */ | ||
807 | { | ||
808 | struct scatterlist *sg; | ||
809 | unsigned int i; | ||
810 | |||
811 | dma_sync_sg_for_cpu(&pl022->adev->dev, | ||
812 | pl022->sgt_rx.sgl, | ||
813 | pl022->sgt_rx.nents, | ||
814 | DMA_FROM_DEVICE); | ||
815 | |||
816 | for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) { | ||
817 | dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i); | ||
818 | print_hex_dump(KERN_ERR, "SPI RX: ", | ||
819 | DUMP_PREFIX_OFFSET, | ||
820 | 16, | ||
821 | 1, | ||
822 | sg_virt(sg), | ||
823 | sg_dma_len(sg), | ||
824 | 1); | ||
825 | } | ||
826 | for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) { | ||
827 | dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i); | ||
828 | print_hex_dump(KERN_ERR, "SPI TX: ", | ||
829 | DUMP_PREFIX_OFFSET, | ||
830 | 16, | ||
831 | 1, | ||
832 | sg_virt(sg), | ||
833 | sg_dma_len(sg), | ||
834 | 1); | ||
835 | } | ||
836 | } | ||
837 | #endif | ||
838 | |||
839 | unmap_free_dma_scatter(pl022); | ||
840 | |||
841 | /* Update total bytes transfered */ | ||
842 | msg->actual_length += pl022->cur_transfer->len; | ||
843 | if (pl022->cur_transfer->cs_change) | ||
844 | pl022->cur_chip-> | ||
845 | cs_control(SSP_CHIP_DESELECT); | ||
846 | |||
847 | /* Move to next transfer */ | ||
848 | msg->state = next_transfer(pl022); | ||
849 | tasklet_schedule(&pl022->pump_transfers); | ||
850 | } | ||
851 | |||
852 | static void setup_dma_scatter(struct pl022 *pl022, | ||
853 | void *buffer, | ||
854 | unsigned int length, | ||
855 | struct sg_table *sgtab) | ||
856 | { | ||
857 | struct scatterlist *sg; | ||
858 | int bytesleft = length; | ||
859 | void *bufp = buffer; | ||
860 | int mapbytes; | ||
861 | int i; | ||
862 | |||
863 | if (buffer) { | ||
864 | for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { | ||
865 | /* | ||
866 | * If there are less bytes left than what fits | ||
867 | * in the current page (plus page alignment offset) | ||
868 | * we just feed in this, else we stuff in as much | ||
869 | * as we can. | ||
870 | */ | ||
871 | if (bytesleft < (PAGE_SIZE - offset_in_page(bufp))) | ||
872 | mapbytes = bytesleft; | ||
873 | else | ||
874 | mapbytes = PAGE_SIZE - offset_in_page(bufp); | ||
875 | sg_set_page(sg, virt_to_page(bufp), | ||
876 | mapbytes, offset_in_page(bufp)); | ||
877 | bufp += mapbytes; | ||
878 | bytesleft -= mapbytes; | ||
879 | dev_dbg(&pl022->adev->dev, | ||
880 | "set RX/TX target page @ %p, %d bytes, %d left\n", | ||
881 | bufp, mapbytes, bytesleft); | ||
882 | } | ||
883 | } else { | ||
884 | /* Map the dummy buffer on every page */ | ||
885 | for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { | ||
886 | if (bytesleft < PAGE_SIZE) | ||
887 | mapbytes = bytesleft; | ||
888 | else | ||
889 | mapbytes = PAGE_SIZE; | ||
890 | sg_set_page(sg, virt_to_page(pl022->dummypage), | ||
891 | mapbytes, 0); | ||
892 | bytesleft -= mapbytes; | ||
893 | dev_dbg(&pl022->adev->dev, | ||
894 | "set RX/TX to dummy page %d bytes, %d left\n", | ||
895 | mapbytes, bytesleft); | ||
896 | |||
897 | } | ||
898 | } | ||
899 | BUG_ON(bytesleft); | ||
900 | } | ||
901 | |||
902 | /** | ||
903 | * configure_dma - configures the channels for the next transfer | ||
904 | * @pl022: SSP driver's private data structure | ||
905 | */ | ||
906 | static int configure_dma(struct pl022 *pl022) | ||
907 | { | ||
908 | struct dma_slave_config rx_conf = { | ||
909 | .src_addr = SSP_DR(pl022->phybase), | ||
910 | .direction = DMA_FROM_DEVICE, | ||
911 | .src_maxburst = pl022->vendor->fifodepth >> 1, | ||
912 | }; | ||
913 | struct dma_slave_config tx_conf = { | ||
914 | .dst_addr = SSP_DR(pl022->phybase), | ||
915 | .direction = DMA_TO_DEVICE, | ||
916 | .dst_maxburst = pl022->vendor->fifodepth >> 1, | ||
917 | }; | ||
918 | unsigned int pages; | ||
919 | int ret; | ||
920 | int sglen; | ||
921 | struct dma_chan *rxchan = pl022->dma_rx_channel; | ||
922 | struct dma_chan *txchan = pl022->dma_tx_channel; | ||
923 | struct dma_async_tx_descriptor *rxdesc; | ||
924 | struct dma_async_tx_descriptor *txdesc; | ||
925 | dma_cookie_t cookie; | ||
926 | |||
927 | /* Check that the channels are available */ | ||
928 | if (!rxchan || !txchan) | ||
929 | return -ENODEV; | ||
930 | |||
931 | switch (pl022->read) { | ||
932 | case READING_NULL: | ||
933 | /* Use the same as for writing */ | ||
934 | rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
935 | break; | ||
936 | case READING_U8: | ||
937 | rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
938 | break; | ||
939 | case READING_U16: | ||
940 | rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
941 | break; | ||
942 | case READING_U32: | ||
943 | rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
944 | break; | ||
945 | } | ||
946 | |||
947 | switch (pl022->write) { | ||
948 | case WRITING_NULL: | ||
949 | /* Use the same as for reading */ | ||
950 | tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
951 | break; | ||
952 | case WRITING_U8: | ||
953 | tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
954 | break; | ||
955 | case WRITING_U16: | ||
956 | tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
957 | break; | ||
958 | case WRITING_U32: | ||
959 | tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;; | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | /* SPI pecularity: we need to read and write the same width */ | ||
964 | if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) | ||
965 | rx_conf.src_addr_width = tx_conf.dst_addr_width; | ||
966 | if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) | ||
967 | tx_conf.dst_addr_width = rx_conf.src_addr_width; | ||
968 | BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); | ||
969 | |||
970 | rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, | ||
971 | (unsigned long) &rx_conf); | ||
972 | txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, | ||
973 | (unsigned long) &tx_conf); | ||
974 | |||
975 | /* Create sglists for the transfers */ | ||
976 | pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; | ||
977 | dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages); | ||
978 | |||
979 | ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL); | ||
980 | if (ret) | ||
981 | goto err_alloc_rx_sg; | ||
982 | |||
983 | ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL); | ||
984 | if (ret) | ||
985 | goto err_alloc_tx_sg; | ||
986 | |||
987 | /* Fill in the scatterlists for the RX+TX buffers */ | ||
988 | setup_dma_scatter(pl022, pl022->rx, | ||
989 | pl022->cur_transfer->len, &pl022->sgt_rx); | ||
990 | setup_dma_scatter(pl022, pl022->tx, | ||
991 | pl022->cur_transfer->len, &pl022->sgt_tx); | ||
992 | |||
993 | /* Map DMA buffers */ | ||
994 | sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl, | ||
995 | pl022->sgt_rx.nents, DMA_FROM_DEVICE); | ||
996 | if (!sglen) | ||
997 | goto err_rx_sgmap; | ||
998 | |||
999 | sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl, | ||
1000 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | ||
1001 | if (!sglen) | ||
1002 | goto err_tx_sgmap; | ||
1003 | |||
1004 | /* Send both scatterlists */ | ||
1005 | rxdesc = rxchan->device->device_prep_slave_sg(rxchan, | ||
1006 | pl022->sgt_rx.sgl, | ||
1007 | pl022->sgt_rx.nents, | ||
1008 | DMA_FROM_DEVICE, | ||
1009 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1010 | if (!rxdesc) | ||
1011 | goto err_rxdesc; | ||
1012 | |||
1013 | txdesc = txchan->device->device_prep_slave_sg(txchan, | ||
1014 | pl022->sgt_tx.sgl, | ||
1015 | pl022->sgt_tx.nents, | ||
1016 | DMA_TO_DEVICE, | ||
1017 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1018 | if (!txdesc) | ||
1019 | goto err_txdesc; | ||
1020 | |||
1021 | /* Put the callback on the RX transfer only, that should finish last */ | ||
1022 | rxdesc->callback = dma_callback; | ||
1023 | rxdesc->callback_param = pl022; | ||
1024 | |||
1025 | /* Submit and fire RX and TX with TX last so we're ready to read! */ | ||
1026 | cookie = rxdesc->tx_submit(rxdesc); | ||
1027 | if (dma_submit_error(cookie)) | ||
1028 | goto err_submit_rx; | ||
1029 | cookie = txdesc->tx_submit(txdesc); | ||
1030 | if (dma_submit_error(cookie)) | ||
1031 | goto err_submit_tx; | ||
1032 | rxchan->device->device_issue_pending(rxchan); | ||
1033 | txchan->device->device_issue_pending(txchan); | ||
1034 | |||
1035 | return 0; | ||
1036 | |||
1037 | err_submit_tx: | ||
1038 | err_submit_rx: | ||
1039 | err_txdesc: | ||
1040 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | ||
1041 | err_rxdesc: | ||
1042 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | ||
1043 | dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl, | ||
1044 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | ||
1045 | err_tx_sgmap: | ||
1046 | dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl, | ||
1047 | pl022->sgt_tx.nents, DMA_FROM_DEVICE); | ||
1048 | err_rx_sgmap: | ||
1049 | sg_free_table(&pl022->sgt_tx); | ||
1050 | err_alloc_tx_sg: | ||
1051 | sg_free_table(&pl022->sgt_rx); | ||
1052 | err_alloc_rx_sg: | ||
1053 | return -ENOMEM; | ||
1054 | } | ||
1055 | |||
1056 | static int __init pl022_dma_probe(struct pl022 *pl022) | ||
1057 | { | ||
1058 | dma_cap_mask_t mask; | ||
1059 | |||
1060 | /* Try to acquire a generic DMA engine slave channel */ | ||
1061 | dma_cap_zero(mask); | ||
1062 | dma_cap_set(DMA_SLAVE, mask); | ||
1063 | /* | ||
1064 | * We need both RX and TX channels to do DMA, else do none | ||
1065 | * of them. | ||
1066 | */ | ||
1067 | pl022->dma_rx_channel = dma_request_channel(mask, | ||
1068 | pl022->master_info->dma_filter, | ||
1069 | pl022->master_info->dma_rx_param); | ||
1070 | if (!pl022->dma_rx_channel) { | ||
1071 | dev_err(&pl022->adev->dev, "no RX DMA channel!\n"); | ||
1072 | goto err_no_rxchan; | ||
1073 | } | ||
1074 | |||
1075 | pl022->dma_tx_channel = dma_request_channel(mask, | ||
1076 | pl022->master_info->dma_filter, | ||
1077 | pl022->master_info->dma_tx_param); | ||
1078 | if (!pl022->dma_tx_channel) { | ||
1079 | dev_err(&pl022->adev->dev, "no TX DMA channel!\n"); | ||
1080 | goto err_no_txchan; | ||
1081 | } | ||
1082 | |||
1083 | pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1084 | if (!pl022->dummypage) { | ||
1085 | dev_err(&pl022->adev->dev, "no DMA dummypage!\n"); | ||
1086 | goto err_no_dummypage; | ||
1087 | } | ||
1088 | |||
1089 | dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n", | ||
1090 | dma_chan_name(pl022->dma_rx_channel), | ||
1091 | dma_chan_name(pl022->dma_tx_channel)); | ||
1092 | |||
1093 | return 0; | ||
1094 | |||
1095 | err_no_dummypage: | ||
1096 | dma_release_channel(pl022->dma_tx_channel); | ||
1097 | err_no_txchan: | ||
1098 | dma_release_channel(pl022->dma_rx_channel); | ||
1099 | pl022->dma_rx_channel = NULL; | ||
1100 | err_no_rxchan: | ||
1101 | return -ENODEV; | ||
1102 | } | ||
1103 | |||
1104 | static void terminate_dma(struct pl022 *pl022) | ||
1105 | { | ||
1106 | struct dma_chan *rxchan = pl022->dma_rx_channel; | ||
1107 | struct dma_chan *txchan = pl022->dma_tx_channel; | ||
1108 | |||
1109 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | ||
1110 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | ||
1111 | unmap_free_dma_scatter(pl022); | ||
1112 | } | ||
1113 | |||
1114 | static void pl022_dma_remove(struct pl022 *pl022) | ||
1115 | { | ||
1116 | if (pl022->busy) | ||
1117 | terminate_dma(pl022); | ||
1118 | if (pl022->dma_tx_channel) | ||
1119 | dma_release_channel(pl022->dma_tx_channel); | ||
1120 | if (pl022->dma_rx_channel) | ||
1121 | dma_release_channel(pl022->dma_rx_channel); | ||
1122 | kfree(pl022->dummypage); | ||
1123 | } | ||
1124 | |||
1125 | #else | ||
1126 | static inline int configure_dma(struct pl022 *pl022) | ||
1127 | { | ||
1128 | return -ENODEV; | ||
1129 | } | ||
1130 | |||
1131 | static inline int pl022_dma_probe(struct pl022 *pl022) | ||
1132 | { | ||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | static inline void pl022_dma_remove(struct pl022 *pl022) | ||
1137 | { | ||
1138 | } | ||
1139 | #endif | ||
1140 | |||
766 | /** | 1141 | /** |
767 | * pl022_interrupt_handler - Interrupt handler for SSP controller | 1142 | * pl022_interrupt_handler - Interrupt handler for SSP controller |
768 | * | 1143 | * |
@@ -794,14 +1169,17 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) | |||
794 | if (unlikely(!irq_status)) | 1169 | if (unlikely(!irq_status)) |
795 | return IRQ_NONE; | 1170 | return IRQ_NONE; |
796 | 1171 | ||
797 | /* This handles the error code interrupts */ | 1172 | /* |
1173 | * This handles the FIFO interrupts, the timeout | ||
1174 | * interrupts are flatly ignored, they cannot be | ||
1175 | * trusted. | ||
1176 | */ | ||
798 | if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { | 1177 | if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { |
799 | /* | 1178 | /* |
800 | * Overrun interrupt - bail out since our Data has been | 1179 | * Overrun interrupt - bail out since our Data has been |
801 | * corrupted | 1180 | * corrupted |
802 | */ | 1181 | */ |
803 | dev_err(&pl022->adev->dev, | 1182 | dev_err(&pl022->adev->dev, "FIFO overrun\n"); |
804 | "FIFO overrun\n"); | ||
805 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) | 1183 | if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) |
806 | dev_err(&pl022->adev->dev, | 1184 | dev_err(&pl022->adev->dev, |
807 | "RXFIFO is full\n"); | 1185 | "RXFIFO is full\n"); |
@@ -896,8 +1274,8 @@ static int set_up_next_transfer(struct pl022 *pl022, | |||
896 | } | 1274 | } |
897 | 1275 | ||
898 | /** | 1276 | /** |
899 | * pump_transfers - Tasklet function which schedules next interrupt transfer | 1277 | * pump_transfers - Tasklet function which schedules next transfer |
900 | * when running in interrupt transfer mode. | 1278 | * when running in interrupt or DMA transfer mode. |
901 | * @data: SSP driver private data structure | 1279 | * @data: SSP driver private data structure |
902 | * | 1280 | * |
903 | */ | 1281 | */ |
@@ -954,65 +1332,23 @@ static void pump_transfers(unsigned long data) | |||
954 | } | 1332 | } |
955 | /* Flush the FIFOs and let's go! */ | 1333 | /* Flush the FIFOs and let's go! */ |
956 | flush(pl022); | 1334 | flush(pl022); |
957 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | ||
958 | } | ||
959 | |||
960 | /** | ||
961 | * NOT IMPLEMENTED | ||
962 | * configure_dma - It configures the DMA pipes for DMA transfers | ||
963 | * @data: SSP driver's private data structure | ||
964 | * | ||
965 | */ | ||
966 | static int configure_dma(void *data) | ||
967 | { | ||
968 | struct pl022 *pl022 = data; | ||
969 | dev_dbg(&pl022->adev->dev, "configure DMA\n"); | ||
970 | return -ENOTSUPP; | ||
971 | } | ||
972 | |||
973 | /** | ||
974 | * do_dma_transfer - It handles transfers of the current message | ||
975 | * if it is DMA xfer. | ||
976 | * NOT FULLY IMPLEMENTED | ||
977 | * @data: SSP driver's private data structure | ||
978 | */ | ||
979 | static void do_dma_transfer(void *data) | ||
980 | { | ||
981 | struct pl022 *pl022 = data; | ||
982 | |||
983 | if (configure_dma(data)) { | ||
984 | dev_dbg(&pl022->adev->dev, "configuration of DMA Failed!\n"); | ||
985 | goto err_config_dma; | ||
986 | } | ||
987 | 1335 | ||
988 | /* TODO: Implememt DMA setup of pipes here */ | 1336 | if (pl022->cur_chip->enable_dma) { |
989 | 1337 | if (configure_dma(pl022)) { | |
990 | /* Enable target chip, set up transfer */ | 1338 | dev_dbg(&pl022->adev->dev, |
991 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1339 | "configuration of DMA failed, fall back to interrupt mode\n"); |
992 | if (set_up_next_transfer(pl022, pl022->cur_transfer)) { | 1340 | goto err_config_dma; |
993 | /* Error path */ | 1341 | } |
994 | pl022->cur_msg->state = STATE_ERROR; | ||
995 | pl022->cur_msg->status = -EIO; | ||
996 | giveback(pl022); | ||
997 | return; | 1342 | return; |
998 | } | 1343 | } |
999 | /* Enable SSP */ | ||
1000 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | ||
1001 | SSP_CR1(pl022->virtbase)); | ||
1002 | |||
1003 | /* TODO: Enable the DMA transfer here */ | ||
1004 | return; | ||
1005 | 1344 | ||
1006 | err_config_dma: | 1345 | err_config_dma: |
1007 | pl022->cur_msg->state = STATE_ERROR; | 1346 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); |
1008 | pl022->cur_msg->status = -EIO; | ||
1009 | giveback(pl022); | ||
1010 | return; | ||
1011 | } | 1347 | } |
1012 | 1348 | ||
1013 | static void do_interrupt_transfer(void *data) | 1349 | static void do_interrupt_dma_transfer(struct pl022 *pl022) |
1014 | { | 1350 | { |
1015 | struct pl022 *pl022 = data; | 1351 | u32 irqflags = ENABLE_ALL_INTERRUPTS; |
1016 | 1352 | ||
1017 | /* Enable target chip */ | 1353 | /* Enable target chip */ |
1018 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); | 1354 | pl022->cur_chip->cs_control(SSP_CHIP_SELECT); |
@@ -1023,15 +1359,26 @@ static void do_interrupt_transfer(void *data) | |||
1023 | giveback(pl022); | 1359 | giveback(pl022); |
1024 | return; | 1360 | return; |
1025 | } | 1361 | } |
1362 | /* If we're using DMA, set up DMA here */ | ||
1363 | if (pl022->cur_chip->enable_dma) { | ||
1364 | /* Configure DMA transfer */ | ||
1365 | if (configure_dma(pl022)) { | ||
1366 | dev_dbg(&pl022->adev->dev, | ||
1367 | "configuration of DMA failed, fall back to interrupt mode\n"); | ||
1368 | goto err_config_dma; | ||
1369 | } | ||
1370 | /* Disable interrupts in DMA mode, IRQ from DMA controller */ | ||
1371 | irqflags = DISABLE_ALL_INTERRUPTS; | ||
1372 | } | ||
1373 | err_config_dma: | ||
1026 | /* Enable SSP, turn on interrupts */ | 1374 | /* Enable SSP, turn on interrupts */ |
1027 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), | 1375 | writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE), |
1028 | SSP_CR1(pl022->virtbase)); | 1376 | SSP_CR1(pl022->virtbase)); |
1029 | writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase)); | 1377 | writew(irqflags, SSP_IMSC(pl022->virtbase)); |
1030 | } | 1378 | } |
1031 | 1379 | ||
1032 | static void do_polling_transfer(void *data) | 1380 | static void do_polling_transfer(struct pl022 *pl022) |
1033 | { | 1381 | { |
1034 | struct pl022 *pl022 = data; | ||
1035 | struct spi_message *message = NULL; | 1382 | struct spi_message *message = NULL; |
1036 | struct spi_transfer *transfer = NULL; | 1383 | struct spi_transfer *transfer = NULL; |
1037 | struct spi_transfer *previous = NULL; | 1384 | struct spi_transfer *previous = NULL; |
@@ -1101,7 +1448,7 @@ static void do_polling_transfer(void *data) | |||
1101 | * | 1448 | * |
1102 | * This function checks if there is any spi message in the queue that | 1449 | * This function checks if there is any spi message in the queue that |
1103 | * needs processing and delegate control to appropriate function | 1450 | * needs processing and delegate control to appropriate function |
1104 | * do_polling_transfer()/do_interrupt_transfer()/do_dma_transfer() | 1451 | * do_polling_transfer()/do_interrupt_dma_transfer() |
1105 | * based on the kind of the transfer | 1452 | * based on the kind of the transfer |
1106 | * | 1453 | * |
1107 | */ | 1454 | */ |
@@ -1150,10 +1497,8 @@ static void pump_messages(struct work_struct *work) | |||
1150 | 1497 | ||
1151 | if (pl022->cur_chip->xfer_type == POLLING_TRANSFER) | 1498 | if (pl022->cur_chip->xfer_type == POLLING_TRANSFER) |
1152 | do_polling_transfer(pl022); | 1499 | do_polling_transfer(pl022); |
1153 | else if (pl022->cur_chip->xfer_type == INTERRUPT_TRANSFER) | ||
1154 | do_interrupt_transfer(pl022); | ||
1155 | else | 1500 | else |
1156 | do_dma_transfer(pl022); | 1501 | do_interrupt_dma_transfer(pl022); |
1157 | } | 1502 | } |
1158 | 1503 | ||
1159 | 1504 | ||
@@ -1248,100 +1593,56 @@ static int destroy_queue(struct pl022 *pl022) | |||
1248 | } | 1593 | } |
1249 | 1594 | ||
1250 | static int verify_controller_parameters(struct pl022 *pl022, | 1595 | static int verify_controller_parameters(struct pl022 *pl022, |
1251 | struct pl022_config_chip *chip_info) | 1596 | struct pl022_config_chip const *chip_info) |
1252 | { | 1597 | { |
1253 | if ((chip_info->lbm != LOOPBACK_ENABLED) | ||
1254 | && (chip_info->lbm != LOOPBACK_DISABLED)) { | ||
1255 | dev_err(chip_info->dev, | ||
1256 | "loopback Mode is configured incorrectly\n"); | ||
1257 | return -EINVAL; | ||
1258 | } | ||
1259 | if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI) | 1598 | if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI) |
1260 | || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) { | 1599 | || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) { |
1261 | dev_err(chip_info->dev, | 1600 | dev_err(&pl022->adev->dev, |
1262 | "interface is configured incorrectly\n"); | 1601 | "interface is configured incorrectly\n"); |
1263 | return -EINVAL; | 1602 | return -EINVAL; |
1264 | } | 1603 | } |
1265 | if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) && | 1604 | if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) && |
1266 | (!pl022->vendor->unidir)) { | 1605 | (!pl022->vendor->unidir)) { |
1267 | dev_err(chip_info->dev, | 1606 | dev_err(&pl022->adev->dev, |
1268 | "unidirectional mode not supported in this " | 1607 | "unidirectional mode not supported in this " |
1269 | "hardware version\n"); | 1608 | "hardware version\n"); |
1270 | return -EINVAL; | 1609 | return -EINVAL; |
1271 | } | 1610 | } |
1272 | if ((chip_info->hierarchy != SSP_MASTER) | 1611 | if ((chip_info->hierarchy != SSP_MASTER) |
1273 | && (chip_info->hierarchy != SSP_SLAVE)) { | 1612 | && (chip_info->hierarchy != SSP_SLAVE)) { |
1274 | dev_err(chip_info->dev, | 1613 | dev_err(&pl022->adev->dev, |
1275 | "hierarchy is configured incorrectly\n"); | 1614 | "hierarchy is configured incorrectly\n"); |
1276 | return -EINVAL; | 1615 | return -EINVAL; |
1277 | } | 1616 | } |
1278 | if (((chip_info->clk_freq).cpsdvsr < CPSDVR_MIN) | ||
1279 | || ((chip_info->clk_freq).cpsdvsr > CPSDVR_MAX)) { | ||
1280 | dev_err(chip_info->dev, | ||
1281 | "cpsdvsr is configured incorrectly\n"); | ||
1282 | return -EINVAL; | ||
1283 | } | ||
1284 | if ((chip_info->endian_rx != SSP_RX_MSB) | ||
1285 | && (chip_info->endian_rx != SSP_RX_LSB)) { | ||
1286 | dev_err(chip_info->dev, | ||
1287 | "RX FIFO endianess is configured incorrectly\n"); | ||
1288 | return -EINVAL; | ||
1289 | } | ||
1290 | if ((chip_info->endian_tx != SSP_TX_MSB) | ||
1291 | && (chip_info->endian_tx != SSP_TX_LSB)) { | ||
1292 | dev_err(chip_info->dev, | ||
1293 | "TX FIFO endianess is configured incorrectly\n"); | ||
1294 | return -EINVAL; | ||
1295 | } | ||
1296 | if ((chip_info->data_size < SSP_DATA_BITS_4) | ||
1297 | || (chip_info->data_size > SSP_DATA_BITS_32)) { | ||
1298 | dev_err(chip_info->dev, | ||
1299 | "DATA Size is configured incorrectly\n"); | ||
1300 | return -EINVAL; | ||
1301 | } | ||
1302 | if ((chip_info->com_mode != INTERRUPT_TRANSFER) | 1617 | if ((chip_info->com_mode != INTERRUPT_TRANSFER) |
1303 | && (chip_info->com_mode != DMA_TRANSFER) | 1618 | && (chip_info->com_mode != DMA_TRANSFER) |
1304 | && (chip_info->com_mode != POLLING_TRANSFER)) { | 1619 | && (chip_info->com_mode != POLLING_TRANSFER)) { |
1305 | dev_err(chip_info->dev, | 1620 | dev_err(&pl022->adev->dev, |
1306 | "Communication mode is configured incorrectly\n"); | 1621 | "Communication mode is configured incorrectly\n"); |
1307 | return -EINVAL; | 1622 | return -EINVAL; |
1308 | } | 1623 | } |
1309 | if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM) | 1624 | if ((chip_info->rx_lev_trig < SSP_RX_1_OR_MORE_ELEM) |
1310 | || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) { | 1625 | || (chip_info->rx_lev_trig > SSP_RX_32_OR_MORE_ELEM)) { |
1311 | dev_err(chip_info->dev, | 1626 | dev_err(&pl022->adev->dev, |
1312 | "RX FIFO Trigger Level is configured incorrectly\n"); | 1627 | "RX FIFO Trigger Level is configured incorrectly\n"); |
1313 | return -EINVAL; | 1628 | return -EINVAL; |
1314 | } | 1629 | } |
1315 | if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC) | 1630 | if ((chip_info->tx_lev_trig < SSP_TX_1_OR_MORE_EMPTY_LOC) |
1316 | || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) { | 1631 | || (chip_info->tx_lev_trig > SSP_TX_32_OR_MORE_EMPTY_LOC)) { |
1317 | dev_err(chip_info->dev, | 1632 | dev_err(&pl022->adev->dev, |
1318 | "TX FIFO Trigger Level is configured incorrectly\n"); | 1633 | "TX FIFO Trigger Level is configured incorrectly\n"); |
1319 | return -EINVAL; | 1634 | return -EINVAL; |
1320 | } | 1635 | } |
1321 | if (chip_info->iface == SSP_INTERFACE_MOTOROLA_SPI) { | ||
1322 | if ((chip_info->clk_phase != SSP_CLK_FIRST_EDGE) | ||
1323 | && (chip_info->clk_phase != SSP_CLK_SECOND_EDGE)) { | ||
1324 | dev_err(chip_info->dev, | ||
1325 | "Clock Phase is configured incorrectly\n"); | ||
1326 | return -EINVAL; | ||
1327 | } | ||
1328 | if ((chip_info->clk_pol != SSP_CLK_POL_IDLE_LOW) | ||
1329 | && (chip_info->clk_pol != SSP_CLK_POL_IDLE_HIGH)) { | ||
1330 | dev_err(chip_info->dev, | ||
1331 | "Clock Polarity is configured incorrectly\n"); | ||
1332 | return -EINVAL; | ||
1333 | } | ||
1334 | } | ||
1335 | if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) { | 1636 | if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) { |
1336 | if ((chip_info->ctrl_len < SSP_BITS_4) | 1637 | if ((chip_info->ctrl_len < SSP_BITS_4) |
1337 | || (chip_info->ctrl_len > SSP_BITS_32)) { | 1638 | || (chip_info->ctrl_len > SSP_BITS_32)) { |
1338 | dev_err(chip_info->dev, | 1639 | dev_err(&pl022->adev->dev, |
1339 | "CTRL LEN is configured incorrectly\n"); | 1640 | "CTRL LEN is configured incorrectly\n"); |
1340 | return -EINVAL; | 1641 | return -EINVAL; |
1341 | } | 1642 | } |
1342 | if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO) | 1643 | if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO) |
1343 | && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) { | 1644 | && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) { |
1344 | dev_err(chip_info->dev, | 1645 | dev_err(&pl022->adev->dev, |
1345 | "Wait State is configured incorrectly\n"); | 1646 | "Wait State is configured incorrectly\n"); |
1346 | return -EINVAL; | 1647 | return -EINVAL; |
1347 | } | 1648 | } |
@@ -1350,24 +1651,20 @@ static int verify_controller_parameters(struct pl022 *pl022, | |||
1350 | if ((chip_info->duplex != | 1651 | if ((chip_info->duplex != |
1351 | SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) | 1652 | SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) |
1352 | && (chip_info->duplex != | 1653 | && (chip_info->duplex != |
1353 | SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) | 1654 | SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) { |
1354 | dev_err(chip_info->dev, | 1655 | dev_err(&pl022->adev->dev, |
1355 | "Microwire duplex mode is configured incorrectly\n"); | 1656 | "Microwire duplex mode is configured incorrectly\n"); |
1356 | return -EINVAL; | 1657 | return -EINVAL; |
1658 | } | ||
1357 | } else { | 1659 | } else { |
1358 | if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) | 1660 | if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX) |
1359 | dev_err(chip_info->dev, | 1661 | dev_err(&pl022->adev->dev, |
1360 | "Microwire half duplex mode requested," | 1662 | "Microwire half duplex mode requested," |
1361 | " but this is only available in the" | 1663 | " but this is only available in the" |
1362 | " ST version of PL022\n"); | 1664 | " ST version of PL022\n"); |
1363 | return -EINVAL; | 1665 | return -EINVAL; |
1364 | } | 1666 | } |
1365 | } | 1667 | } |
1366 | if (chip_info->cs_control == NULL) { | ||
1367 | dev_warn(chip_info->dev, | ||
1368 | "Chip Select Function is NULL for this chip\n"); | ||
1369 | chip_info->cs_control = null_cs_control; | ||
1370 | } | ||
1371 | return 0; | 1668 | return 0; |
1372 | } | 1669 | } |
1373 | 1670 | ||
@@ -1467,22 +1764,24 @@ static int calculate_effective_freq(struct pl022 *pl022, | |||
1467 | return 0; | 1764 | return 0; |
1468 | } | 1765 | } |
1469 | 1766 | ||
1470 | /** | 1767 | |
1471 | * NOT IMPLEMENTED | 1768 | /* |
1472 | * process_dma_info - Processes the DMA info provided by client drivers | 1769 | * A piece of default chip info unless the platform |
1473 | * @chip_info: chip info provided by client device | 1770 | * supplies it. |
1474 | * @chip: Runtime state maintained by the SSP controller for each spi device | ||
1475 | * | ||
1476 | * This function processes and stores DMA config provided by client driver | ||
1477 | * into the runtime state maintained by the SSP controller driver | ||
1478 | */ | 1771 | */ |
1479 | static int process_dma_info(struct pl022_config_chip *chip_info, | 1772 | static const struct pl022_config_chip pl022_default_chip_info = { |
1480 | struct chip_data *chip) | 1773 | .com_mode = POLLING_TRANSFER, |
1481 | { | 1774 | .iface = SSP_INTERFACE_MOTOROLA_SPI, |
1482 | dev_err(chip_info->dev, | 1775 | .hierarchy = SSP_SLAVE, |
1483 | "cannot process DMA info, DMA not implemented!\n"); | 1776 | .slave_tx_disable = DO_NOT_DRIVE_TX, |
1484 | return -ENOTSUPP; | 1777 | .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, |
1485 | } | 1778 | .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, |
1779 | .ctrl_len = SSP_BITS_8, | ||
1780 | .wait_state = SSP_MWIRE_WAIT_ZERO, | ||
1781 | .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, | ||
1782 | .cs_control = null_cs_control, | ||
1783 | }; | ||
1784 | |||
1486 | 1785 | ||
1487 | /** | 1786 | /** |
1488 | * pl022_setup - setup function registered to SPI master framework | 1787 | * pl022_setup - setup function registered to SPI master framework |
@@ -1496,23 +1795,15 @@ static int process_dma_info(struct pl022_config_chip *chip_info, | |||
1496 | * controller hardware here, that is not done until the actual transfer | 1795 | * controller hardware here, that is not done until the actual transfer |
1497 | * commence. | 1796 | * commence. |
1498 | */ | 1797 | */ |
1499 | |||
1500 | /* FIXME: JUST GUESSING the spi->mode bits understood by this driver */ | ||
1501 | #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | ||
1502 | | SPI_LSB_FIRST | SPI_LOOP) | ||
1503 | |||
1504 | static int pl022_setup(struct spi_device *spi) | 1798 | static int pl022_setup(struct spi_device *spi) |
1505 | { | 1799 | { |
1506 | struct pl022_config_chip *chip_info; | 1800 | struct pl022_config_chip const *chip_info; |
1507 | struct chip_data *chip; | 1801 | struct chip_data *chip; |
1802 | struct ssp_clock_params clk_freq; | ||
1508 | int status = 0; | 1803 | int status = 0; |
1509 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); | 1804 | struct pl022 *pl022 = spi_master_get_devdata(spi->master); |
1510 | 1805 | unsigned int bits = spi->bits_per_word; | |
1511 | if (spi->mode & ~MODEBITS) { | 1806 | u32 tmp; |
1512 | dev_dbg(&spi->dev, "unsupported mode bits %x\n", | ||
1513 | spi->mode & ~MODEBITS); | ||
1514 | return -EINVAL; | ||
1515 | } | ||
1516 | 1807 | ||
1517 | if (!spi->max_speed_hz) | 1808 | if (!spi->max_speed_hz) |
1518 | return -EINVAL; | 1809 | return -EINVAL; |
@@ -1535,48 +1826,13 @@ static int pl022_setup(struct spi_device *spi) | |||
1535 | chip_info = spi->controller_data; | 1826 | chip_info = spi->controller_data; |
1536 | 1827 | ||
1537 | if (chip_info == NULL) { | 1828 | if (chip_info == NULL) { |
1829 | chip_info = &pl022_default_chip_info; | ||
1538 | /* spi_board_info.controller_data not is supplied */ | 1830 | /* spi_board_info.controller_data not is supplied */ |
1539 | dev_dbg(&spi->dev, | 1831 | dev_dbg(&spi->dev, |
1540 | "using default controller_data settings\n"); | 1832 | "using default controller_data settings\n"); |
1541 | 1833 | } else | |
1542 | chip_info = | ||
1543 | kzalloc(sizeof(struct pl022_config_chip), GFP_KERNEL); | ||
1544 | |||
1545 | if (!chip_info) { | ||
1546 | dev_err(&spi->dev, | ||
1547 | "cannot allocate controller data\n"); | ||
1548 | status = -ENOMEM; | ||
1549 | goto err_first_setup; | ||
1550 | } | ||
1551 | |||
1552 | dev_dbg(&spi->dev, "allocated memory for controller data\n"); | ||
1553 | |||
1554 | /* Pointer back to the SPI device */ | ||
1555 | chip_info->dev = &spi->dev; | ||
1556 | /* | ||
1557 | * Set controller data default values: | ||
1558 | * Polling is supported by default | ||
1559 | */ | ||
1560 | chip_info->lbm = LOOPBACK_DISABLED; | ||
1561 | chip_info->com_mode = POLLING_TRANSFER; | ||
1562 | chip_info->iface = SSP_INTERFACE_MOTOROLA_SPI; | ||
1563 | chip_info->hierarchy = SSP_SLAVE; | ||
1564 | chip_info->slave_tx_disable = DO_NOT_DRIVE_TX; | ||
1565 | chip_info->endian_tx = SSP_TX_LSB; | ||
1566 | chip_info->endian_rx = SSP_RX_LSB; | ||
1567 | chip_info->data_size = SSP_DATA_BITS_12; | ||
1568 | chip_info->rx_lev_trig = SSP_RX_1_OR_MORE_ELEM; | ||
1569 | chip_info->tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC; | ||
1570 | chip_info->clk_phase = SSP_CLK_SECOND_EDGE; | ||
1571 | chip_info->clk_pol = SSP_CLK_POL_IDLE_LOW; | ||
1572 | chip_info->ctrl_len = SSP_BITS_8; | ||
1573 | chip_info->wait_state = SSP_MWIRE_WAIT_ZERO; | ||
1574 | chip_info->duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX; | ||
1575 | chip_info->cs_control = null_cs_control; | ||
1576 | } else { | ||
1577 | dev_dbg(&spi->dev, | 1834 | dev_dbg(&spi->dev, |
1578 | "using user supplied controller_data settings\n"); | 1835 | "using user supplied controller_data settings\n"); |
1579 | } | ||
1580 | 1836 | ||
1581 | /* | 1837 | /* |
1582 | * We can override with custom divisors, else we use the board | 1838 | * We can override with custom divisors, else we use the board |
@@ -1586,29 +1842,48 @@ static int pl022_setup(struct spi_device *spi) | |||
1586 | && (0 == chip_info->clk_freq.scr)) { | 1842 | && (0 == chip_info->clk_freq.scr)) { |
1587 | status = calculate_effective_freq(pl022, | 1843 | status = calculate_effective_freq(pl022, |
1588 | spi->max_speed_hz, | 1844 | spi->max_speed_hz, |
1589 | &chip_info->clk_freq); | 1845 | &clk_freq); |
1590 | if (status < 0) | 1846 | if (status < 0) |
1591 | goto err_config_params; | 1847 | goto err_config_params; |
1592 | } else { | 1848 | } else { |
1593 | if ((chip_info->clk_freq.cpsdvsr % 2) != 0) | 1849 | memcpy(&clk_freq, &chip_info->clk_freq, sizeof(clk_freq)); |
1594 | chip_info->clk_freq.cpsdvsr = | 1850 | if ((clk_freq.cpsdvsr % 2) != 0) |
1595 | chip_info->clk_freq.cpsdvsr - 1; | 1851 | clk_freq.cpsdvsr = |
1852 | clk_freq.cpsdvsr - 1; | ||
1853 | } | ||
1854 | if ((clk_freq.cpsdvsr < CPSDVR_MIN) | ||
1855 | || (clk_freq.cpsdvsr > CPSDVR_MAX)) { | ||
1856 | dev_err(&spi->dev, | ||
1857 | "cpsdvsr is configured incorrectly\n"); | ||
1858 | goto err_config_params; | ||
1596 | } | 1859 | } |
1860 | |||
1861 | |||
1597 | status = verify_controller_parameters(pl022, chip_info); | 1862 | status = verify_controller_parameters(pl022, chip_info); |
1598 | if (status) { | 1863 | if (status) { |
1599 | dev_err(&spi->dev, "controller data is incorrect"); | 1864 | dev_err(&spi->dev, "controller data is incorrect"); |
1600 | goto err_config_params; | 1865 | goto err_config_params; |
1601 | } | 1866 | } |
1867 | |||
1602 | /* Now set controller state based on controller data */ | 1868 | /* Now set controller state based on controller data */ |
1603 | chip->xfer_type = chip_info->com_mode; | 1869 | chip->xfer_type = chip_info->com_mode; |
1604 | chip->cs_control = chip_info->cs_control; | 1870 | if (!chip_info->cs_control) { |
1605 | 1871 | chip->cs_control = null_cs_control; | |
1606 | if (chip_info->data_size <= 8) { | 1872 | dev_warn(&spi->dev, |
1607 | dev_dbg(&spi->dev, "1 <= n <=8 bits per word\n"); | 1873 | "chip select function is NULL for this chip\n"); |
1874 | } else | ||
1875 | chip->cs_control = chip_info->cs_control; | ||
1876 | |||
1877 | if (bits <= 3) { | ||
1878 | /* PL022 doesn't support less than 4-bits */ | ||
1879 | status = -ENOTSUPP; | ||
1880 | goto err_config_params; | ||
1881 | } else if (bits <= 8) { | ||
1882 | dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n"); | ||
1608 | chip->n_bytes = 1; | 1883 | chip->n_bytes = 1; |
1609 | chip->read = READING_U8; | 1884 | chip->read = READING_U8; |
1610 | chip->write = WRITING_U8; | 1885 | chip->write = WRITING_U8; |
1611 | } else if (chip_info->data_size <= 16) { | 1886 | } else if (bits <= 16) { |
1612 | dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n"); | 1887 | dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n"); |
1613 | chip->n_bytes = 2; | 1888 | chip->n_bytes = 2; |
1614 | chip->read = READING_U16; | 1889 | chip->read = READING_U16; |
@@ -1625,6 +1900,7 @@ static int pl022_setup(struct spi_device *spi) | |||
1625 | dev_err(&spi->dev, | 1900 | dev_err(&spi->dev, |
1626 | "a standard pl022 can only handle " | 1901 | "a standard pl022 can only handle " |
1627 | "1 <= n <= 16 bit words\n"); | 1902 | "1 <= n <= 16 bit words\n"); |
1903 | status = -ENOTSUPP; | ||
1628 | goto err_config_params; | 1904 | goto err_config_params; |
1629 | } | 1905 | } |
1630 | } | 1906 | } |
@@ -1636,9 +1912,8 @@ static int pl022_setup(struct spi_device *spi) | |||
1636 | chip->cpsr = 0; | 1912 | chip->cpsr = 0; |
1637 | if ((chip_info->com_mode == DMA_TRANSFER) | 1913 | if ((chip_info->com_mode == DMA_TRANSFER) |
1638 | && ((pl022->master_info)->enable_dma)) { | 1914 | && ((pl022->master_info)->enable_dma)) { |
1639 | chip->enable_dma = 1; | 1915 | chip->enable_dma = true; |
1640 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); | 1916 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); |
1641 | status = process_dma_info(chip_info, chip); | ||
1642 | if (status < 0) | 1917 | if (status < 0) |
1643 | goto err_config_params; | 1918 | goto err_config_params; |
1644 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1919 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
@@ -1646,7 +1921,7 @@ static int pl022_setup(struct spi_device *spi) | |||
1646 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1921 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
1647 | SSP_DMACR_MASK_TXDMAE, 1); | 1922 | SSP_DMACR_MASK_TXDMAE, 1); |
1648 | } else { | 1923 | } else { |
1649 | chip->enable_dma = 0; | 1924 | chip->enable_dma = false; |
1650 | dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n"); | 1925 | dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n"); |
1651 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, | 1926 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED, |
1652 | SSP_DMACR_MASK_RXDMAE, 0); | 1927 | SSP_DMACR_MASK_RXDMAE, 0); |
@@ -1654,10 +1929,12 @@ static int pl022_setup(struct spi_device *spi) | |||
1654 | SSP_DMACR_MASK_TXDMAE, 1); | 1929 | SSP_DMACR_MASK_TXDMAE, 1); |
1655 | } | 1930 | } |
1656 | 1931 | ||
1657 | chip->cpsr = chip_info->clk_freq.cpsdvsr; | 1932 | chip->cpsr = clk_freq.cpsdvsr; |
1658 | 1933 | ||
1659 | /* Special setup for the ST micro extended control registers */ | 1934 | /* Special setup for the ST micro extended control registers */ |
1660 | if (pl022->vendor->extended_cr) { | 1935 | if (pl022->vendor->extended_cr) { |
1936 | u32 etx; | ||
1937 | |||
1661 | if (pl022->vendor->pl023) { | 1938 | if (pl022->vendor->pl023) { |
1662 | /* These bits are only in the PL023 */ | 1939 | /* These bits are only in the PL023 */ |
1663 | SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay, | 1940 | SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay, |
@@ -1673,29 +1950,51 @@ static int pl022_setup(struct spi_device *spi) | |||
1673 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, | 1950 | SSP_WRITE_BITS(chip->cr1, chip_info->wait_state, |
1674 | SSP_CR1_MASK_MWAIT_ST, 6); | 1951 | SSP_CR1_MASK_MWAIT_ST, 6); |
1675 | } | 1952 | } |
1676 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, | 1953 | SSP_WRITE_BITS(chip->cr0, bits - 1, |
1677 | SSP_CR0_MASK_DSS_ST, 0); | 1954 | SSP_CR0_MASK_DSS_ST, 0); |
1678 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_rx, | 1955 | |
1679 | SSP_CR1_MASK_RENDN_ST, 4); | 1956 | if (spi->mode & SPI_LSB_FIRST) { |
1680 | SSP_WRITE_BITS(chip->cr1, chip_info->endian_tx, | 1957 | tmp = SSP_RX_LSB; |
1681 | SSP_CR1_MASK_TENDN_ST, 5); | 1958 | etx = SSP_TX_LSB; |
1959 | } else { | ||
1960 | tmp = SSP_RX_MSB; | ||
1961 | etx = SSP_TX_MSB; | ||
1962 | } | ||
1963 | SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_RENDN_ST, 4); | ||
1964 | SSP_WRITE_BITS(chip->cr1, etx, SSP_CR1_MASK_TENDN_ST, 5); | ||
1682 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, | 1965 | SSP_WRITE_BITS(chip->cr1, chip_info->rx_lev_trig, |
1683 | SSP_CR1_MASK_RXIFLSEL_ST, 7); | 1966 | SSP_CR1_MASK_RXIFLSEL_ST, 7); |
1684 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, | 1967 | SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, |
1685 | SSP_CR1_MASK_TXIFLSEL_ST, 10); | 1968 | SSP_CR1_MASK_TXIFLSEL_ST, 10); |
1686 | } else { | 1969 | } else { |
1687 | SSP_WRITE_BITS(chip->cr0, chip_info->data_size, | 1970 | SSP_WRITE_BITS(chip->cr0, bits - 1, |
1688 | SSP_CR0_MASK_DSS, 0); | 1971 | SSP_CR0_MASK_DSS, 0); |
1689 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, | 1972 | SSP_WRITE_BITS(chip->cr0, chip_info->iface, |
1690 | SSP_CR0_MASK_FRF, 4); | 1973 | SSP_CR0_MASK_FRF, 4); |
1691 | } | 1974 | } |
1975 | |||
1692 | /* Stuff that is common for all versions */ | 1976 | /* Stuff that is common for all versions */ |
1693 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_pol, SSP_CR0_MASK_SPO, 6); | 1977 | if (spi->mode & SPI_CPOL) |
1694 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_phase, SSP_CR0_MASK_SPH, 7); | 1978 | tmp = SSP_CLK_POL_IDLE_HIGH; |
1695 | SSP_WRITE_BITS(chip->cr0, chip_info->clk_freq.scr, SSP_CR0_MASK_SCR, 8); | 1979 | else |
1980 | tmp = SSP_CLK_POL_IDLE_LOW; | ||
1981 | SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6); | ||
1982 | |||
1983 | if (spi->mode & SPI_CPHA) | ||
1984 | tmp = SSP_CLK_SECOND_EDGE; | ||
1985 | else | ||
1986 | tmp = SSP_CLK_FIRST_EDGE; | ||
1987 | SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPH, 7); | ||
1988 | |||
1989 | SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8); | ||
1696 | /* Loopback is available on all versions except PL023 */ | 1990 | /* Loopback is available on all versions except PL023 */ |
1697 | if (!pl022->vendor->pl023) | 1991 | if (!pl022->vendor->pl023) { |
1698 | SSP_WRITE_BITS(chip->cr1, chip_info->lbm, SSP_CR1_MASK_LBM, 0); | 1992 | if (spi->mode & SPI_LOOP) |
1993 | tmp = LOOPBACK_ENABLED; | ||
1994 | else | ||
1995 | tmp = LOOPBACK_DISABLED; | ||
1996 | SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_LBM, 0); | ||
1997 | } | ||
1699 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); | 1998 | SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); |
1700 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); | 1999 | SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); |
1701 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); | 2000 | SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3); |
@@ -1704,7 +2003,7 @@ static int pl022_setup(struct spi_device *spi) | |||
1704 | spi_set_ctldata(spi, chip); | 2003 | spi_set_ctldata(spi, chip); |
1705 | return status; | 2004 | return status; |
1706 | err_config_params: | 2005 | err_config_params: |
1707 | err_first_setup: | 2006 | spi_set_ctldata(spi, NULL); |
1708 | kfree(chip); | 2007 | kfree(chip); |
1709 | return status; | 2008 | return status; |
1710 | } | 2009 | } |
@@ -1766,12 +2065,21 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
1766 | master->setup = pl022_setup; | 2065 | master->setup = pl022_setup; |
1767 | master->transfer = pl022_transfer; | 2066 | master->transfer = pl022_transfer; |
1768 | 2067 | ||
2068 | /* | ||
2069 | * Supports mode 0-3, loopback, and active low CS. Transfers are | ||
2070 | * always MS bit first on the original pl022. | ||
2071 | */ | ||
2072 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; | ||
2073 | if (pl022->vendor->extended_cr) | ||
2074 | master->mode_bits |= SPI_LSB_FIRST; | ||
2075 | |||
1769 | dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num); | 2076 | dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num); |
1770 | 2077 | ||
1771 | status = amba_request_regions(adev, NULL); | 2078 | status = amba_request_regions(adev, NULL); |
1772 | if (status) | 2079 | if (status) |
1773 | goto err_no_ioregion; | 2080 | goto err_no_ioregion; |
1774 | 2081 | ||
2082 | pl022->phybase = adev->res.start; | ||
1775 | pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); | 2083 | pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); |
1776 | if (pl022->virtbase == NULL) { | 2084 | if (pl022->virtbase == NULL) { |
1777 | status = -ENOMEM; | 2085 | status = -ENOMEM; |
@@ -1798,6 +2106,14 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
1798 | dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status); | 2106 | dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status); |
1799 | goto err_no_irq; | 2107 | goto err_no_irq; |
1800 | } | 2108 | } |
2109 | |||
2110 | /* Get DMA channels */ | ||
2111 | if (platform_info->enable_dma) { | ||
2112 | status = pl022_dma_probe(pl022); | ||
2113 | if (status != 0) | ||
2114 | goto err_no_dma; | ||
2115 | } | ||
2116 | |||
1801 | /* Initialize and start queue */ | 2117 | /* Initialize and start queue */ |
1802 | status = init_queue(pl022); | 2118 | status = init_queue(pl022); |
1803 | if (status != 0) { | 2119 | if (status != 0) { |
@@ -1826,6 +2142,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
1826 | err_start_queue: | 2142 | err_start_queue: |
1827 | err_init_queue: | 2143 | err_init_queue: |
1828 | destroy_queue(pl022); | 2144 | destroy_queue(pl022); |
2145 | pl022_dma_remove(pl022); | ||
2146 | err_no_dma: | ||
1829 | free_irq(adev->irq[0], pl022); | 2147 | free_irq(adev->irq[0], pl022); |
1830 | err_no_irq: | 2148 | err_no_irq: |
1831 | clk_put(pl022->clk); | 2149 | clk_put(pl022->clk); |
@@ -1856,6 +2174,7 @@ pl022_remove(struct amba_device *adev) | |||
1856 | return status; | 2174 | return status; |
1857 | } | 2175 | } |
1858 | load_ssp_default_config(pl022); | 2176 | load_ssp_default_config(pl022); |
2177 | pl022_dma_remove(pl022); | ||
1859 | free_irq(adev->irq[0], pl022); | 2178 | free_irq(adev->irq[0], pl022); |
1860 | clk_disable(pl022->clk); | 2179 | clk_disable(pl022->clk); |
1861 | clk_put(pl022->clk); | 2180 | clk_put(pl022->clk); |
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index c4e04428992d..154529aacc03 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -654,6 +654,8 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
654 | struct spi_transfer *xfer; | 654 | struct spi_transfer *xfer; |
655 | unsigned long flags; | 655 | unsigned long flags; |
656 | struct device *controller = spi->master->dev.parent; | 656 | struct device *controller = spi->master->dev.parent; |
657 | u8 bits; | ||
658 | struct atmel_spi_device *asd; | ||
657 | 659 | ||
658 | as = spi_master_get_devdata(spi->master); | 660 | as = spi_master_get_devdata(spi->master); |
659 | 661 | ||
@@ -672,8 +674,18 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
672 | return -EINVAL; | 674 | return -EINVAL; |
673 | } | 675 | } |
674 | 676 | ||
677 | if (xfer->bits_per_word) { | ||
678 | asd = spi->controller_state; | ||
679 | bits = (asd->csr >> 4) & 0xf; | ||
680 | if (bits != xfer->bits_per_word - 8) { | ||
681 | dev_dbg(&spi->dev, "you can't yet change " | ||
682 | "bits_per_word in transfers\n"); | ||
683 | return -ENOPROTOOPT; | ||
684 | } | ||
685 | } | ||
686 | |||
675 | /* FIXME implement these protocol options!! */ | 687 | /* FIXME implement these protocol options!! */ |
676 | if (xfer->bits_per_word || xfer->speed_hz) { | 688 | if (xfer->speed_hz) { |
677 | dev_dbg(&spi->dev, "no protocol options yet\n"); | 689 | dev_dbg(&spi->dev, "no protocol options yet\n"); |
678 | return -ENOPROTOOPT; | 690 | return -ENOPROTOOPT; |
679 | } | 691 | } |
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index b3a94ca0a75a..2a651e61bfbf 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) | |||
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | 298 | ||
299 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) | ||
300 | { | ||
301 | unsigned long timeout; | ||
302 | |||
303 | timeout = jiffies + msecs_to_jiffies(1000); | ||
304 | while (!(__raw_readl(reg) & bit)) { | ||
305 | if (time_after(jiffies, timeout)) | ||
306 | return -1; | ||
307 | cpu_relax(); | ||
308 | } | ||
309 | return 0; | ||
310 | } | ||
311 | |||
299 | static unsigned | 312 | static unsigned |
300 | omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | 313 | omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) |
301 | { | 314 | { |
@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
309 | u32 l; | 322 | u32 l; |
310 | u8 * rx; | 323 | u8 * rx; |
311 | const u8 * tx; | 324 | const u8 * tx; |
325 | void __iomem *chstat_reg; | ||
312 | 326 | ||
313 | mcspi = spi_master_get_devdata(spi->master); | 327 | mcspi = spi_master_get_devdata(spi->master); |
314 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; | 328 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; |
315 | l = mcspi_cached_chconf0(spi); | 329 | l = mcspi_cached_chconf0(spi); |
316 | 330 | ||
331 | chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; | ||
332 | |||
317 | count = xfer->len; | 333 | count = xfer->len; |
318 | c = count; | 334 | c = count; |
319 | word_len = cs->word_len; | 335 | word_len = cs->word_len; |
@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
382 | if (tx != NULL) { | 398 | if (tx != NULL) { |
383 | wait_for_completion(&mcspi_dma->dma_tx_completion); | 399 | wait_for_completion(&mcspi_dma->dma_tx_completion); |
384 | dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE); | 400 | dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE); |
401 | |||
402 | /* for TX_ONLY mode, be sure all words have shifted out */ | ||
403 | if (rx == NULL) { | ||
404 | if (mcspi_wait_for_reg_bit(chstat_reg, | ||
405 | OMAP2_MCSPI_CHSTAT_TXS) < 0) | ||
406 | dev_err(&spi->dev, "TXS timed out\n"); | ||
407 | else if (mcspi_wait_for_reg_bit(chstat_reg, | ||
408 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | ||
409 | dev_err(&spi->dev, "EOT timed out\n"); | ||
410 | } | ||
385 | } | 411 | } |
386 | 412 | ||
387 | if (rx != NULL) { | 413 | if (rx != NULL) { |
@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
435 | return count; | 461 | return count; |
436 | } | 462 | } |
437 | 463 | ||
438 | static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) | ||
439 | { | ||
440 | unsigned long timeout; | ||
441 | |||
442 | timeout = jiffies + msecs_to_jiffies(1000); | ||
443 | while (!(__raw_readl(reg) & bit)) { | ||
444 | if (time_after(jiffies, timeout)) | ||
445 | return -1; | ||
446 | cpu_relax(); | ||
447 | } | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static unsigned | 464 | static unsigned |
452 | omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | 465 | omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) |
453 | { | 466 | { |
@@ -489,10 +502,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
489 | dev_err(&spi->dev, "TXS timed out\n"); | 502 | dev_err(&spi->dev, "TXS timed out\n"); |
490 | goto out; | 503 | goto out; |
491 | } | 504 | } |
492 | #ifdef VERBOSE | 505 | dev_vdbg(&spi->dev, "write-%d %02x\n", |
493 | dev_dbg(&spi->dev, "write-%d %02x\n", | ||
494 | word_len, *tx); | 506 | word_len, *tx); |
495 | #endif | ||
496 | __raw_writel(*tx++, tx_reg); | 507 | __raw_writel(*tx++, tx_reg); |
497 | } | 508 | } |
498 | if (rx != NULL) { | 509 | if (rx != NULL) { |
@@ -506,10 +517,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
506 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 517 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
507 | omap2_mcspi_set_enable(spi, 0); | 518 | omap2_mcspi_set_enable(spi, 0); |
508 | *rx++ = __raw_readl(rx_reg); | 519 | *rx++ = __raw_readl(rx_reg); |
509 | #ifdef VERBOSE | 520 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
510 | dev_dbg(&spi->dev, "read-%d %02x\n", | ||
511 | word_len, *(rx - 1)); | 521 | word_len, *(rx - 1)); |
512 | #endif | ||
513 | if (mcspi_wait_for_reg_bit(chstat_reg, | 522 | if (mcspi_wait_for_reg_bit(chstat_reg, |
514 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 523 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
515 | dev_err(&spi->dev, | 524 | dev_err(&spi->dev, |
@@ -522,10 +531,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
522 | } | 531 | } |
523 | 532 | ||
524 | *rx++ = __raw_readl(rx_reg); | 533 | *rx++ = __raw_readl(rx_reg); |
525 | #ifdef VERBOSE | 534 | dev_vdbg(&spi->dev, "read-%d %02x\n", |
526 | dev_dbg(&spi->dev, "read-%d %02x\n", | ||
527 | word_len, *(rx - 1)); | 535 | word_len, *(rx - 1)); |
528 | #endif | ||
529 | } | 536 | } |
530 | } while (c); | 537 | } while (c); |
531 | } else if (word_len <= 16) { | 538 | } else if (word_len <= 16) { |
@@ -542,10 +549,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
542 | dev_err(&spi->dev, "TXS timed out\n"); | 549 | dev_err(&spi->dev, "TXS timed out\n"); |
543 | goto out; | 550 | goto out; |
544 | } | 551 | } |
545 | #ifdef VERBOSE | 552 | dev_vdbg(&spi->dev, "write-%d %04x\n", |
546 | dev_dbg(&spi->dev, "write-%d %04x\n", | ||
547 | word_len, *tx); | 553 | word_len, *tx); |
548 | #endif | ||
549 | __raw_writel(*tx++, tx_reg); | 554 | __raw_writel(*tx++, tx_reg); |
550 | } | 555 | } |
551 | if (rx != NULL) { | 556 | if (rx != NULL) { |
@@ -559,10 +564,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
559 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 564 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
560 | omap2_mcspi_set_enable(spi, 0); | 565 | omap2_mcspi_set_enable(spi, 0); |
561 | *rx++ = __raw_readl(rx_reg); | 566 | *rx++ = __raw_readl(rx_reg); |
562 | #ifdef VERBOSE | 567 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
563 | dev_dbg(&spi->dev, "read-%d %04x\n", | ||
564 | word_len, *(rx - 1)); | 568 | word_len, *(rx - 1)); |
565 | #endif | ||
566 | if (mcspi_wait_for_reg_bit(chstat_reg, | 569 | if (mcspi_wait_for_reg_bit(chstat_reg, |
567 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 570 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
568 | dev_err(&spi->dev, | 571 | dev_err(&spi->dev, |
@@ -575,10 +578,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
575 | } | 578 | } |
576 | 579 | ||
577 | *rx++ = __raw_readl(rx_reg); | 580 | *rx++ = __raw_readl(rx_reg); |
578 | #ifdef VERBOSE | 581 | dev_vdbg(&spi->dev, "read-%d %04x\n", |
579 | dev_dbg(&spi->dev, "read-%d %04x\n", | ||
580 | word_len, *(rx - 1)); | 582 | word_len, *(rx - 1)); |
581 | #endif | ||
582 | } | 583 | } |
583 | } while (c); | 584 | } while (c); |
584 | } else if (word_len <= 32) { | 585 | } else if (word_len <= 32) { |
@@ -595,10 +596,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
595 | dev_err(&spi->dev, "TXS timed out\n"); | 596 | dev_err(&spi->dev, "TXS timed out\n"); |
596 | goto out; | 597 | goto out; |
597 | } | 598 | } |
598 | #ifdef VERBOSE | 599 | dev_vdbg(&spi->dev, "write-%d %08x\n", |
599 | dev_dbg(&spi->dev, "write-%d %08x\n", | ||
600 | word_len, *tx); | 600 | word_len, *tx); |
601 | #endif | ||
602 | __raw_writel(*tx++, tx_reg); | 601 | __raw_writel(*tx++, tx_reg); |
603 | } | 602 | } |
604 | if (rx != NULL) { | 603 | if (rx != NULL) { |
@@ -612,10 +611,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
612 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { | 611 | (l & OMAP2_MCSPI_CHCONF_TURBO)) { |
613 | omap2_mcspi_set_enable(spi, 0); | 612 | omap2_mcspi_set_enable(spi, 0); |
614 | *rx++ = __raw_readl(rx_reg); | 613 | *rx++ = __raw_readl(rx_reg); |
615 | #ifdef VERBOSE | 614 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
616 | dev_dbg(&spi->dev, "read-%d %08x\n", | ||
617 | word_len, *(rx - 1)); | 615 | word_len, *(rx - 1)); |
618 | #endif | ||
619 | if (mcspi_wait_for_reg_bit(chstat_reg, | 616 | if (mcspi_wait_for_reg_bit(chstat_reg, |
620 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { | 617 | OMAP2_MCSPI_CHSTAT_RXS) < 0) { |
621 | dev_err(&spi->dev, | 618 | dev_err(&spi->dev, |
@@ -628,10 +625,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
628 | } | 625 | } |
629 | 626 | ||
630 | *rx++ = __raw_readl(rx_reg); | 627 | *rx++ = __raw_readl(rx_reg); |
631 | #ifdef VERBOSE | 628 | dev_vdbg(&spi->dev, "read-%d %08x\n", |
632 | dev_dbg(&spi->dev, "read-%d %08x\n", | ||
633 | word_len, *(rx - 1)); | 629 | word_len, *(rx - 1)); |
634 | #endif | ||
635 | } | 630 | } |
636 | } while (c); | 631 | } while (c); |
637 | } | 632 | } |
@@ -644,6 +639,12 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) | |||
644 | } else if (mcspi_wait_for_reg_bit(chstat_reg, | 639 | } else if (mcspi_wait_for_reg_bit(chstat_reg, |
645 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | 640 | OMAP2_MCSPI_CHSTAT_EOT) < 0) |
646 | dev_err(&spi->dev, "EOT timed out\n"); | 641 | dev_err(&spi->dev, "EOT timed out\n"); |
642 | |||
643 | /* disable chan to purge rx datas received in TX_ONLY transfer, | ||
644 | * otherwise these rx datas will affect the direct following | ||
645 | * RX_ONLY transfer. | ||
646 | */ | ||
647 | omap2_mcspi_set_enable(spi, 0); | ||
647 | } | 648 | } |
648 | out: | 649 | out: |
649 | omap2_mcspi_set_enable(spi, 1); | 650 | omap2_mcspi_set_enable(spi, 1); |
diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index 3aea50da7b29..0b677dc041ad 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c | |||
@@ -404,7 +404,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m) | |||
404 | goto msg_rejected; | 404 | goto msg_rejected; |
405 | } | 405 | } |
406 | 406 | ||
407 | if ((t != NULL) && t->bits_per_word) | 407 | if (t->bits_per_word) |
408 | bits_per_word = t->bits_per_word; | 408 | bits_per_word = t->bits_per_word; |
409 | 409 | ||
410 | if ((bits_per_word != 8) && (bits_per_word != 16)) { | 410 | if ((bits_per_word != 8) && (bits_per_word != 16)) { |
@@ -415,7 +415,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m) | |||
415 | goto msg_rejected; | 415 | goto msg_rejected; |
416 | } | 416 | } |
417 | /*make sure buffer length is even when working in 16 bit mode*/ | 417 | /*make sure buffer length is even when working in 16 bit mode*/ |
418 | if ((t != NULL) && (t->bits_per_word == 16) && (t->len & 1)) { | 418 | if ((t->bits_per_word == 16) && (t->len & 1)) { |
419 | dev_err(&spi->dev, | 419 | dev_err(&spi->dev, |
420 | "message rejected : " | 420 | "message rejected : " |
421 | "odd data length (%d) while in 16 bit mode\n", | 421 | "odd data length (%d) while in 16 bit mode\n", |
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 10a6dc3d37ac..ab483a0ec6d0 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip SPI Driver | 2 | * Blackfin On-Chip SPI Driver |
3 | * | 3 | * |
4 | * Copyright 2004-2007 Analog Devices Inc. | 4 | * Copyright 2004-2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Enter bugs at http://blackfin.uclinux.org/ | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
7 | * | 7 | * |
@@ -41,13 +41,16 @@ MODULE_LICENSE("GPL"); | |||
41 | #define RUNNING_STATE ((void *)1) | 41 | #define RUNNING_STATE ((void *)1) |
42 | #define DONE_STATE ((void *)2) | 42 | #define DONE_STATE ((void *)2) |
43 | #define ERROR_STATE ((void *)-1) | 43 | #define ERROR_STATE ((void *)-1) |
44 | #define QUEUE_RUNNING 0 | ||
45 | #define QUEUE_STOPPED 1 | ||
46 | 44 | ||
47 | /* Value to send if no TX value is supplied */ | 45 | struct bfin_spi_master_data; |
48 | #define SPI_IDLE_TXVAL 0x0000 | ||
49 | 46 | ||
50 | struct driver_data { | 47 | struct bfin_spi_transfer_ops { |
48 | void (*write) (struct bfin_spi_master_data *); | ||
49 | void (*read) (struct bfin_spi_master_data *); | ||
50 | void (*duplex) (struct bfin_spi_master_data *); | ||
51 | }; | ||
52 | |||
53 | struct bfin_spi_master_data { | ||
51 | /* Driver model hookup */ | 54 | /* Driver model hookup */ |
52 | struct platform_device *pdev; | 55 | struct platform_device *pdev; |
53 | 56 | ||
@@ -69,7 +72,7 @@ struct driver_data { | |||
69 | spinlock_t lock; | 72 | spinlock_t lock; |
70 | struct list_head queue; | 73 | struct list_head queue; |
71 | int busy; | 74 | int busy; |
72 | int run; | 75 | bool running; |
73 | 76 | ||
74 | /* Message Transfer pump */ | 77 | /* Message Transfer pump */ |
75 | struct tasklet_struct pump_transfers; | 78 | struct tasklet_struct pump_transfers; |
@@ -77,7 +80,7 @@ struct driver_data { | |||
77 | /* Current message transfer state info */ | 80 | /* Current message transfer state info */ |
78 | struct spi_message *cur_msg; | 81 | struct spi_message *cur_msg; |
79 | struct spi_transfer *cur_transfer; | 82 | struct spi_transfer *cur_transfer; |
80 | struct chip_data *cur_chip; | 83 | struct bfin_spi_slave_data *cur_chip; |
81 | size_t len_in_bytes; | 84 | size_t len_in_bytes; |
82 | size_t len; | 85 | size_t len; |
83 | void *tx; | 86 | void *tx; |
@@ -92,38 +95,37 @@ struct driver_data { | |||
92 | dma_addr_t rx_dma; | 95 | dma_addr_t rx_dma; |
93 | dma_addr_t tx_dma; | 96 | dma_addr_t tx_dma; |
94 | 97 | ||
98 | int irq_requested; | ||
99 | int spi_irq; | ||
100 | |||
95 | size_t rx_map_len; | 101 | size_t rx_map_len; |
96 | size_t tx_map_len; | 102 | size_t tx_map_len; |
97 | u8 n_bytes; | 103 | u8 n_bytes; |
104 | u16 ctrl_reg; | ||
105 | u16 flag_reg; | ||
106 | |||
98 | int cs_change; | 107 | int cs_change; |
99 | void (*write) (struct driver_data *); | 108 | const struct bfin_spi_transfer_ops *ops; |
100 | void (*read) (struct driver_data *); | ||
101 | void (*duplex) (struct driver_data *); | ||
102 | }; | 109 | }; |
103 | 110 | ||
104 | struct chip_data { | 111 | struct bfin_spi_slave_data { |
105 | u16 ctl_reg; | 112 | u16 ctl_reg; |
106 | u16 baud; | 113 | u16 baud; |
107 | u16 flag; | 114 | u16 flag; |
108 | 115 | ||
109 | u8 chip_select_num; | 116 | u8 chip_select_num; |
110 | u8 n_bytes; | ||
111 | u8 width; /* 0 or 1 */ | ||
112 | u8 enable_dma; | 117 | u8 enable_dma; |
113 | u8 bits_per_word; /* 8 or 16 */ | ||
114 | u8 cs_change_per_word; | ||
115 | u16 cs_chg_udelay; /* Some devices require > 255usec delay */ | 118 | u16 cs_chg_udelay; /* Some devices require > 255usec delay */ |
116 | u32 cs_gpio; | 119 | u32 cs_gpio; |
117 | u16 idle_tx_val; | 120 | u16 idle_tx_val; |
118 | void (*write) (struct driver_data *); | 121 | u8 pio_interrupt; /* use spi data irq */ |
119 | void (*read) (struct driver_data *); | 122 | const struct bfin_spi_transfer_ops *ops; |
120 | void (*duplex) (struct driver_data *); | ||
121 | }; | 123 | }; |
122 | 124 | ||
123 | #define DEFINE_SPI_REG(reg, off) \ | 125 | #define DEFINE_SPI_REG(reg, off) \ |
124 | static inline u16 read_##reg(struct driver_data *drv_data) \ | 126 | static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \ |
125 | { return bfin_read16(drv_data->regs_base + off); } \ | 127 | { return bfin_read16(drv_data->regs_base + off); } \ |
126 | static inline void write_##reg(struct driver_data *drv_data, u16 v) \ | 128 | static inline void write_##reg(struct bfin_spi_master_data *drv_data, u16 v) \ |
127 | { bfin_write16(drv_data->regs_base + off, v); } | 129 | { bfin_write16(drv_data->regs_base + off, v); } |
128 | 130 | ||
129 | DEFINE_SPI_REG(CTRL, 0x00) | 131 | DEFINE_SPI_REG(CTRL, 0x00) |
@@ -134,7 +136,7 @@ DEFINE_SPI_REG(RDBR, 0x10) | |||
134 | DEFINE_SPI_REG(BAUD, 0x14) | 136 | DEFINE_SPI_REG(BAUD, 0x14) |
135 | DEFINE_SPI_REG(SHAW, 0x18) | 137 | DEFINE_SPI_REG(SHAW, 0x18) |
136 | 138 | ||
137 | static void bfin_spi_enable(struct driver_data *drv_data) | 139 | static void bfin_spi_enable(struct bfin_spi_master_data *drv_data) |
138 | { | 140 | { |
139 | u16 cr; | 141 | u16 cr; |
140 | 142 | ||
@@ -142,7 +144,7 @@ static void bfin_spi_enable(struct driver_data *drv_data) | |||
142 | write_CTRL(drv_data, (cr | BIT_CTL_ENABLE)); | 144 | write_CTRL(drv_data, (cr | BIT_CTL_ENABLE)); |
143 | } | 145 | } |
144 | 146 | ||
145 | static void bfin_spi_disable(struct driver_data *drv_data) | 147 | static void bfin_spi_disable(struct bfin_spi_master_data *drv_data) |
146 | { | 148 | { |
147 | u16 cr; | 149 | u16 cr; |
148 | 150 | ||
@@ -165,7 +167,7 @@ static u16 hz_to_spi_baud(u32 speed_hz) | |||
165 | return spi_baud; | 167 | return spi_baud; |
166 | } | 168 | } |
167 | 169 | ||
168 | static int bfin_spi_flush(struct driver_data *drv_data) | 170 | static int bfin_spi_flush(struct bfin_spi_master_data *drv_data) |
169 | { | 171 | { |
170 | unsigned long limit = loops_per_jiffy << 1; | 172 | unsigned long limit = loops_per_jiffy << 1; |
171 | 173 | ||
@@ -179,13 +181,12 @@ static int bfin_spi_flush(struct driver_data *drv_data) | |||
179 | } | 181 | } |
180 | 182 | ||
181 | /* Chip select operation functions for cs_change flag */ | 183 | /* Chip select operation functions for cs_change flag */ |
182 | static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *chip) | 184 | static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip) |
183 | { | 185 | { |
184 | if (likely(chip->chip_select_num)) { | 186 | if (likely(chip->chip_select_num < MAX_CTRL_CS)) { |
185 | u16 flag = read_FLAG(drv_data); | 187 | u16 flag = read_FLAG(drv_data); |
186 | 188 | ||
187 | flag |= chip->flag; | 189 | flag &= ~chip->flag; |
188 | flag &= ~(chip->flag << 8); | ||
189 | 190 | ||
190 | write_FLAG(drv_data, flag); | 191 | write_FLAG(drv_data, flag); |
191 | } else { | 192 | } else { |
@@ -193,13 +194,13 @@ static void bfin_spi_cs_active(struct driver_data *drv_data, struct chip_data *c | |||
193 | } | 194 | } |
194 | } | 195 | } |
195 | 196 | ||
196 | static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data *chip) | 197 | static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data, |
198 | struct bfin_spi_slave_data *chip) | ||
197 | { | 199 | { |
198 | if (likely(chip->chip_select_num)) { | 200 | if (likely(chip->chip_select_num < MAX_CTRL_CS)) { |
199 | u16 flag = read_FLAG(drv_data); | 201 | u16 flag = read_FLAG(drv_data); |
200 | 202 | ||
201 | flag &= ~chip->flag; | 203 | flag |= chip->flag; |
202 | flag |= (chip->flag << 8); | ||
203 | 204 | ||
204 | write_FLAG(drv_data, flag); | 205 | write_FLAG(drv_data, flag); |
205 | } else { | 206 | } else { |
@@ -211,16 +212,43 @@ static void bfin_spi_cs_deactive(struct driver_data *drv_data, struct chip_data | |||
211 | udelay(chip->cs_chg_udelay); | 212 | udelay(chip->cs_chg_udelay); |
212 | } | 213 | } |
213 | 214 | ||
215 | /* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ | ||
216 | static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data, | ||
217 | struct bfin_spi_slave_data *chip) | ||
218 | { | ||
219 | if (chip->chip_select_num < MAX_CTRL_CS) { | ||
220 | u16 flag = read_FLAG(drv_data); | ||
221 | |||
222 | flag |= (chip->flag >> 8); | ||
223 | |||
224 | write_FLAG(drv_data, flag); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data, | ||
229 | struct bfin_spi_slave_data *chip) | ||
230 | { | ||
231 | if (chip->chip_select_num < MAX_CTRL_CS) { | ||
232 | u16 flag = read_FLAG(drv_data); | ||
233 | |||
234 | flag &= ~(chip->flag >> 8); | ||
235 | |||
236 | write_FLAG(drv_data, flag); | ||
237 | } | ||
238 | } | ||
239 | |||
214 | /* stop controller and re-config current chip*/ | 240 | /* stop controller and re-config current chip*/ |
215 | static void bfin_spi_restore_state(struct driver_data *drv_data) | 241 | static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data) |
216 | { | 242 | { |
217 | struct chip_data *chip = drv_data->cur_chip; | 243 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; |
218 | 244 | ||
219 | /* Clear status and disable clock */ | 245 | /* Clear status and disable clock */ |
220 | write_STAT(drv_data, BIT_STAT_CLR); | 246 | write_STAT(drv_data, BIT_STAT_CLR); |
221 | bfin_spi_disable(drv_data); | 247 | bfin_spi_disable(drv_data); |
222 | dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); | 248 | dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); |
223 | 249 | ||
250 | SSYNC(); | ||
251 | |||
224 | /* Load the registers */ | 252 | /* Load the registers */ |
225 | write_CTRL(drv_data, chip->ctl_reg); | 253 | write_CTRL(drv_data, chip->ctl_reg); |
226 | write_BAUD(drv_data, chip->baud); | 254 | write_BAUD(drv_data, chip->baud); |
@@ -230,49 +258,12 @@ static void bfin_spi_restore_state(struct driver_data *drv_data) | |||
230 | } | 258 | } |
231 | 259 | ||
232 | /* used to kick off transfer in rx mode and read unwanted RX data */ | 260 | /* used to kick off transfer in rx mode and read unwanted RX data */ |
233 | static inline void bfin_spi_dummy_read(struct driver_data *drv_data) | 261 | static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data) |
234 | { | 262 | { |
235 | (void) read_RDBR(drv_data); | 263 | (void) read_RDBR(drv_data); |
236 | } | 264 | } |
237 | 265 | ||
238 | static void bfin_spi_null_writer(struct driver_data *drv_data) | 266 | static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data) |
239 | { | ||
240 | u8 n_bytes = drv_data->n_bytes; | ||
241 | u16 tx_val = drv_data->cur_chip->idle_tx_val; | ||
242 | |||
243 | /* clear RXS (we check for RXS inside the loop) */ | ||
244 | bfin_spi_dummy_read(drv_data); | ||
245 | |||
246 | while (drv_data->tx < drv_data->tx_end) { | ||
247 | write_TDBR(drv_data, tx_val); | ||
248 | drv_data->tx += n_bytes; | ||
249 | /* wait until transfer finished. | ||
250 | checking SPIF or TXS may not guarantee transfer completion */ | ||
251 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
252 | cpu_relax(); | ||
253 | /* discard RX data and clear RXS */ | ||
254 | bfin_spi_dummy_read(drv_data); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | static void bfin_spi_null_reader(struct driver_data *drv_data) | ||
259 | { | ||
260 | u8 n_bytes = drv_data->n_bytes; | ||
261 | u16 tx_val = drv_data->cur_chip->idle_tx_val; | ||
262 | |||
263 | /* discard old RX data and clear RXS */ | ||
264 | bfin_spi_dummy_read(drv_data); | ||
265 | |||
266 | while (drv_data->rx < drv_data->rx_end) { | ||
267 | write_TDBR(drv_data, tx_val); | ||
268 | drv_data->rx += n_bytes; | ||
269 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
270 | cpu_relax(); | ||
271 | bfin_spi_dummy_read(drv_data); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | static void bfin_spi_u8_writer(struct driver_data *drv_data) | ||
276 | { | 267 | { |
277 | /* clear RXS (we check for RXS inside the loop) */ | 268 | /* clear RXS (we check for RXS inside the loop) */ |
278 | bfin_spi_dummy_read(drv_data); | 269 | bfin_spi_dummy_read(drv_data); |
@@ -288,25 +279,7 @@ static void bfin_spi_u8_writer(struct driver_data *drv_data) | |||
288 | } | 279 | } |
289 | } | 280 | } |
290 | 281 | ||
291 | static void bfin_spi_u8_cs_chg_writer(struct driver_data *drv_data) | 282 | static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data) |
292 | { | ||
293 | struct chip_data *chip = drv_data->cur_chip; | ||
294 | |||
295 | /* clear RXS (we check for RXS inside the loop) */ | ||
296 | bfin_spi_dummy_read(drv_data); | ||
297 | |||
298 | while (drv_data->tx < drv_data->tx_end) { | ||
299 | bfin_spi_cs_active(drv_data, chip); | ||
300 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx++))); | ||
301 | /* make sure transfer finished before deactiving CS */ | ||
302 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
303 | cpu_relax(); | ||
304 | bfin_spi_dummy_read(drv_data); | ||
305 | bfin_spi_cs_deactive(drv_data, chip); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static void bfin_spi_u8_reader(struct driver_data *drv_data) | ||
310 | { | 283 | { |
311 | u16 tx_val = drv_data->cur_chip->idle_tx_val; | 284 | u16 tx_val = drv_data->cur_chip->idle_tx_val; |
312 | 285 | ||
@@ -321,25 +294,7 @@ static void bfin_spi_u8_reader(struct driver_data *drv_data) | |||
321 | } | 294 | } |
322 | } | 295 | } |
323 | 296 | ||
324 | static void bfin_spi_u8_cs_chg_reader(struct driver_data *drv_data) | 297 | static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data) |
325 | { | ||
326 | struct chip_data *chip = drv_data->cur_chip; | ||
327 | u16 tx_val = chip->idle_tx_val; | ||
328 | |||
329 | /* discard old RX data and clear RXS */ | ||
330 | bfin_spi_dummy_read(drv_data); | ||
331 | |||
332 | while (drv_data->rx < drv_data->rx_end) { | ||
333 | bfin_spi_cs_active(drv_data, chip); | ||
334 | write_TDBR(drv_data, tx_val); | ||
335 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
336 | cpu_relax(); | ||
337 | *(u8 *) (drv_data->rx++) = read_RDBR(drv_data); | ||
338 | bfin_spi_cs_deactive(drv_data, chip); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | static void bfin_spi_u8_duplex(struct driver_data *drv_data) | ||
343 | { | 298 | { |
344 | /* discard old RX data and clear RXS */ | 299 | /* discard old RX data and clear RXS */ |
345 | bfin_spi_dummy_read(drv_data); | 300 | bfin_spi_dummy_read(drv_data); |
@@ -352,24 +307,13 @@ static void bfin_spi_u8_duplex(struct driver_data *drv_data) | |||
352 | } | 307 | } |
353 | } | 308 | } |
354 | 309 | ||
355 | static void bfin_spi_u8_cs_chg_duplex(struct driver_data *drv_data) | 310 | static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { |
356 | { | 311 | .write = bfin_spi_u8_writer, |
357 | struct chip_data *chip = drv_data->cur_chip; | 312 | .read = bfin_spi_u8_reader, |
358 | 313 | .duplex = bfin_spi_u8_duplex, | |
359 | /* discard old RX data and clear RXS */ | 314 | }; |
360 | bfin_spi_dummy_read(drv_data); | ||
361 | |||
362 | while (drv_data->rx < drv_data->rx_end) { | ||
363 | bfin_spi_cs_active(drv_data, chip); | ||
364 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx++))); | ||
365 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
366 | cpu_relax(); | ||
367 | *(u8 *) (drv_data->rx++) = read_RDBR(drv_data); | ||
368 | bfin_spi_cs_deactive(drv_data, chip); | ||
369 | } | ||
370 | } | ||
371 | 315 | ||
372 | static void bfin_spi_u16_writer(struct driver_data *drv_data) | 316 | static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data) |
373 | { | 317 | { |
374 | /* clear RXS (we check for RXS inside the loop) */ | 318 | /* clear RXS (we check for RXS inside the loop) */ |
375 | bfin_spi_dummy_read(drv_data); | 319 | bfin_spi_dummy_read(drv_data); |
@@ -386,26 +330,7 @@ static void bfin_spi_u16_writer(struct driver_data *drv_data) | |||
386 | } | 330 | } |
387 | } | 331 | } |
388 | 332 | ||
389 | static void bfin_spi_u16_cs_chg_writer(struct driver_data *drv_data) | 333 | static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data) |
390 | { | ||
391 | struct chip_data *chip = drv_data->cur_chip; | ||
392 | |||
393 | /* clear RXS (we check for RXS inside the loop) */ | ||
394 | bfin_spi_dummy_read(drv_data); | ||
395 | |||
396 | while (drv_data->tx < drv_data->tx_end) { | ||
397 | bfin_spi_cs_active(drv_data, chip); | ||
398 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | ||
399 | drv_data->tx += 2; | ||
400 | /* make sure transfer finished before deactiving CS */ | ||
401 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
402 | cpu_relax(); | ||
403 | bfin_spi_dummy_read(drv_data); | ||
404 | bfin_spi_cs_deactive(drv_data, chip); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | static void bfin_spi_u16_reader(struct driver_data *drv_data) | ||
409 | { | 334 | { |
410 | u16 tx_val = drv_data->cur_chip->idle_tx_val; | 335 | u16 tx_val = drv_data->cur_chip->idle_tx_val; |
411 | 336 | ||
@@ -421,26 +346,7 @@ static void bfin_spi_u16_reader(struct driver_data *drv_data) | |||
421 | } | 346 | } |
422 | } | 347 | } |
423 | 348 | ||
424 | static void bfin_spi_u16_cs_chg_reader(struct driver_data *drv_data) | 349 | static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data) |
425 | { | ||
426 | struct chip_data *chip = drv_data->cur_chip; | ||
427 | u16 tx_val = chip->idle_tx_val; | ||
428 | |||
429 | /* discard old RX data and clear RXS */ | ||
430 | bfin_spi_dummy_read(drv_data); | ||
431 | |||
432 | while (drv_data->rx < drv_data->rx_end) { | ||
433 | bfin_spi_cs_active(drv_data, chip); | ||
434 | write_TDBR(drv_data, tx_val); | ||
435 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
436 | cpu_relax(); | ||
437 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | ||
438 | drv_data->rx += 2; | ||
439 | bfin_spi_cs_deactive(drv_data, chip); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static void bfin_spi_u16_duplex(struct driver_data *drv_data) | ||
444 | { | 350 | { |
445 | /* discard old RX data and clear RXS */ | 351 | /* discard old RX data and clear RXS */ |
446 | bfin_spi_dummy_read(drv_data); | 352 | bfin_spi_dummy_read(drv_data); |
@@ -455,27 +361,14 @@ static void bfin_spi_u16_duplex(struct driver_data *drv_data) | |||
455 | } | 361 | } |
456 | } | 362 | } |
457 | 363 | ||
458 | static void bfin_spi_u16_cs_chg_duplex(struct driver_data *drv_data) | 364 | static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { |
459 | { | 365 | .write = bfin_spi_u16_writer, |
460 | struct chip_data *chip = drv_data->cur_chip; | 366 | .read = bfin_spi_u16_reader, |
461 | 367 | .duplex = bfin_spi_u16_duplex, | |
462 | /* discard old RX data and clear RXS */ | 368 | }; |
463 | bfin_spi_dummy_read(drv_data); | ||
464 | |||
465 | while (drv_data->rx < drv_data->rx_end) { | ||
466 | bfin_spi_cs_active(drv_data, chip); | ||
467 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | ||
468 | drv_data->tx += 2; | ||
469 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
470 | cpu_relax(); | ||
471 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | ||
472 | drv_data->rx += 2; | ||
473 | bfin_spi_cs_deactive(drv_data, chip); | ||
474 | } | ||
475 | } | ||
476 | 369 | ||
477 | /* test if ther is more transfer to be done */ | 370 | /* test if there is more transfer to be done */ |
478 | static void *bfin_spi_next_transfer(struct driver_data *drv_data) | 371 | static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data) |
479 | { | 372 | { |
480 | struct spi_message *msg = drv_data->cur_msg; | 373 | struct spi_message *msg = drv_data->cur_msg; |
481 | struct spi_transfer *trans = drv_data->cur_transfer; | 374 | struct spi_transfer *trans = drv_data->cur_transfer; |
@@ -494,9 +387,9 @@ static void *bfin_spi_next_transfer(struct driver_data *drv_data) | |||
494 | * caller already set message->status; | 387 | * caller already set message->status; |
495 | * dma and pio irqs are blocked give finished message back | 388 | * dma and pio irqs are blocked give finished message back |
496 | */ | 389 | */ |
497 | static void bfin_spi_giveback(struct driver_data *drv_data) | 390 | static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data) |
498 | { | 391 | { |
499 | struct chip_data *chip = drv_data->cur_chip; | 392 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; |
500 | struct spi_transfer *last_transfer; | 393 | struct spi_transfer *last_transfer; |
501 | unsigned long flags; | 394 | unsigned long flags; |
502 | struct spi_message *msg; | 395 | struct spi_message *msg; |
@@ -525,10 +418,83 @@ static void bfin_spi_giveback(struct driver_data *drv_data) | |||
525 | msg->complete(msg->context); | 418 | msg->complete(msg->context); |
526 | } | 419 | } |
527 | 420 | ||
421 | /* spi data irq handler */ | ||
422 | static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) | ||
423 | { | ||
424 | struct bfin_spi_master_data *drv_data = dev_id; | ||
425 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; | ||
426 | struct spi_message *msg = drv_data->cur_msg; | ||
427 | int n_bytes = drv_data->n_bytes; | ||
428 | |||
429 | /* wait until transfer finished. */ | ||
430 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
431 | cpu_relax(); | ||
432 | |||
433 | if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) || | ||
434 | (drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) { | ||
435 | /* last read */ | ||
436 | if (drv_data->rx) { | ||
437 | dev_dbg(&drv_data->pdev->dev, "last read\n"); | ||
438 | if (n_bytes == 2) | ||
439 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | ||
440 | else if (n_bytes == 1) | ||
441 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | ||
442 | drv_data->rx += n_bytes; | ||
443 | } | ||
444 | |||
445 | msg->actual_length += drv_data->len_in_bytes; | ||
446 | if (drv_data->cs_change) | ||
447 | bfin_spi_cs_deactive(drv_data, chip); | ||
448 | /* Move to next transfer */ | ||
449 | msg->state = bfin_spi_next_transfer(drv_data); | ||
450 | |||
451 | disable_irq_nosync(drv_data->spi_irq); | ||
452 | |||
453 | /* Schedule transfer tasklet */ | ||
454 | tasklet_schedule(&drv_data->pump_transfers); | ||
455 | return IRQ_HANDLED; | ||
456 | } | ||
457 | |||
458 | if (drv_data->rx && drv_data->tx) { | ||
459 | /* duplex */ | ||
460 | dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); | ||
461 | if (drv_data->n_bytes == 2) { | ||
462 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | ||
463 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | ||
464 | } else if (drv_data->n_bytes == 1) { | ||
465 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | ||
466 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | ||
467 | } | ||
468 | } else if (drv_data->rx) { | ||
469 | /* read */ | ||
470 | dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); | ||
471 | if (drv_data->n_bytes == 2) | ||
472 | *(u16 *) (drv_data->rx) = read_RDBR(drv_data); | ||
473 | else if (drv_data->n_bytes == 1) | ||
474 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | ||
475 | write_TDBR(drv_data, chip->idle_tx_val); | ||
476 | } else if (drv_data->tx) { | ||
477 | /* write */ | ||
478 | dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); | ||
479 | bfin_spi_dummy_read(drv_data); | ||
480 | if (drv_data->n_bytes == 2) | ||
481 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | ||
482 | else if (drv_data->n_bytes == 1) | ||
483 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | ||
484 | } | ||
485 | |||
486 | if (drv_data->tx) | ||
487 | drv_data->tx += n_bytes; | ||
488 | if (drv_data->rx) | ||
489 | drv_data->rx += n_bytes; | ||
490 | |||
491 | return IRQ_HANDLED; | ||
492 | } | ||
493 | |||
528 | static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) | 494 | static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) |
529 | { | 495 | { |
530 | struct driver_data *drv_data = dev_id; | 496 | struct bfin_spi_master_data *drv_data = dev_id; |
531 | struct chip_data *chip = drv_data->cur_chip; | 497 | struct bfin_spi_slave_data *chip = drv_data->cur_chip; |
532 | struct spi_message *msg = drv_data->cur_msg; | 498 | struct spi_message *msg = drv_data->cur_msg; |
533 | unsigned long timeout; | 499 | unsigned long timeout; |
534 | unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel); | 500 | unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel); |
@@ -540,10 +506,6 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) | |||
540 | 506 | ||
541 | clear_dma_irqstat(drv_data->dma_channel); | 507 | clear_dma_irqstat(drv_data->dma_channel); |
542 | 508 | ||
543 | /* Wait for DMA to complete */ | ||
544 | while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN) | ||
545 | cpu_relax(); | ||
546 | |||
547 | /* | 509 | /* |
548 | * wait for the last transaction shifted out. HRM states: | 510 | * wait for the last transaction shifted out. HRM states: |
549 | * at this point there may still be data in the SPI DMA FIFO waiting | 511 | * at this point there may still be data in the SPI DMA FIFO waiting |
@@ -551,8 +513,8 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) | |||
551 | * register until it goes low for 2 successive reads | 513 | * register until it goes low for 2 successive reads |
552 | */ | 514 | */ |
553 | if (drv_data->tx != NULL) { | 515 | if (drv_data->tx != NULL) { |
554 | while ((read_STAT(drv_data) & TXS) || | 516 | while ((read_STAT(drv_data) & BIT_STAT_TXS) || |
555 | (read_STAT(drv_data) & TXS)) | 517 | (read_STAT(drv_data) & BIT_STAT_TXS)) |
556 | cpu_relax(); | 518 | cpu_relax(); |
557 | } | 519 | } |
558 | 520 | ||
@@ -561,14 +523,14 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) | |||
561 | dmastat, read_STAT(drv_data)); | 523 | dmastat, read_STAT(drv_data)); |
562 | 524 | ||
563 | timeout = jiffies + HZ; | 525 | timeout = jiffies + HZ; |
564 | while (!(read_STAT(drv_data) & SPIF)) | 526 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
565 | if (!time_before(jiffies, timeout)) { | 527 | if (!time_before(jiffies, timeout)) { |
566 | dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF"); | 528 | dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF"); |
567 | break; | 529 | break; |
568 | } else | 530 | } else |
569 | cpu_relax(); | 531 | cpu_relax(); |
570 | 532 | ||
571 | if ((dmastat & DMA_ERR) && (spistat & RBSY)) { | 533 | if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) { |
572 | msg->state = ERROR_STATE; | 534 | msg->state = ERROR_STATE; |
573 | dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n"); | 535 | dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n"); |
574 | } else { | 536 | } else { |
@@ -588,20 +550,20 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) | |||
588 | dev_dbg(&drv_data->pdev->dev, | 550 | dev_dbg(&drv_data->pdev->dev, |
589 | "disable dma channel irq%d\n", | 551 | "disable dma channel irq%d\n", |
590 | drv_data->dma_channel); | 552 | drv_data->dma_channel); |
591 | dma_disable_irq(drv_data->dma_channel); | 553 | dma_disable_irq_nosync(drv_data->dma_channel); |
592 | 554 | ||
593 | return IRQ_HANDLED; | 555 | return IRQ_HANDLED; |
594 | } | 556 | } |
595 | 557 | ||
596 | static void bfin_spi_pump_transfers(unsigned long data) | 558 | static void bfin_spi_pump_transfers(unsigned long data) |
597 | { | 559 | { |
598 | struct driver_data *drv_data = (struct driver_data *)data; | 560 | struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data; |
599 | struct spi_message *message = NULL; | 561 | struct spi_message *message = NULL; |
600 | struct spi_transfer *transfer = NULL; | 562 | struct spi_transfer *transfer = NULL; |
601 | struct spi_transfer *previous = NULL; | 563 | struct spi_transfer *previous = NULL; |
602 | struct chip_data *chip = NULL; | 564 | struct bfin_spi_slave_data *chip = NULL; |
603 | u8 width; | 565 | unsigned int bits_per_word; |
604 | u16 cr, dma_width, dma_config; | 566 | u16 cr, cr_width, dma_width, dma_config; |
605 | u32 tranf_success = 1; | 567 | u32 tranf_success = 1; |
606 | u8 full_duplex = 0; | 568 | u8 full_duplex = 0; |
607 | 569 | ||
@@ -639,7 +601,7 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
639 | udelay(previous->delay_usecs); | 601 | udelay(previous->delay_usecs); |
640 | } | 602 | } |
641 | 603 | ||
642 | /* Setup the transfer state based on the type of transfer */ | 604 | /* Flush any existing transfers that may be sitting in the hardware */ |
643 | if (bfin_spi_flush(drv_data) == 0) { | 605 | if (bfin_spi_flush(drv_data) == 0) { |
644 | dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); | 606 | dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); |
645 | message->status = -EIO; | 607 | message->status = -EIO; |
@@ -679,52 +641,31 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
679 | drv_data->cs_change = transfer->cs_change; | 641 | drv_data->cs_change = transfer->cs_change; |
680 | 642 | ||
681 | /* Bits per word setup */ | 643 | /* Bits per word setup */ |
682 | switch (transfer->bits_per_word) { | 644 | bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word; |
683 | case 8: | 645 | if (bits_per_word == 8) { |
684 | drv_data->n_bytes = 1; | 646 | drv_data->n_bytes = 1; |
685 | width = CFG_SPI_WORDSIZE8; | 647 | drv_data->len = transfer->len; |
686 | drv_data->read = chip->cs_change_per_word ? | 648 | cr_width = 0; |
687 | bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader; | 649 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; |
688 | drv_data->write = chip->cs_change_per_word ? | 650 | } else if (bits_per_word == 16) { |
689 | bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer; | ||
690 | drv_data->duplex = chip->cs_change_per_word ? | ||
691 | bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex; | ||
692 | break; | ||
693 | |||
694 | case 16: | ||
695 | drv_data->n_bytes = 2; | 651 | drv_data->n_bytes = 2; |
696 | width = CFG_SPI_WORDSIZE16; | ||
697 | drv_data->read = chip->cs_change_per_word ? | ||
698 | bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader; | ||
699 | drv_data->write = chip->cs_change_per_word ? | ||
700 | bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer; | ||
701 | drv_data->duplex = chip->cs_change_per_word ? | ||
702 | bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex; | ||
703 | break; | ||
704 | |||
705 | default: | ||
706 | /* No change, the same as default setting */ | ||
707 | drv_data->n_bytes = chip->n_bytes; | ||
708 | width = chip->width; | ||
709 | drv_data->write = drv_data->tx ? chip->write : bfin_spi_null_writer; | ||
710 | drv_data->read = drv_data->rx ? chip->read : bfin_spi_null_reader; | ||
711 | drv_data->duplex = chip->duplex ? chip->duplex : bfin_spi_null_writer; | ||
712 | break; | ||
713 | } | ||
714 | cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); | ||
715 | cr |= (width << 8); | ||
716 | write_CTRL(drv_data, cr); | ||
717 | |||
718 | if (width == CFG_SPI_WORDSIZE16) { | ||
719 | drv_data->len = (transfer->len) >> 1; | 652 | drv_data->len = (transfer->len) >> 1; |
653 | cr_width = BIT_CTL_WORDSIZE; | ||
654 | drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; | ||
720 | } else { | 655 | } else { |
721 | drv_data->len = transfer->len; | 656 | dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n"); |
657 | message->status = -EINVAL; | ||
658 | bfin_spi_giveback(drv_data); | ||
659 | return; | ||
722 | } | 660 | } |
661 | cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE); | ||
662 | cr |= cr_width; | ||
663 | write_CTRL(drv_data, cr); | ||
664 | |||
723 | dev_dbg(&drv_data->pdev->dev, | 665 | dev_dbg(&drv_data->pdev->dev, |
724 | "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n", | 666 | "transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n", |
725 | drv_data->write, chip->write, bfin_spi_null_writer); | 667 | drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8); |
726 | 668 | ||
727 | /* speed and width has been set on per message */ | ||
728 | message->state = RUNNING_STATE; | 669 | message->state = RUNNING_STATE; |
729 | dma_config = 0; | 670 | dma_config = 0; |
730 | 671 | ||
@@ -735,13 +676,11 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
735 | write_BAUD(drv_data, chip->baud); | 676 | write_BAUD(drv_data, chip->baud); |
736 | 677 | ||
737 | write_STAT(drv_data, BIT_STAT_CLR); | 678 | write_STAT(drv_data, BIT_STAT_CLR); |
738 | cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD)); | 679 | bfin_spi_cs_active(drv_data, chip); |
739 | if (drv_data->cs_change) | ||
740 | bfin_spi_cs_active(drv_data, chip); | ||
741 | 680 | ||
742 | dev_dbg(&drv_data->pdev->dev, | 681 | dev_dbg(&drv_data->pdev->dev, |
743 | "now pumping a transfer: width is %d, len is %d\n", | 682 | "now pumping a transfer: width is %d, len is %d\n", |
744 | width, transfer->len); | 683 | cr_width, transfer->len); |
745 | 684 | ||
746 | /* | 685 | /* |
747 | * Try to map dma buffer and do a dma transfer. If successful use, | 686 | * Try to map dma buffer and do a dma transfer. If successful use, |
@@ -760,7 +699,7 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
760 | /* config dma channel */ | 699 | /* config dma channel */ |
761 | dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n"); | 700 | dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n"); |
762 | set_dma_x_count(drv_data->dma_channel, drv_data->len); | 701 | set_dma_x_count(drv_data->dma_channel, drv_data->len); |
763 | if (width == CFG_SPI_WORDSIZE16) { | 702 | if (cr_width == BIT_CTL_WORDSIZE) { |
764 | set_dma_x_modify(drv_data->dma_channel, 2); | 703 | set_dma_x_modify(drv_data->dma_channel, 2); |
765 | dma_width = WDSIZE_16; | 704 | dma_width = WDSIZE_16; |
766 | } else { | 705 | } else { |
@@ -846,73 +785,100 @@ static void bfin_spi_pump_transfers(unsigned long data) | |||
846 | dma_enable_irq(drv_data->dma_channel); | 785 | dma_enable_irq(drv_data->dma_channel); |
847 | local_irq_restore(flags); | 786 | local_irq_restore(flags); |
848 | 787 | ||
849 | } else { | 788 | return; |
850 | /* IO mode write then read */ | 789 | } |
851 | dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n"); | ||
852 | |||
853 | /* we always use SPI_WRITE mode. SPI_READ mode | ||
854 | seems to have problems with setting up the | ||
855 | output value in TDBR prior to the transfer. */ | ||
856 | write_CTRL(drv_data, (cr | CFG_SPI_WRITE)); | ||
857 | |||
858 | if (full_duplex) { | ||
859 | /* full duplex mode */ | ||
860 | BUG_ON((drv_data->tx_end - drv_data->tx) != | ||
861 | (drv_data->rx_end - drv_data->rx)); | ||
862 | dev_dbg(&drv_data->pdev->dev, | ||
863 | "IO duplex: cr is 0x%x\n", cr); | ||
864 | |||
865 | drv_data->duplex(drv_data); | ||
866 | 790 | ||
867 | if (drv_data->tx != drv_data->tx_end) | 791 | /* |
868 | tranf_success = 0; | 792 | * We always use SPI_WRITE mode (transfer starts with TDBR write). |
869 | } else if (drv_data->tx != NULL) { | 793 | * SPI_READ mode (transfer starts with RDBR read) seems to have |
870 | /* write only half duplex */ | 794 | * problems with setting up the output value in TDBR prior to the |
871 | dev_dbg(&drv_data->pdev->dev, | 795 | * start of the transfer. |
872 | "IO write: cr is 0x%x\n", cr); | 796 | */ |
797 | write_CTRL(drv_data, cr | BIT_CTL_TXMOD); | ||
873 | 798 | ||
874 | drv_data->write(drv_data); | 799 | if (chip->pio_interrupt) { |
800 | /* SPI irq should have been disabled by now */ | ||
875 | 801 | ||
876 | if (drv_data->tx != drv_data->tx_end) | 802 | /* discard old RX data and clear RXS */ |
877 | tranf_success = 0; | 803 | bfin_spi_dummy_read(drv_data); |
878 | } else if (drv_data->rx != NULL) { | ||
879 | /* read only half duplex */ | ||
880 | dev_dbg(&drv_data->pdev->dev, | ||
881 | "IO read: cr is 0x%x\n", cr); | ||
882 | 804 | ||
883 | drv_data->read(drv_data); | 805 | /* start transfer */ |
884 | if (drv_data->rx != drv_data->rx_end) | 806 | if (drv_data->tx == NULL) |
885 | tranf_success = 0; | 807 | write_TDBR(drv_data, chip->idle_tx_val); |
808 | else { | ||
809 | if (bits_per_word == 8) | ||
810 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | ||
811 | else | ||
812 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | ||
813 | drv_data->tx += drv_data->n_bytes; | ||
886 | } | 814 | } |
887 | 815 | ||
888 | if (!tranf_success) { | 816 | /* once TDBR is empty, interrupt is triggered */ |
889 | dev_dbg(&drv_data->pdev->dev, | 817 | enable_irq(drv_data->spi_irq); |
890 | "IO write error!\n"); | 818 | return; |
891 | message->state = ERROR_STATE; | 819 | } |
892 | } else { | 820 | |
893 | /* Update total byte transfered */ | 821 | /* IO mode */ |
894 | message->actual_length += drv_data->len_in_bytes; | 822 | dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n"); |
895 | /* Move to next transfer of this msg */ | 823 | |
896 | message->state = bfin_spi_next_transfer(drv_data); | 824 | if (full_duplex) { |
897 | if (drv_data->cs_change) | 825 | /* full duplex mode */ |
898 | bfin_spi_cs_deactive(drv_data, chip); | 826 | BUG_ON((drv_data->tx_end - drv_data->tx) != |
899 | } | 827 | (drv_data->rx_end - drv_data->rx)); |
900 | /* Schedule next transfer tasklet */ | 828 | dev_dbg(&drv_data->pdev->dev, |
901 | tasklet_schedule(&drv_data->pump_transfers); | 829 | "IO duplex: cr is 0x%x\n", cr); |
830 | |||
831 | drv_data->ops->duplex(drv_data); | ||
832 | |||
833 | if (drv_data->tx != drv_data->tx_end) | ||
834 | tranf_success = 0; | ||
835 | } else if (drv_data->tx != NULL) { | ||
836 | /* write only half duplex */ | ||
837 | dev_dbg(&drv_data->pdev->dev, | ||
838 | "IO write: cr is 0x%x\n", cr); | ||
839 | |||
840 | drv_data->ops->write(drv_data); | ||
841 | |||
842 | if (drv_data->tx != drv_data->tx_end) | ||
843 | tranf_success = 0; | ||
844 | } else if (drv_data->rx != NULL) { | ||
845 | /* read only half duplex */ | ||
846 | dev_dbg(&drv_data->pdev->dev, | ||
847 | "IO read: cr is 0x%x\n", cr); | ||
848 | |||
849 | drv_data->ops->read(drv_data); | ||
850 | if (drv_data->rx != drv_data->rx_end) | ||
851 | tranf_success = 0; | ||
852 | } | ||
853 | |||
854 | if (!tranf_success) { | ||
855 | dev_dbg(&drv_data->pdev->dev, | ||
856 | "IO write error!\n"); | ||
857 | message->state = ERROR_STATE; | ||
858 | } else { | ||
859 | /* Update total byte transfered */ | ||
860 | message->actual_length += drv_data->len_in_bytes; | ||
861 | /* Move to next transfer of this msg */ | ||
862 | message->state = bfin_spi_next_transfer(drv_data); | ||
863 | if (drv_data->cs_change) | ||
864 | bfin_spi_cs_deactive(drv_data, chip); | ||
902 | } | 865 | } |
866 | |||
867 | /* Schedule next transfer tasklet */ | ||
868 | tasklet_schedule(&drv_data->pump_transfers); | ||
903 | } | 869 | } |
904 | 870 | ||
905 | /* pop a msg from queue and kick off real transfer */ | 871 | /* pop a msg from queue and kick off real transfer */ |
906 | static void bfin_spi_pump_messages(struct work_struct *work) | 872 | static void bfin_spi_pump_messages(struct work_struct *work) |
907 | { | 873 | { |
908 | struct driver_data *drv_data; | 874 | struct bfin_spi_master_data *drv_data; |
909 | unsigned long flags; | 875 | unsigned long flags; |
910 | 876 | ||
911 | drv_data = container_of(work, struct driver_data, pump_messages); | 877 | drv_data = container_of(work, struct bfin_spi_master_data, pump_messages); |
912 | 878 | ||
913 | /* Lock queue and check for queue work */ | 879 | /* Lock queue and check for queue work */ |
914 | spin_lock_irqsave(&drv_data->lock, flags); | 880 | spin_lock_irqsave(&drv_data->lock, flags); |
915 | if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { | 881 | if (list_empty(&drv_data->queue) || !drv_data->running) { |
916 | /* pumper kicked off but no work to do */ | 882 | /* pumper kicked off but no work to do */ |
917 | drv_data->busy = 0; | 883 | drv_data->busy = 0; |
918 | spin_unlock_irqrestore(&drv_data->lock, flags); | 884 | spin_unlock_irqrestore(&drv_data->lock, flags); |
@@ -962,12 +928,12 @@ static void bfin_spi_pump_messages(struct work_struct *work) | |||
962 | */ | 928 | */ |
963 | static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) | 929 | static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) |
964 | { | 930 | { |
965 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 931 | struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); |
966 | unsigned long flags; | 932 | unsigned long flags; |
967 | 933 | ||
968 | spin_lock_irqsave(&drv_data->lock, flags); | 934 | spin_lock_irqsave(&drv_data->lock, flags); |
969 | 935 | ||
970 | if (drv_data->run == QUEUE_STOPPED) { | 936 | if (!drv_data->running) { |
971 | spin_unlock_irqrestore(&drv_data->lock, flags); | 937 | spin_unlock_irqrestore(&drv_data->lock, flags); |
972 | return -ESHUTDOWN; | 938 | return -ESHUTDOWN; |
973 | } | 939 | } |
@@ -979,7 +945,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
979 | dev_dbg(&spi->dev, "adding an msg in transfer() \n"); | 945 | dev_dbg(&spi->dev, "adding an msg in transfer() \n"); |
980 | list_add_tail(&msg->queue, &drv_data->queue); | 946 | list_add_tail(&msg->queue, &drv_data->queue); |
981 | 947 | ||
982 | if (drv_data->run == QUEUE_RUNNING && !drv_data->busy) | 948 | if (drv_data->running && !drv_data->busy) |
983 | queue_work(drv_data->workqueue, &drv_data->pump_messages); | 949 | queue_work(drv_data->workqueue, &drv_data->pump_messages); |
984 | 950 | ||
985 | spin_unlock_irqrestore(&drv_data->lock, flags); | 951 | spin_unlock_irqrestore(&drv_data->lock, flags); |
@@ -1003,147 +969,184 @@ static u16 ssel[][MAX_SPI_SSEL] = { | |||
1003 | P_SPI2_SSEL6, P_SPI2_SSEL7}, | 969 | P_SPI2_SSEL6, P_SPI2_SSEL7}, |
1004 | }; | 970 | }; |
1005 | 971 | ||
1006 | /* first setup for new devices */ | 972 | /* setup for devices (may be called multiple times -- not just first setup) */ |
1007 | static int bfin_spi_setup(struct spi_device *spi) | 973 | static int bfin_spi_setup(struct spi_device *spi) |
1008 | { | 974 | { |
1009 | struct bfin5xx_spi_chip *chip_info = NULL; | 975 | struct bfin5xx_spi_chip *chip_info; |
1010 | struct chip_data *chip; | 976 | struct bfin_spi_slave_data *chip = NULL; |
1011 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 977 | struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); |
1012 | int ret; | 978 | u16 bfin_ctl_reg; |
1013 | 979 | int ret = -EINVAL; | |
1014 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) | ||
1015 | return -EINVAL; | ||
1016 | 980 | ||
1017 | /* Only alloc (or use chip_info) on first setup */ | 981 | /* Only alloc (or use chip_info) on first setup */ |
982 | chip_info = NULL; | ||
1018 | chip = spi_get_ctldata(spi); | 983 | chip = spi_get_ctldata(spi); |
1019 | if (chip == NULL) { | 984 | if (chip == NULL) { |
1020 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | 985 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1021 | if (!chip) | 986 | if (!chip) { |
1022 | return -ENOMEM; | 987 | dev_err(&spi->dev, "cannot allocate chip data\n"); |
988 | ret = -ENOMEM; | ||
989 | goto error; | ||
990 | } | ||
1023 | 991 | ||
1024 | chip->enable_dma = 0; | 992 | chip->enable_dma = 0; |
1025 | chip_info = spi->controller_data; | 993 | chip_info = spi->controller_data; |
1026 | } | 994 | } |
1027 | 995 | ||
996 | /* Let people set non-standard bits directly */ | ||
997 | bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO | | ||
998 | BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ; | ||
999 | |||
1028 | /* chip_info isn't always needed */ | 1000 | /* chip_info isn't always needed */ |
1029 | if (chip_info) { | 1001 | if (chip_info) { |
1030 | /* Make sure people stop trying to set fields via ctl_reg | 1002 | /* Make sure people stop trying to set fields via ctl_reg |
1031 | * when they should actually be using common SPI framework. | 1003 | * when they should actually be using common SPI framework. |
1032 | * Currently we let through: WOM EMISO PSSE GM SZ TIMOD. | 1004 | * Currently we let through: WOM EMISO PSSE GM SZ. |
1033 | * Not sure if a user actually needs/uses any of these, | 1005 | * Not sure if a user actually needs/uses any of these, |
1034 | * but let's assume (for now) they do. | 1006 | * but let's assume (for now) they do. |
1035 | */ | 1007 | */ |
1036 | if (chip_info->ctl_reg & (SPE|MSTR|CPOL|CPHA|LSBF|SIZE)) { | 1008 | if (chip_info->ctl_reg & ~bfin_ctl_reg) { |
1037 | dev_err(&spi->dev, "do not set bits in ctl_reg " | 1009 | dev_err(&spi->dev, "do not set bits in ctl_reg " |
1038 | "that the SPI framework manages\n"); | 1010 | "that the SPI framework manages\n"); |
1039 | return -EINVAL; | 1011 | goto error; |
1040 | } | 1012 | } |
1041 | |||
1042 | chip->enable_dma = chip_info->enable_dma != 0 | 1013 | chip->enable_dma = chip_info->enable_dma != 0 |
1043 | && drv_data->master_info->enable_dma; | 1014 | && drv_data->master_info->enable_dma; |
1044 | chip->ctl_reg = chip_info->ctl_reg; | 1015 | chip->ctl_reg = chip_info->ctl_reg; |
1045 | chip->bits_per_word = chip_info->bits_per_word; | ||
1046 | chip->cs_change_per_word = chip_info->cs_change_per_word; | ||
1047 | chip->cs_chg_udelay = chip_info->cs_chg_udelay; | 1016 | chip->cs_chg_udelay = chip_info->cs_chg_udelay; |
1048 | chip->cs_gpio = chip_info->cs_gpio; | ||
1049 | chip->idle_tx_val = chip_info->idle_tx_val; | 1017 | chip->idle_tx_val = chip_info->idle_tx_val; |
1018 | chip->pio_interrupt = chip_info->pio_interrupt; | ||
1019 | spi->bits_per_word = chip_info->bits_per_word; | ||
1020 | } else { | ||
1021 | /* force a default base state */ | ||
1022 | chip->ctl_reg &= bfin_ctl_reg; | ||
1023 | } | ||
1024 | |||
1025 | if (spi->bits_per_word != 8 && spi->bits_per_word != 16) { | ||
1026 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", | ||
1027 | spi->bits_per_word); | ||
1028 | goto error; | ||
1050 | } | 1029 | } |
1051 | 1030 | ||
1052 | /* translate common spi framework into our register */ | 1031 | /* translate common spi framework into our register */ |
1032 | if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST)) { | ||
1033 | dev_err(&spi->dev, "unsupported spi modes detected\n"); | ||
1034 | goto error; | ||
1035 | } | ||
1053 | if (spi->mode & SPI_CPOL) | 1036 | if (spi->mode & SPI_CPOL) |
1054 | chip->ctl_reg |= CPOL; | 1037 | chip->ctl_reg |= BIT_CTL_CPOL; |
1055 | if (spi->mode & SPI_CPHA) | 1038 | if (spi->mode & SPI_CPHA) |
1056 | chip->ctl_reg |= CPHA; | 1039 | chip->ctl_reg |= BIT_CTL_CPHA; |
1057 | if (spi->mode & SPI_LSB_FIRST) | 1040 | if (spi->mode & SPI_LSB_FIRST) |
1058 | chip->ctl_reg |= LSBF; | 1041 | chip->ctl_reg |= BIT_CTL_LSBF; |
1059 | /* we dont support running in slave mode (yet?) */ | 1042 | /* we dont support running in slave mode (yet?) */ |
1060 | chip->ctl_reg |= MSTR; | 1043 | chip->ctl_reg |= BIT_CTL_MASTER; |
1061 | 1044 | ||
1062 | /* | 1045 | /* |
1046 | * Notice: for blackfin, the speed_hz is the value of register | ||
1047 | * SPI_BAUD, not the real baudrate | ||
1048 | */ | ||
1049 | chip->baud = hz_to_spi_baud(spi->max_speed_hz); | ||
1050 | chip->chip_select_num = spi->chip_select; | ||
1051 | if (chip->chip_select_num < MAX_CTRL_CS) { | ||
1052 | if (!(spi->mode & SPI_CPHA)) | ||
1053 | dev_warn(&spi->dev, "Warning: SPI CPHA not set:" | ||
1054 | " Slave Select not under software control!\n" | ||
1055 | " See Documentation/blackfin/bfin-spi-notes.txt"); | ||
1056 | |||
1057 | chip->flag = (1 << spi->chip_select) << 8; | ||
1058 | } else | ||
1059 | chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS; | ||
1060 | |||
1061 | if (chip->enable_dma && chip->pio_interrupt) { | ||
1062 | dev_err(&spi->dev, "enable_dma is set, " | ||
1063 | "do not set pio_interrupt\n"); | ||
1064 | goto error; | ||
1065 | } | ||
1066 | /* | ||
1063 | * if any one SPI chip is registered and wants DMA, request the | 1067 | * if any one SPI chip is registered and wants DMA, request the |
1064 | * DMA channel for it | 1068 | * DMA channel for it |
1065 | */ | 1069 | */ |
1066 | if (chip->enable_dma && !drv_data->dma_requested) { | 1070 | if (chip->enable_dma && !drv_data->dma_requested) { |
1067 | /* register dma irq handler */ | 1071 | /* register dma irq handler */ |
1068 | if (request_dma(drv_data->dma_channel, "BFIN_SPI_DMA") < 0) { | 1072 | ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA"); |
1069 | dev_dbg(&spi->dev, | 1073 | if (ret) { |
1074 | dev_err(&spi->dev, | ||
1070 | "Unable to request BlackFin SPI DMA channel\n"); | 1075 | "Unable to request BlackFin SPI DMA channel\n"); |
1071 | return -ENODEV; | 1076 | goto error; |
1072 | } | 1077 | } |
1073 | if (set_dma_callback(drv_data->dma_channel, | 1078 | drv_data->dma_requested = 1; |
1074 | bfin_spi_dma_irq_handler, drv_data) < 0) { | 1079 | |
1075 | dev_dbg(&spi->dev, "Unable to set dma callback\n"); | 1080 | ret = set_dma_callback(drv_data->dma_channel, |
1076 | return -EPERM; | 1081 | bfin_spi_dma_irq_handler, drv_data); |
1082 | if (ret) { | ||
1083 | dev_err(&spi->dev, "Unable to set dma callback\n"); | ||
1084 | goto error; | ||
1077 | } | 1085 | } |
1078 | dma_disable_irq(drv_data->dma_channel); | 1086 | dma_disable_irq(drv_data->dma_channel); |
1079 | drv_data->dma_requested = 1; | ||
1080 | } | 1087 | } |
1081 | 1088 | ||
1082 | /* | 1089 | if (chip->pio_interrupt && !drv_data->irq_requested) { |
1083 | * Notice: for blackfin, the speed_hz is the value of register | 1090 | ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler, |
1084 | * SPI_BAUD, not the real baudrate | 1091 | IRQF_DISABLED, "BFIN_SPI", drv_data); |
1085 | */ | 1092 | if (ret) { |
1086 | chip->baud = hz_to_spi_baud(spi->max_speed_hz); | 1093 | dev_err(&spi->dev, "Unable to register spi IRQ\n"); |
1087 | chip->flag = 1 << (spi->chip_select); | 1094 | goto error; |
1088 | chip->chip_select_num = spi->chip_select; | 1095 | } |
1096 | drv_data->irq_requested = 1; | ||
1097 | /* we use write mode, spi irq has to be disabled here */ | ||
1098 | disable_irq(drv_data->spi_irq); | ||
1099 | } | ||
1089 | 1100 | ||
1090 | if (chip->chip_select_num == 0) { | 1101 | if (chip->chip_select_num >= MAX_CTRL_CS) { |
1091 | ret = gpio_request(chip->cs_gpio, spi->modalias); | 1102 | ret = gpio_request(chip->cs_gpio, spi->modalias); |
1092 | if (ret) { | 1103 | if (ret) { |
1093 | if (drv_data->dma_requested) | 1104 | dev_err(&spi->dev, "gpio_request() error\n"); |
1094 | free_dma(drv_data->dma_channel); | 1105 | goto pin_error; |
1095 | return ret; | ||
1096 | } | 1106 | } |
1097 | gpio_direction_output(chip->cs_gpio, 1); | 1107 | gpio_direction_output(chip->cs_gpio, 1); |
1098 | } | 1108 | } |
1099 | 1109 | ||
1100 | switch (chip->bits_per_word) { | ||
1101 | case 8: | ||
1102 | chip->n_bytes = 1; | ||
1103 | chip->width = CFG_SPI_WORDSIZE8; | ||
1104 | chip->read = chip->cs_change_per_word ? | ||
1105 | bfin_spi_u8_cs_chg_reader : bfin_spi_u8_reader; | ||
1106 | chip->write = chip->cs_change_per_word ? | ||
1107 | bfin_spi_u8_cs_chg_writer : bfin_spi_u8_writer; | ||
1108 | chip->duplex = chip->cs_change_per_word ? | ||
1109 | bfin_spi_u8_cs_chg_duplex : bfin_spi_u8_duplex; | ||
1110 | break; | ||
1111 | |||
1112 | case 16: | ||
1113 | chip->n_bytes = 2; | ||
1114 | chip->width = CFG_SPI_WORDSIZE16; | ||
1115 | chip->read = chip->cs_change_per_word ? | ||
1116 | bfin_spi_u16_cs_chg_reader : bfin_spi_u16_reader; | ||
1117 | chip->write = chip->cs_change_per_word ? | ||
1118 | bfin_spi_u16_cs_chg_writer : bfin_spi_u16_writer; | ||
1119 | chip->duplex = chip->cs_change_per_word ? | ||
1120 | bfin_spi_u16_cs_chg_duplex : bfin_spi_u16_duplex; | ||
1121 | break; | ||
1122 | |||
1123 | default: | ||
1124 | dev_err(&spi->dev, "%d bits_per_word is not supported\n", | ||
1125 | chip->bits_per_word); | ||
1126 | if (chip_info) | ||
1127 | kfree(chip); | ||
1128 | return -ENODEV; | ||
1129 | } | ||
1130 | |||
1131 | dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n", | 1110 | dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n", |
1132 | spi->modalias, chip->width, chip->enable_dma); | 1111 | spi->modalias, spi->bits_per_word, chip->enable_dma); |
1133 | dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n", | 1112 | dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n", |
1134 | chip->ctl_reg, chip->flag); | 1113 | chip->ctl_reg, chip->flag); |
1135 | 1114 | ||
1136 | spi_set_ctldata(spi, chip); | 1115 | spi_set_ctldata(spi, chip); |
1137 | 1116 | ||
1138 | dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); | 1117 | dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); |
1139 | if ((chip->chip_select_num > 0) | 1118 | if (chip->chip_select_num < MAX_CTRL_CS) { |
1140 | && (chip->chip_select_num <= spi->master->num_chipselect)) | 1119 | ret = peripheral_request(ssel[spi->master->bus_num] |
1141 | peripheral_request(ssel[spi->master->bus_num] | 1120 | [chip->chip_select_num-1], spi->modalias); |
1142 | [chip->chip_select_num-1], spi->modalias); | 1121 | if (ret) { |
1122 | dev_err(&spi->dev, "peripheral_request() error\n"); | ||
1123 | goto pin_error; | ||
1124 | } | ||
1125 | } | ||
1143 | 1126 | ||
1127 | bfin_spi_cs_enable(drv_data, chip); | ||
1144 | bfin_spi_cs_deactive(drv_data, chip); | 1128 | bfin_spi_cs_deactive(drv_data, chip); |
1145 | 1129 | ||
1146 | return 0; | 1130 | return 0; |
1131 | |||
1132 | pin_error: | ||
1133 | if (chip->chip_select_num >= MAX_CTRL_CS) | ||
1134 | gpio_free(chip->cs_gpio); | ||
1135 | else | ||
1136 | peripheral_free(ssel[spi->master->bus_num] | ||
1137 | [chip->chip_select_num - 1]); | ||
1138 | error: | ||
1139 | if (chip) { | ||
1140 | if (drv_data->dma_requested) | ||
1141 | free_dma(drv_data->dma_channel); | ||
1142 | drv_data->dma_requested = 0; | ||
1143 | |||
1144 | kfree(chip); | ||
1145 | /* prevent free 'chip' twice */ | ||
1146 | spi_set_ctldata(spi, NULL); | ||
1147 | } | ||
1148 | |||
1149 | return ret; | ||
1147 | } | 1150 | } |
1148 | 1151 | ||
1149 | /* | 1152 | /* |
@@ -1152,28 +1155,30 @@ static int bfin_spi_setup(struct spi_device *spi) | |||
1152 | */ | 1155 | */ |
1153 | static void bfin_spi_cleanup(struct spi_device *spi) | 1156 | static void bfin_spi_cleanup(struct spi_device *spi) |
1154 | { | 1157 | { |
1155 | struct chip_data *chip = spi_get_ctldata(spi); | 1158 | struct bfin_spi_slave_data *chip = spi_get_ctldata(spi); |
1159 | struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); | ||
1156 | 1160 | ||
1157 | if (!chip) | 1161 | if (!chip) |
1158 | return; | 1162 | return; |
1159 | 1163 | ||
1160 | if ((chip->chip_select_num > 0) | 1164 | if (chip->chip_select_num < MAX_CTRL_CS) { |
1161 | && (chip->chip_select_num <= spi->master->num_chipselect)) | ||
1162 | peripheral_free(ssel[spi->master->bus_num] | 1165 | peripheral_free(ssel[spi->master->bus_num] |
1163 | [chip->chip_select_num-1]); | 1166 | [chip->chip_select_num-1]); |
1164 | 1167 | bfin_spi_cs_disable(drv_data, chip); | |
1165 | if (chip->chip_select_num == 0) | 1168 | } else |
1166 | gpio_free(chip->cs_gpio); | 1169 | gpio_free(chip->cs_gpio); |
1167 | 1170 | ||
1168 | kfree(chip); | 1171 | kfree(chip); |
1172 | /* prevent free 'chip' twice */ | ||
1173 | spi_set_ctldata(spi, NULL); | ||
1169 | } | 1174 | } |
1170 | 1175 | ||
1171 | static inline int bfin_spi_init_queue(struct driver_data *drv_data) | 1176 | static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) |
1172 | { | 1177 | { |
1173 | INIT_LIST_HEAD(&drv_data->queue); | 1178 | INIT_LIST_HEAD(&drv_data->queue); |
1174 | spin_lock_init(&drv_data->lock); | 1179 | spin_lock_init(&drv_data->lock); |
1175 | 1180 | ||
1176 | drv_data->run = QUEUE_STOPPED; | 1181 | drv_data->running = false; |
1177 | drv_data->busy = 0; | 1182 | drv_data->busy = 0; |
1178 | 1183 | ||
1179 | /* init transfer tasklet */ | 1184 | /* init transfer tasklet */ |
@@ -1190,18 +1195,18 @@ static inline int bfin_spi_init_queue(struct driver_data *drv_data) | |||
1190 | return 0; | 1195 | return 0; |
1191 | } | 1196 | } |
1192 | 1197 | ||
1193 | static inline int bfin_spi_start_queue(struct driver_data *drv_data) | 1198 | static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) |
1194 | { | 1199 | { |
1195 | unsigned long flags; | 1200 | unsigned long flags; |
1196 | 1201 | ||
1197 | spin_lock_irqsave(&drv_data->lock, flags); | 1202 | spin_lock_irqsave(&drv_data->lock, flags); |
1198 | 1203 | ||
1199 | if (drv_data->run == QUEUE_RUNNING || drv_data->busy) { | 1204 | if (drv_data->running || drv_data->busy) { |
1200 | spin_unlock_irqrestore(&drv_data->lock, flags); | 1205 | spin_unlock_irqrestore(&drv_data->lock, flags); |
1201 | return -EBUSY; | 1206 | return -EBUSY; |
1202 | } | 1207 | } |
1203 | 1208 | ||
1204 | drv_data->run = QUEUE_RUNNING; | 1209 | drv_data->running = true; |
1205 | drv_data->cur_msg = NULL; | 1210 | drv_data->cur_msg = NULL; |
1206 | drv_data->cur_transfer = NULL; | 1211 | drv_data->cur_transfer = NULL; |
1207 | drv_data->cur_chip = NULL; | 1212 | drv_data->cur_chip = NULL; |
@@ -1212,7 +1217,7 @@ static inline int bfin_spi_start_queue(struct driver_data *drv_data) | |||
1212 | return 0; | 1217 | return 0; |
1213 | } | 1218 | } |
1214 | 1219 | ||
1215 | static inline int bfin_spi_stop_queue(struct driver_data *drv_data) | 1220 | static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data) |
1216 | { | 1221 | { |
1217 | unsigned long flags; | 1222 | unsigned long flags; |
1218 | unsigned limit = 500; | 1223 | unsigned limit = 500; |
@@ -1226,7 +1231,7 @@ static inline int bfin_spi_stop_queue(struct driver_data *drv_data) | |||
1226 | * execution path (pump_messages) would be required to call wake_up or | 1231 | * execution path (pump_messages) would be required to call wake_up or |
1227 | * friends on every SPI message. Do this instead | 1232 | * friends on every SPI message. Do this instead |
1228 | */ | 1233 | */ |
1229 | drv_data->run = QUEUE_STOPPED; | 1234 | drv_data->running = false; |
1230 | while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { | 1235 | while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { |
1231 | spin_unlock_irqrestore(&drv_data->lock, flags); | 1236 | spin_unlock_irqrestore(&drv_data->lock, flags); |
1232 | msleep(10); | 1237 | msleep(10); |
@@ -1241,7 +1246,7 @@ static inline int bfin_spi_stop_queue(struct driver_data *drv_data) | |||
1241 | return status; | 1246 | return status; |
1242 | } | 1247 | } |
1243 | 1248 | ||
1244 | static inline int bfin_spi_destroy_queue(struct driver_data *drv_data) | 1249 | static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) |
1245 | { | 1250 | { |
1246 | int status; | 1251 | int status; |
1247 | 1252 | ||
@@ -1259,14 +1264,14 @@ static int __init bfin_spi_probe(struct platform_device *pdev) | |||
1259 | struct device *dev = &pdev->dev; | 1264 | struct device *dev = &pdev->dev; |
1260 | struct bfin5xx_spi_master *platform_info; | 1265 | struct bfin5xx_spi_master *platform_info; |
1261 | struct spi_master *master; | 1266 | struct spi_master *master; |
1262 | struct driver_data *drv_data = 0; | 1267 | struct bfin_spi_master_data *drv_data; |
1263 | struct resource *res; | 1268 | struct resource *res; |
1264 | int status = 0; | 1269 | int status = 0; |
1265 | 1270 | ||
1266 | platform_info = dev->platform_data; | 1271 | platform_info = dev->platform_data; |
1267 | 1272 | ||
1268 | /* Allocate master with space for drv_data */ | 1273 | /* Allocate master with space for drv_data */ |
1269 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | 1274 | master = spi_alloc_master(dev, sizeof(*drv_data)); |
1270 | if (!master) { | 1275 | if (!master) { |
1271 | dev_err(&pdev->dev, "can not alloc spi_master\n"); | 1276 | dev_err(&pdev->dev, "can not alloc spi_master\n"); |
1272 | return -ENOMEM; | 1277 | return -ENOMEM; |
@@ -1302,11 +1307,19 @@ static int __init bfin_spi_probe(struct platform_device *pdev) | |||
1302 | goto out_error_ioremap; | 1307 | goto out_error_ioremap; |
1303 | } | 1308 | } |
1304 | 1309 | ||
1305 | drv_data->dma_channel = platform_get_irq(pdev, 0); | 1310 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1306 | if (drv_data->dma_channel < 0) { | 1311 | if (res == NULL) { |
1307 | dev_err(dev, "No DMA channel specified\n"); | 1312 | dev_err(dev, "No DMA channel specified\n"); |
1308 | status = -ENOENT; | 1313 | status = -ENOENT; |
1309 | goto out_error_no_dma_ch; | 1314 | goto out_error_free_io; |
1315 | } | ||
1316 | drv_data->dma_channel = res->start; | ||
1317 | |||
1318 | drv_data->spi_irq = platform_get_irq(pdev, 0); | ||
1319 | if (drv_data->spi_irq < 0) { | ||
1320 | dev_err(dev, "No spi pio irq specified\n"); | ||
1321 | status = -ENOENT; | ||
1322 | goto out_error_free_io; | ||
1310 | } | 1323 | } |
1311 | 1324 | ||
1312 | /* Initial and start queue */ | 1325 | /* Initial and start queue */ |
@@ -1328,6 +1341,12 @@ static int __init bfin_spi_probe(struct platform_device *pdev) | |||
1328 | goto out_error_queue_alloc; | 1341 | goto out_error_queue_alloc; |
1329 | } | 1342 | } |
1330 | 1343 | ||
1344 | /* Reset SPI registers. If these registers were used by the boot loader, | ||
1345 | * the sky may fall on your head if you enable the dma controller. | ||
1346 | */ | ||
1347 | write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER); | ||
1348 | write_FLAG(drv_data, 0xFF00); | ||
1349 | |||
1331 | /* Register with the SPI framework */ | 1350 | /* Register with the SPI framework */ |
1332 | platform_set_drvdata(pdev, drv_data); | 1351 | platform_set_drvdata(pdev, drv_data); |
1333 | status = spi_register_master(master); | 1352 | status = spi_register_master(master); |
@@ -1343,7 +1362,7 @@ static int __init bfin_spi_probe(struct platform_device *pdev) | |||
1343 | 1362 | ||
1344 | out_error_queue_alloc: | 1363 | out_error_queue_alloc: |
1345 | bfin_spi_destroy_queue(drv_data); | 1364 | bfin_spi_destroy_queue(drv_data); |
1346 | out_error_no_dma_ch: | 1365 | out_error_free_io: |
1347 | iounmap((void *) drv_data->regs_base); | 1366 | iounmap((void *) drv_data->regs_base); |
1348 | out_error_ioremap: | 1367 | out_error_ioremap: |
1349 | out_error_get_res: | 1368 | out_error_get_res: |
@@ -1355,7 +1374,7 @@ out_error_get_res: | |||
1355 | /* stop hardware and remove the driver */ | 1374 | /* stop hardware and remove the driver */ |
1356 | static int __devexit bfin_spi_remove(struct platform_device *pdev) | 1375 | static int __devexit bfin_spi_remove(struct platform_device *pdev) |
1357 | { | 1376 | { |
1358 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1377 | struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); |
1359 | int status = 0; | 1378 | int status = 0; |
1360 | 1379 | ||
1361 | if (!drv_data) | 1380 | if (!drv_data) |
@@ -1375,6 +1394,11 @@ static int __devexit bfin_spi_remove(struct platform_device *pdev) | |||
1375 | free_dma(drv_data->dma_channel); | 1394 | free_dma(drv_data->dma_channel); |
1376 | } | 1395 | } |
1377 | 1396 | ||
1397 | if (drv_data->irq_requested) { | ||
1398 | free_irq(drv_data->spi_irq, drv_data); | ||
1399 | drv_data->irq_requested = 0; | ||
1400 | } | ||
1401 | |||
1378 | /* Disconnect from the SPI framework */ | 1402 | /* Disconnect from the SPI framework */ |
1379 | spi_unregister_master(drv_data->master); | 1403 | spi_unregister_master(drv_data->master); |
1380 | 1404 | ||
@@ -1389,26 +1413,32 @@ static int __devexit bfin_spi_remove(struct platform_device *pdev) | |||
1389 | #ifdef CONFIG_PM | 1413 | #ifdef CONFIG_PM |
1390 | static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state) | 1414 | static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state) |
1391 | { | 1415 | { |
1392 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1416 | struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); |
1393 | int status = 0; | 1417 | int status = 0; |
1394 | 1418 | ||
1395 | status = bfin_spi_stop_queue(drv_data); | 1419 | status = bfin_spi_stop_queue(drv_data); |
1396 | if (status != 0) | 1420 | if (status != 0) |
1397 | return status; | 1421 | return status; |
1398 | 1422 | ||
1399 | /* stop hardware */ | 1423 | drv_data->ctrl_reg = read_CTRL(drv_data); |
1400 | bfin_spi_disable(drv_data); | 1424 | drv_data->flag_reg = read_FLAG(drv_data); |
1425 | |||
1426 | /* | ||
1427 | * reset SPI_CTL and SPI_FLG registers | ||
1428 | */ | ||
1429 | write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER); | ||
1430 | write_FLAG(drv_data, 0xFF00); | ||
1401 | 1431 | ||
1402 | return 0; | 1432 | return 0; |
1403 | } | 1433 | } |
1404 | 1434 | ||
1405 | static int bfin_spi_resume(struct platform_device *pdev) | 1435 | static int bfin_spi_resume(struct platform_device *pdev) |
1406 | { | 1436 | { |
1407 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1437 | struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); |
1408 | int status = 0; | 1438 | int status = 0; |
1409 | 1439 | ||
1410 | /* Enable the SPI interface */ | 1440 | write_CTRL(drv_data, drv_data->ctrl_reg); |
1411 | bfin_spi_enable(drv_data); | 1441 | write_FLAG(drv_data, drv_data->flag_reg); |
1412 | 1442 | ||
1413 | /* Start the queue running */ | 1443 | /* Start the queue running */ |
1414 | status = bfin_spi_start_queue(drv_data); | 1444 | status = bfin_spi_start_queue(drv_data); |
@@ -1439,7 +1469,7 @@ static int __init bfin_spi_init(void) | |||
1439 | { | 1469 | { |
1440 | return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe); | 1470 | return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe); |
1441 | } | 1471 | } |
1442 | module_init(bfin_spi_init); | 1472 | subsys_initcall(bfin_spi_init); |
1443 | 1473 | ||
1444 | static void __exit bfin_spi_exit(void) | 1474 | static void __exit bfin_spi_exit(void) |
1445 | { | 1475 | { |
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c new file mode 100644 index 000000000000..e3b4f6451966 --- /dev/null +++ b/drivers/spi/spi_fsl_espi.c | |||
@@ -0,0 +1,748 @@ | |||
1 | /* | ||
2 | * Freescale eSPI controller driver. | ||
3 | * | ||
4 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/fsl_devices.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/of_spi.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <sysdev/fsl_soc.h> | ||
24 | |||
25 | #include "spi_fsl_lib.h" | ||
26 | |||
27 | /* eSPI Controller registers */ | ||
28 | struct fsl_espi_reg { | ||
29 | __be32 mode; /* 0x000 - eSPI mode register */ | ||
30 | __be32 event; /* 0x004 - eSPI event register */ | ||
31 | __be32 mask; /* 0x008 - eSPI mask register */ | ||
32 | __be32 command; /* 0x00c - eSPI command register */ | ||
33 | __be32 transmit; /* 0x010 - eSPI transmit FIFO access register*/ | ||
34 | __be32 receive; /* 0x014 - eSPI receive FIFO access register*/ | ||
35 | u8 res[8]; /* 0x018 - 0x01c reserved */ | ||
36 | __be32 csmode[4]; /* 0x020 - 0x02c eSPI cs mode register */ | ||
37 | }; | ||
38 | |||
39 | struct fsl_espi_transfer { | ||
40 | const void *tx_buf; | ||
41 | void *rx_buf; | ||
42 | unsigned len; | ||
43 | unsigned n_tx; | ||
44 | unsigned n_rx; | ||
45 | unsigned actual_length; | ||
46 | int status; | ||
47 | }; | ||
48 | |||
49 | /* eSPI Controller mode register definitions */ | ||
50 | #define SPMODE_ENABLE (1 << 31) | ||
51 | #define SPMODE_LOOP (1 << 30) | ||
52 | #define SPMODE_TXTHR(x) ((x) << 8) | ||
53 | #define SPMODE_RXTHR(x) ((x) << 0) | ||
54 | |||
55 | /* eSPI Controller CS mode register definitions */ | ||
56 | #define CSMODE_CI_INACTIVEHIGH (1 << 31) | ||
57 | #define CSMODE_CP_BEGIN_EDGECLK (1 << 30) | ||
58 | #define CSMODE_REV (1 << 29) | ||
59 | #define CSMODE_DIV16 (1 << 28) | ||
60 | #define CSMODE_PM(x) ((x) << 24) | ||
61 | #define CSMODE_POL_1 (1 << 20) | ||
62 | #define CSMODE_LEN(x) ((x) << 16) | ||
63 | #define CSMODE_BEF(x) ((x) << 12) | ||
64 | #define CSMODE_AFT(x) ((x) << 8) | ||
65 | #define CSMODE_CG(x) ((x) << 3) | ||
66 | |||
67 | /* Default mode/csmode for eSPI controller */ | ||
68 | #define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3)) | ||
69 | #define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \ | ||
70 | | CSMODE_AFT(0) | CSMODE_CG(1)) | ||
71 | |||
72 | /* SPIE register values */ | ||
73 | #define SPIE_NE 0x00000200 /* Not empty */ | ||
74 | #define SPIE_NF 0x00000100 /* Not full */ | ||
75 | |||
76 | /* SPIM register values */ | ||
77 | #define SPIM_NE 0x00000200 /* Not empty */ | ||
78 | #define SPIM_NF 0x00000100 /* Not full */ | ||
79 | #define SPIE_RXCNT(reg) ((reg >> 24) & 0x3F) | ||
80 | #define SPIE_TXCNT(reg) ((reg >> 16) & 0x3F) | ||
81 | |||
82 | /* SPCOM register values */ | ||
83 | #define SPCOM_CS(x) ((x) << 30) | ||
84 | #define SPCOM_TRANLEN(x) ((x) << 0) | ||
85 | #define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */ | ||
86 | |||
87 | static void fsl_espi_change_mode(struct spi_device *spi) | ||
88 | { | ||
89 | struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); | ||
90 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | ||
91 | struct fsl_espi_reg *reg_base = mspi->reg_base; | ||
92 | __be32 __iomem *mode = ®_base->csmode[spi->chip_select]; | ||
93 | __be32 __iomem *espi_mode = ®_base->mode; | ||
94 | u32 tmp; | ||
95 | unsigned long flags; | ||
96 | |||
97 | /* Turn off IRQs locally to minimize time that SPI is disabled. */ | ||
98 | local_irq_save(flags); | ||
99 | |||
100 | /* Turn off SPI unit prior changing mode */ | ||
101 | tmp = mpc8xxx_spi_read_reg(espi_mode); | ||
102 | mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE); | ||
103 | mpc8xxx_spi_write_reg(mode, cs->hw_mode); | ||
104 | mpc8xxx_spi_write_reg(espi_mode, tmp); | ||
105 | |||
106 | local_irq_restore(flags); | ||
107 | } | ||
108 | |||
109 | static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi) | ||
110 | { | ||
111 | u32 data; | ||
112 | u16 data_h; | ||
113 | u16 data_l; | ||
114 | const u32 *tx = mpc8xxx_spi->tx; | ||
115 | |||
116 | if (!tx) | ||
117 | return 0; | ||
118 | |||
119 | data = *tx++ << mpc8xxx_spi->tx_shift; | ||
120 | data_l = data & 0xffff; | ||
121 | data_h = (data >> 16) & 0xffff; | ||
122 | swab16s(&data_l); | ||
123 | swab16s(&data_h); | ||
124 | data = data_h | data_l; | ||
125 | |||
126 | mpc8xxx_spi->tx = tx; | ||
127 | return data; | ||
128 | } | ||
129 | |||
130 | static int fsl_espi_setup_transfer(struct spi_device *spi, | ||
131 | struct spi_transfer *t) | ||
132 | { | ||
133 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
134 | int bits_per_word = 0; | ||
135 | u8 pm; | ||
136 | u32 hz = 0; | ||
137 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | ||
138 | |||
139 | if (t) { | ||
140 | bits_per_word = t->bits_per_word; | ||
141 | hz = t->speed_hz; | ||
142 | } | ||
143 | |||
144 | /* spi_transfer level calls that work per-word */ | ||
145 | if (!bits_per_word) | ||
146 | bits_per_word = spi->bits_per_word; | ||
147 | |||
148 | /* Make sure its a bit width we support [4..16] */ | ||
149 | if ((bits_per_word < 4) || (bits_per_word > 16)) | ||
150 | return -EINVAL; | ||
151 | |||
152 | if (!hz) | ||
153 | hz = spi->max_speed_hz; | ||
154 | |||
155 | cs->rx_shift = 0; | ||
156 | cs->tx_shift = 0; | ||
157 | cs->get_rx = mpc8xxx_spi_rx_buf_u32; | ||
158 | cs->get_tx = mpc8xxx_spi_tx_buf_u32; | ||
159 | if (bits_per_word <= 8) { | ||
160 | cs->rx_shift = 8 - bits_per_word; | ||
161 | } else if (bits_per_word <= 16) { | ||
162 | cs->rx_shift = 16 - bits_per_word; | ||
163 | if (spi->mode & SPI_LSB_FIRST) | ||
164 | cs->get_tx = fsl_espi_tx_buf_lsb; | ||
165 | } else { | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | mpc8xxx_spi->rx_shift = cs->rx_shift; | ||
170 | mpc8xxx_spi->tx_shift = cs->tx_shift; | ||
171 | mpc8xxx_spi->get_rx = cs->get_rx; | ||
172 | mpc8xxx_spi->get_tx = cs->get_tx; | ||
173 | |||
174 | bits_per_word = bits_per_word - 1; | ||
175 | |||
176 | /* mask out bits we are going to set */ | ||
177 | cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF)); | ||
178 | |||
179 | cs->hw_mode |= CSMODE_LEN(bits_per_word); | ||
180 | |||
181 | if ((mpc8xxx_spi->spibrg / hz) > 64) { | ||
182 | cs->hw_mode |= CSMODE_DIV16; | ||
183 | pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1; | ||
184 | |||
185 | WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. " | ||
186 | "Will use %d Hz instead.\n", dev_name(&spi->dev), | ||
187 | hz, mpc8xxx_spi->spibrg / 1024); | ||
188 | if (pm > 16) | ||
189 | pm = 16; | ||
190 | } else { | ||
191 | pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1; | ||
192 | } | ||
193 | if (pm) | ||
194 | pm--; | ||
195 | |||
196 | cs->hw_mode |= CSMODE_PM(pm); | ||
197 | |||
198 | fsl_espi_change_mode(spi); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t, | ||
203 | unsigned int len) | ||
204 | { | ||
205 | u32 word; | ||
206 | struct fsl_espi_reg *reg_base = mspi->reg_base; | ||
207 | |||
208 | mspi->count = len; | ||
209 | |||
210 | /* enable rx ints */ | ||
211 | mpc8xxx_spi_write_reg(®_base->mask, SPIM_NE); | ||
212 | |||
213 | /* transmit word */ | ||
214 | word = mspi->get_tx(mspi); | ||
215 | mpc8xxx_spi_write_reg(®_base->transmit, word); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) | ||
221 | { | ||
222 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
223 | struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base; | ||
224 | unsigned int len = t->len; | ||
225 | u8 bits_per_word; | ||
226 | int ret; | ||
227 | |||
228 | bits_per_word = spi->bits_per_word; | ||
229 | if (t->bits_per_word) | ||
230 | bits_per_word = t->bits_per_word; | ||
231 | |||
232 | mpc8xxx_spi->len = t->len; | ||
233 | len = roundup(len, 4) / 4; | ||
234 | |||
235 | mpc8xxx_spi->tx = t->tx_buf; | ||
236 | mpc8xxx_spi->rx = t->rx_buf; | ||
237 | |||
238 | INIT_COMPLETION(mpc8xxx_spi->done); | ||
239 | |||
240 | /* Set SPCOM[CS] and SPCOM[TRANLEN] field */ | ||
241 | if ((t->len - 1) > SPCOM_TRANLEN_MAX) { | ||
242 | dev_err(mpc8xxx_spi->dev, "Transaction length (%d)" | ||
243 | " beyond the SPCOM[TRANLEN] field\n", t->len); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | mpc8xxx_spi_write_reg(®_base->command, | ||
247 | (SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1))); | ||
248 | |||
249 | ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len); | ||
250 | if (ret) | ||
251 | return ret; | ||
252 | |||
253 | wait_for_completion(&mpc8xxx_spi->done); | ||
254 | |||
255 | /* disable rx ints */ | ||
256 | mpc8xxx_spi_write_reg(®_base->mask, 0); | ||
257 | |||
258 | return mpc8xxx_spi->count; | ||
259 | } | ||
260 | |||
261 | static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd) | ||
262 | { | ||
263 | if (cmd[1] && cmd[2] && cmd[3]) { | ||
264 | cmd[1] = (u8)(addr >> 16); | ||
265 | cmd[2] = (u8)(addr >> 8); | ||
266 | cmd[3] = (u8)(addr >> 0); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static unsigned int fsl_espi_cmd2addr(u8 *cmd) | ||
271 | { | ||
272 | if (cmd[1] && cmd[2] && cmd[3]) | ||
273 | return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0; | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static void fsl_espi_do_trans(struct spi_message *m, | ||
279 | struct fsl_espi_transfer *tr) | ||
280 | { | ||
281 | struct spi_device *spi = m->spi; | ||
282 | struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); | ||
283 | struct fsl_espi_transfer *espi_trans = tr; | ||
284 | struct spi_message message; | ||
285 | struct spi_transfer *t, *first, trans; | ||
286 | int status = 0; | ||
287 | |||
288 | spi_message_init(&message); | ||
289 | memset(&trans, 0, sizeof(trans)); | ||
290 | |||
291 | first = list_first_entry(&m->transfers, struct spi_transfer, | ||
292 | transfer_list); | ||
293 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
294 | if ((first->bits_per_word != t->bits_per_word) || | ||
295 | (first->speed_hz != t->speed_hz)) { | ||
296 | espi_trans->status = -EINVAL; | ||
297 | dev_err(mspi->dev, "bits_per_word/speed_hz should be" | ||
298 | " same for the same SPI transfer\n"); | ||
299 | return; | ||
300 | } | ||
301 | |||
302 | trans.speed_hz = t->speed_hz; | ||
303 | trans.bits_per_word = t->bits_per_word; | ||
304 | trans.delay_usecs = max(first->delay_usecs, t->delay_usecs); | ||
305 | } | ||
306 | |||
307 | trans.len = espi_trans->len; | ||
308 | trans.tx_buf = espi_trans->tx_buf; | ||
309 | trans.rx_buf = espi_trans->rx_buf; | ||
310 | spi_message_add_tail(&trans, &message); | ||
311 | |||
312 | list_for_each_entry(t, &message.transfers, transfer_list) { | ||
313 | if (t->bits_per_word || t->speed_hz) { | ||
314 | status = -EINVAL; | ||
315 | |||
316 | status = fsl_espi_setup_transfer(spi, t); | ||
317 | if (status < 0) | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | if (t->len) | ||
322 | status = fsl_espi_bufs(spi, t); | ||
323 | |||
324 | if (status) { | ||
325 | status = -EMSGSIZE; | ||
326 | break; | ||
327 | } | ||
328 | |||
329 | if (t->delay_usecs) | ||
330 | udelay(t->delay_usecs); | ||
331 | } | ||
332 | |||
333 | espi_trans->status = status; | ||
334 | fsl_espi_setup_transfer(spi, NULL); | ||
335 | } | ||
336 | |||
337 | static void fsl_espi_cmd_trans(struct spi_message *m, | ||
338 | struct fsl_espi_transfer *trans, u8 *rx_buff) | ||
339 | { | ||
340 | struct spi_transfer *t; | ||
341 | u8 *local_buf; | ||
342 | int i = 0; | ||
343 | struct fsl_espi_transfer *espi_trans = trans; | ||
344 | |||
345 | local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL); | ||
346 | if (!local_buf) { | ||
347 | espi_trans->status = -ENOMEM; | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
352 | if (t->tx_buf) { | ||
353 | memcpy(local_buf + i, t->tx_buf, t->len); | ||
354 | i += t->len; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | espi_trans->tx_buf = local_buf; | ||
359 | espi_trans->rx_buf = local_buf + espi_trans->n_tx; | ||
360 | fsl_espi_do_trans(m, espi_trans); | ||
361 | |||
362 | espi_trans->actual_length = espi_trans->len; | ||
363 | kfree(local_buf); | ||
364 | } | ||
365 | |||
366 | static void fsl_espi_rw_trans(struct spi_message *m, | ||
367 | struct fsl_espi_transfer *trans, u8 *rx_buff) | ||
368 | { | ||
369 | struct fsl_espi_transfer *espi_trans = trans; | ||
370 | unsigned int n_tx = espi_trans->n_tx; | ||
371 | unsigned int n_rx = espi_trans->n_rx; | ||
372 | struct spi_transfer *t; | ||
373 | u8 *local_buf; | ||
374 | u8 *rx_buf = rx_buff; | ||
375 | unsigned int trans_len; | ||
376 | unsigned int addr; | ||
377 | int i, pos, loop; | ||
378 | |||
379 | local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL); | ||
380 | if (!local_buf) { | ||
381 | espi_trans->status = -ENOMEM; | ||
382 | return; | ||
383 | } | ||
384 | |||
385 | for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) { | ||
386 | trans_len = n_rx - pos; | ||
387 | if (trans_len > SPCOM_TRANLEN_MAX - n_tx) | ||
388 | trans_len = SPCOM_TRANLEN_MAX - n_tx; | ||
389 | |||
390 | i = 0; | ||
391 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
392 | if (t->tx_buf) { | ||
393 | memcpy(local_buf + i, t->tx_buf, t->len); | ||
394 | i += t->len; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | addr = fsl_espi_cmd2addr(local_buf); | ||
399 | addr += pos; | ||
400 | fsl_espi_addr2cmd(addr, local_buf); | ||
401 | |||
402 | espi_trans->n_tx = n_tx; | ||
403 | espi_trans->n_rx = trans_len; | ||
404 | espi_trans->len = trans_len + n_tx; | ||
405 | espi_trans->tx_buf = local_buf; | ||
406 | espi_trans->rx_buf = local_buf + n_tx; | ||
407 | fsl_espi_do_trans(m, espi_trans); | ||
408 | |||
409 | memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len); | ||
410 | |||
411 | if (loop > 0) | ||
412 | espi_trans->actual_length += espi_trans->len - n_tx; | ||
413 | else | ||
414 | espi_trans->actual_length += espi_trans->len; | ||
415 | } | ||
416 | |||
417 | kfree(local_buf); | ||
418 | } | ||
419 | |||
420 | static void fsl_espi_do_one_msg(struct spi_message *m) | ||
421 | { | ||
422 | struct spi_transfer *t; | ||
423 | u8 *rx_buf = NULL; | ||
424 | unsigned int n_tx = 0; | ||
425 | unsigned int n_rx = 0; | ||
426 | struct fsl_espi_transfer espi_trans; | ||
427 | |||
428 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
429 | if (t->tx_buf) | ||
430 | n_tx += t->len; | ||
431 | if (t->rx_buf) { | ||
432 | n_rx += t->len; | ||
433 | rx_buf = t->rx_buf; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | espi_trans.n_tx = n_tx; | ||
438 | espi_trans.n_rx = n_rx; | ||
439 | espi_trans.len = n_tx + n_rx; | ||
440 | espi_trans.actual_length = 0; | ||
441 | espi_trans.status = 0; | ||
442 | |||
443 | if (!rx_buf) | ||
444 | fsl_espi_cmd_trans(m, &espi_trans, NULL); | ||
445 | else | ||
446 | fsl_espi_rw_trans(m, &espi_trans, rx_buf); | ||
447 | |||
448 | m->actual_length = espi_trans.actual_length; | ||
449 | m->status = espi_trans.status; | ||
450 | m->complete(m->context); | ||
451 | } | ||
452 | |||
453 | static int fsl_espi_setup(struct spi_device *spi) | ||
454 | { | ||
455 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
456 | struct fsl_espi_reg *reg_base; | ||
457 | int retval; | ||
458 | u32 hw_mode; | ||
459 | u32 loop_mode; | ||
460 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | ||
461 | |||
462 | if (!spi->max_speed_hz) | ||
463 | return -EINVAL; | ||
464 | |||
465 | if (!cs) { | ||
466 | cs = kzalloc(sizeof *cs, GFP_KERNEL); | ||
467 | if (!cs) | ||
468 | return -ENOMEM; | ||
469 | spi->controller_state = cs; | ||
470 | } | ||
471 | |||
472 | mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
473 | reg_base = mpc8xxx_spi->reg_base; | ||
474 | |||
475 | hw_mode = cs->hw_mode; /* Save orginal settings */ | ||
476 | cs->hw_mode = mpc8xxx_spi_read_reg( | ||
477 | ®_base->csmode[spi->chip_select]); | ||
478 | /* mask out bits we are going to set */ | ||
479 | cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH | ||
480 | | CSMODE_REV); | ||
481 | |||
482 | if (spi->mode & SPI_CPHA) | ||
483 | cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK; | ||
484 | if (spi->mode & SPI_CPOL) | ||
485 | cs->hw_mode |= CSMODE_CI_INACTIVEHIGH; | ||
486 | if (!(spi->mode & SPI_LSB_FIRST)) | ||
487 | cs->hw_mode |= CSMODE_REV; | ||
488 | |||
489 | /* Handle the loop mode */ | ||
490 | loop_mode = mpc8xxx_spi_read_reg(®_base->mode); | ||
491 | loop_mode &= ~SPMODE_LOOP; | ||
492 | if (spi->mode & SPI_LOOP) | ||
493 | loop_mode |= SPMODE_LOOP; | ||
494 | mpc8xxx_spi_write_reg(®_base->mode, loop_mode); | ||
495 | |||
496 | retval = fsl_espi_setup_transfer(spi, NULL); | ||
497 | if (retval < 0) { | ||
498 | cs->hw_mode = hw_mode; /* Restore settings */ | ||
499 | return retval; | ||
500 | } | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | ||
505 | { | ||
506 | struct fsl_espi_reg *reg_base = mspi->reg_base; | ||
507 | |||
508 | /* We need handle RX first */ | ||
509 | if (events & SPIE_NE) { | ||
510 | u32 rx_data; | ||
511 | |||
512 | /* Spin until RX is done */ | ||
513 | while (SPIE_RXCNT(events) < min(4, mspi->len)) { | ||
514 | cpu_relax(); | ||
515 | events = mpc8xxx_spi_read_reg(®_base->event); | ||
516 | } | ||
517 | mspi->len -= 4; | ||
518 | |||
519 | rx_data = mpc8xxx_spi_read_reg(®_base->receive); | ||
520 | |||
521 | if (mspi->rx) | ||
522 | mspi->get_rx(rx_data, mspi); | ||
523 | } | ||
524 | |||
525 | if (!(events & SPIE_NF)) { | ||
526 | int ret; | ||
527 | |||
528 | /* spin until TX is done */ | ||
529 | ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg( | ||
530 | ®_base->event)) & SPIE_NF) == 0, 1000, 0); | ||
531 | if (!ret) { | ||
532 | dev_err(mspi->dev, "tired waiting for SPIE_NF\n"); | ||
533 | return; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | /* Clear the events */ | ||
538 | mpc8xxx_spi_write_reg(®_base->event, events); | ||
539 | |||
540 | mspi->count -= 1; | ||
541 | if (mspi->count) { | ||
542 | u32 word = mspi->get_tx(mspi); | ||
543 | |||
544 | mpc8xxx_spi_write_reg(®_base->transmit, word); | ||
545 | } else { | ||
546 | complete(&mspi->done); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) | ||
551 | { | ||
552 | struct mpc8xxx_spi *mspi = context_data; | ||
553 | struct fsl_espi_reg *reg_base = mspi->reg_base; | ||
554 | irqreturn_t ret = IRQ_NONE; | ||
555 | u32 events; | ||
556 | |||
557 | /* Get interrupt events(tx/rx) */ | ||
558 | events = mpc8xxx_spi_read_reg(®_base->event); | ||
559 | if (events) | ||
560 | ret = IRQ_HANDLED; | ||
561 | |||
562 | dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events); | ||
563 | |||
564 | fsl_espi_cpu_irq(mspi, events); | ||
565 | |||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | static void fsl_espi_remove(struct mpc8xxx_spi *mspi) | ||
570 | { | ||
571 | iounmap(mspi->reg_base); | ||
572 | } | ||
573 | |||
574 | static struct spi_master * __devinit fsl_espi_probe(struct device *dev, | ||
575 | struct resource *mem, unsigned int irq) | ||
576 | { | ||
577 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
578 | struct spi_master *master; | ||
579 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
580 | struct fsl_espi_reg *reg_base; | ||
581 | u32 regval; | ||
582 | int i, ret = 0; | ||
583 | |||
584 | master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi)); | ||
585 | if (!master) { | ||
586 | ret = -ENOMEM; | ||
587 | goto err; | ||
588 | } | ||
589 | |||
590 | dev_set_drvdata(dev, master); | ||
591 | |||
592 | ret = mpc8xxx_spi_probe(dev, mem, irq); | ||
593 | if (ret) | ||
594 | goto err_probe; | ||
595 | |||
596 | master->setup = fsl_espi_setup; | ||
597 | |||
598 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
599 | mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg; | ||
600 | mpc8xxx_spi->spi_remove = fsl_espi_remove; | ||
601 | |||
602 | mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); | ||
603 | if (!mpc8xxx_spi->reg_base) { | ||
604 | ret = -ENOMEM; | ||
605 | goto err_probe; | ||
606 | } | ||
607 | |||
608 | reg_base = mpc8xxx_spi->reg_base; | ||
609 | |||
610 | /* Register for SPI Interrupt */ | ||
611 | ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq, | ||
612 | 0, "fsl_espi", mpc8xxx_spi); | ||
613 | if (ret) | ||
614 | goto free_irq; | ||
615 | |||
616 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { | ||
617 | mpc8xxx_spi->rx_shift = 16; | ||
618 | mpc8xxx_spi->tx_shift = 24; | ||
619 | } | ||
620 | |||
621 | /* SPI controller initializations */ | ||
622 | mpc8xxx_spi_write_reg(®_base->mode, 0); | ||
623 | mpc8xxx_spi_write_reg(®_base->mask, 0); | ||
624 | mpc8xxx_spi_write_reg(®_base->command, 0); | ||
625 | mpc8xxx_spi_write_reg(®_base->event, 0xffffffff); | ||
626 | |||
627 | /* Init eSPI CS mode register */ | ||
628 | for (i = 0; i < pdata->max_chipselect; i++) | ||
629 | mpc8xxx_spi_write_reg(®_base->csmode[i], CSMODE_INIT_VAL); | ||
630 | |||
631 | /* Enable SPI interface */ | ||
632 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; | ||
633 | |||
634 | mpc8xxx_spi_write_reg(®_base->mode, regval); | ||
635 | |||
636 | ret = spi_register_master(master); | ||
637 | if (ret < 0) | ||
638 | goto unreg_master; | ||
639 | |||
640 | dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq); | ||
641 | |||
642 | return master; | ||
643 | |||
644 | unreg_master: | ||
645 | free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | ||
646 | free_irq: | ||
647 | iounmap(mpc8xxx_spi->reg_base); | ||
648 | err_probe: | ||
649 | spi_master_put(master); | ||
650 | err: | ||
651 | return ERR_PTR(ret); | ||
652 | } | ||
653 | |||
654 | static int of_fsl_espi_get_chipselects(struct device *dev) | ||
655 | { | ||
656 | struct device_node *np = dev->of_node; | ||
657 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
658 | const u32 *prop; | ||
659 | int len; | ||
660 | |||
661 | prop = of_get_property(np, "fsl,espi-num-chipselects", &len); | ||
662 | if (!prop || len < sizeof(*prop)) { | ||
663 | dev_err(dev, "No 'fsl,espi-num-chipselects' property\n"); | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | pdata->max_chipselect = *prop; | ||
668 | pdata->cs_control = NULL; | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int __devinit of_fsl_espi_probe(struct platform_device *ofdev, | ||
674 | const struct of_device_id *ofid) | ||
675 | { | ||
676 | struct device *dev = &ofdev->dev; | ||
677 | struct device_node *np = ofdev->dev.of_node; | ||
678 | struct spi_master *master; | ||
679 | struct resource mem; | ||
680 | struct resource irq; | ||
681 | int ret = -ENOMEM; | ||
682 | |||
683 | ret = of_mpc8xxx_spi_probe(ofdev, ofid); | ||
684 | if (ret) | ||
685 | return ret; | ||
686 | |||
687 | ret = of_fsl_espi_get_chipselects(dev); | ||
688 | if (ret) | ||
689 | goto err; | ||
690 | |||
691 | ret = of_address_to_resource(np, 0, &mem); | ||
692 | if (ret) | ||
693 | goto err; | ||
694 | |||
695 | ret = of_irq_to_resource(np, 0, &irq); | ||
696 | if (!ret) { | ||
697 | ret = -EINVAL; | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | master = fsl_espi_probe(dev, &mem, irq.start); | ||
702 | if (IS_ERR(master)) { | ||
703 | ret = PTR_ERR(master); | ||
704 | goto err; | ||
705 | } | ||
706 | |||
707 | return 0; | ||
708 | |||
709 | err: | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | static int __devexit of_fsl_espi_remove(struct platform_device *dev) | ||
714 | { | ||
715 | return mpc8xxx_spi_remove(&dev->dev); | ||
716 | } | ||
717 | |||
718 | static const struct of_device_id of_fsl_espi_match[] = { | ||
719 | { .compatible = "fsl,mpc8536-espi" }, | ||
720 | {} | ||
721 | }; | ||
722 | MODULE_DEVICE_TABLE(of, of_fsl_espi_match); | ||
723 | |||
724 | static struct of_platform_driver fsl_espi_driver = { | ||
725 | .driver = { | ||
726 | .name = "fsl_espi", | ||
727 | .owner = THIS_MODULE, | ||
728 | .of_match_table = of_fsl_espi_match, | ||
729 | }, | ||
730 | .probe = of_fsl_espi_probe, | ||
731 | .remove = __devexit_p(of_fsl_espi_remove), | ||
732 | }; | ||
733 | |||
734 | static int __init fsl_espi_init(void) | ||
735 | { | ||
736 | return of_register_platform_driver(&fsl_espi_driver); | ||
737 | } | ||
738 | module_init(fsl_espi_init); | ||
739 | |||
740 | static void __exit fsl_espi_exit(void) | ||
741 | { | ||
742 | of_unregister_platform_driver(&fsl_espi_driver); | ||
743 | } | ||
744 | module_exit(fsl_espi_exit); | ||
745 | |||
746 | MODULE_AUTHOR("Mingkai Hu"); | ||
747 | MODULE_DESCRIPTION("Enhanced Freescale SPI Driver"); | ||
748 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c new file mode 100644 index 000000000000..5cd741fdb5c3 --- /dev/null +++ b/drivers/spi/spi_fsl_lib.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * Freescale SPI/eSPI controller driver library. | ||
3 | * | ||
4 | * Maintainer: Kumar Gala | ||
5 | * | ||
6 | * Copyright (C) 2006 Polycom, Inc. | ||
7 | * | ||
8 | * CPM SPI and QE buffer descriptors mode support: | ||
9 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
10 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
11 | * | ||
12 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | */ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/fsl_devices.h> | ||
22 | #include <linux/dma-mapping.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/of_platform.h> | ||
25 | #include <linux/of_spi.h> | ||
26 | #include <sysdev/fsl_soc.h> | ||
27 | |||
28 | #include "spi_fsl_lib.h" | ||
29 | |||
30 | #define MPC8XXX_SPI_RX_BUF(type) \ | ||
31 | void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \ | ||
32 | { \ | ||
33 | type *rx = mpc8xxx_spi->rx; \ | ||
34 | *rx++ = (type)(data >> mpc8xxx_spi->rx_shift); \ | ||
35 | mpc8xxx_spi->rx = rx; \ | ||
36 | } | ||
37 | |||
38 | #define MPC8XXX_SPI_TX_BUF(type) \ | ||
39 | u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \ | ||
40 | { \ | ||
41 | u32 data; \ | ||
42 | const type *tx = mpc8xxx_spi->tx; \ | ||
43 | if (!tx) \ | ||
44 | return 0; \ | ||
45 | data = *tx++ << mpc8xxx_spi->tx_shift; \ | ||
46 | mpc8xxx_spi->tx = tx; \ | ||
47 | return data; \ | ||
48 | } | ||
49 | |||
50 | MPC8XXX_SPI_RX_BUF(u8) | ||
51 | MPC8XXX_SPI_RX_BUF(u16) | ||
52 | MPC8XXX_SPI_RX_BUF(u32) | ||
53 | MPC8XXX_SPI_TX_BUF(u8) | ||
54 | MPC8XXX_SPI_TX_BUF(u16) | ||
55 | MPC8XXX_SPI_TX_BUF(u32) | ||
56 | |||
57 | struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata) | ||
58 | { | ||
59 | return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata); | ||
60 | } | ||
61 | |||
62 | void mpc8xxx_spi_work(struct work_struct *work) | ||
63 | { | ||
64 | struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi, | ||
65 | work); | ||
66 | |||
67 | spin_lock_irq(&mpc8xxx_spi->lock); | ||
68 | while (!list_empty(&mpc8xxx_spi->queue)) { | ||
69 | struct spi_message *m = container_of(mpc8xxx_spi->queue.next, | ||
70 | struct spi_message, queue); | ||
71 | |||
72 | list_del_init(&m->queue); | ||
73 | spin_unlock_irq(&mpc8xxx_spi->lock); | ||
74 | |||
75 | if (mpc8xxx_spi->spi_do_one_msg) | ||
76 | mpc8xxx_spi->spi_do_one_msg(m); | ||
77 | |||
78 | spin_lock_irq(&mpc8xxx_spi->lock); | ||
79 | } | ||
80 | spin_unlock_irq(&mpc8xxx_spi->lock); | ||
81 | } | ||
82 | |||
83 | int mpc8xxx_spi_transfer(struct spi_device *spi, | ||
84 | struct spi_message *m) | ||
85 | { | ||
86 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
87 | unsigned long flags; | ||
88 | |||
89 | m->actual_length = 0; | ||
90 | m->status = -EINPROGRESS; | ||
91 | |||
92 | spin_lock_irqsave(&mpc8xxx_spi->lock, flags); | ||
93 | list_add_tail(&m->queue, &mpc8xxx_spi->queue); | ||
94 | queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work); | ||
95 | spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void mpc8xxx_spi_cleanup(struct spi_device *spi) | ||
101 | { | ||
102 | kfree(spi->controller_state); | ||
103 | } | ||
104 | |||
105 | const char *mpc8xxx_spi_strmode(unsigned int flags) | ||
106 | { | ||
107 | if (flags & SPI_QE_CPU_MODE) { | ||
108 | return "QE CPU"; | ||
109 | } else if (flags & SPI_CPM_MODE) { | ||
110 | if (flags & SPI_QE) | ||
111 | return "QE"; | ||
112 | else if (flags & SPI_CPM2) | ||
113 | return "CPM2"; | ||
114 | else | ||
115 | return "CPM1"; | ||
116 | } | ||
117 | return "CPU"; | ||
118 | } | ||
119 | |||
120 | int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, | ||
121 | unsigned int irq) | ||
122 | { | ||
123 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
124 | struct spi_master *master; | ||
125 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
126 | int ret = 0; | ||
127 | |||
128 | master = dev_get_drvdata(dev); | ||
129 | |||
130 | /* the spi->mode bits understood by this driver: */ | ||
131 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | ||
132 | | SPI_LSB_FIRST | SPI_LOOP; | ||
133 | |||
134 | master->transfer = mpc8xxx_spi_transfer; | ||
135 | master->cleanup = mpc8xxx_spi_cleanup; | ||
136 | master->dev.of_node = dev->of_node; | ||
137 | |||
138 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
139 | mpc8xxx_spi->dev = dev; | ||
140 | mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; | ||
141 | mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8; | ||
142 | mpc8xxx_spi->flags = pdata->flags; | ||
143 | mpc8xxx_spi->spibrg = pdata->sysclk; | ||
144 | mpc8xxx_spi->irq = irq; | ||
145 | |||
146 | mpc8xxx_spi->rx_shift = 0; | ||
147 | mpc8xxx_spi->tx_shift = 0; | ||
148 | |||
149 | init_completion(&mpc8xxx_spi->done); | ||
150 | |||
151 | master->bus_num = pdata->bus_num; | ||
152 | master->num_chipselect = pdata->max_chipselect; | ||
153 | |||
154 | spin_lock_init(&mpc8xxx_spi->lock); | ||
155 | init_completion(&mpc8xxx_spi->done); | ||
156 | INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work); | ||
157 | INIT_LIST_HEAD(&mpc8xxx_spi->queue); | ||
158 | |||
159 | mpc8xxx_spi->workqueue = create_singlethread_workqueue( | ||
160 | dev_name(master->dev.parent)); | ||
161 | if (mpc8xxx_spi->workqueue == NULL) { | ||
162 | ret = -EBUSY; | ||
163 | goto err; | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | |||
168 | err: | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | int __devexit mpc8xxx_spi_remove(struct device *dev) | ||
173 | { | ||
174 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
175 | struct spi_master *master; | ||
176 | |||
177 | master = dev_get_drvdata(dev); | ||
178 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
179 | |||
180 | flush_workqueue(mpc8xxx_spi->workqueue); | ||
181 | destroy_workqueue(mpc8xxx_spi->workqueue); | ||
182 | spi_unregister_master(master); | ||
183 | |||
184 | free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | ||
185 | |||
186 | if (mpc8xxx_spi->spi_remove) | ||
187 | mpc8xxx_spi->spi_remove(mpc8xxx_spi); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, | ||
193 | const struct of_device_id *ofid) | ||
194 | { | ||
195 | struct device *dev = &ofdev->dev; | ||
196 | struct device_node *np = ofdev->dev.of_node; | ||
197 | struct mpc8xxx_spi_probe_info *pinfo; | ||
198 | struct fsl_spi_platform_data *pdata; | ||
199 | const void *prop; | ||
200 | int ret = -ENOMEM; | ||
201 | |||
202 | pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); | ||
203 | if (!pinfo) | ||
204 | return -ENOMEM; | ||
205 | |||
206 | pdata = &pinfo->pdata; | ||
207 | dev->platform_data = pdata; | ||
208 | |||
209 | /* Allocate bus num dynamically. */ | ||
210 | pdata->bus_num = -1; | ||
211 | |||
212 | /* SPI controller is either clocked from QE or SoC clock. */ | ||
213 | pdata->sysclk = get_brgfreq(); | ||
214 | if (pdata->sysclk == -1) { | ||
215 | pdata->sysclk = fsl_get_sys_freq(); | ||
216 | if (pdata->sysclk == -1) { | ||
217 | ret = -ENODEV; | ||
218 | goto err; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | prop = of_get_property(np, "mode", NULL); | ||
223 | if (prop && !strcmp(prop, "cpu-qe")) | ||
224 | pdata->flags = SPI_QE_CPU_MODE; | ||
225 | else if (prop && !strcmp(prop, "qe")) | ||
226 | pdata->flags = SPI_CPM_MODE | SPI_QE; | ||
227 | else if (of_device_is_compatible(np, "fsl,cpm2-spi")) | ||
228 | pdata->flags = SPI_CPM_MODE | SPI_CPM2; | ||
229 | else if (of_device_is_compatible(np, "fsl,cpm1-spi")) | ||
230 | pdata->flags = SPI_CPM_MODE | SPI_CPM1; | ||
231 | |||
232 | return 0; | ||
233 | |||
234 | err: | ||
235 | kfree(pinfo); | ||
236 | return ret; | ||
237 | } | ||
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h new file mode 100644 index 000000000000..281e060977cd --- /dev/null +++ b/drivers/spi/spi_fsl_lib.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * Freescale SPI/eSPI controller driver library. | ||
3 | * | ||
4 | * Maintainer: Kumar Gala | ||
5 | * | ||
6 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
7 | * Copyright (C) 2006 Polycom, Inc. | ||
8 | * | ||
9 | * CPM SPI and QE buffer descriptors mode support: | ||
10 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
11 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | #ifndef __SPI_FSL_LIB_H__ | ||
19 | #define __SPI_FSL_LIB_H__ | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | |||
23 | /* SPI/eSPI Controller driver's private data. */ | ||
24 | struct mpc8xxx_spi { | ||
25 | struct device *dev; | ||
26 | void *reg_base; | ||
27 | |||
28 | /* rx & tx bufs from the spi_transfer */ | ||
29 | const void *tx; | ||
30 | void *rx; | ||
31 | #ifdef CONFIG_SPI_FSL_ESPI | ||
32 | int len; | ||
33 | #endif | ||
34 | |||
35 | int subblock; | ||
36 | struct spi_pram __iomem *pram; | ||
37 | struct cpm_buf_desc __iomem *tx_bd; | ||
38 | struct cpm_buf_desc __iomem *rx_bd; | ||
39 | |||
40 | struct spi_transfer *xfer_in_progress; | ||
41 | |||
42 | /* dma addresses for CPM transfers */ | ||
43 | dma_addr_t tx_dma; | ||
44 | dma_addr_t rx_dma; | ||
45 | bool map_tx_dma; | ||
46 | bool map_rx_dma; | ||
47 | |||
48 | dma_addr_t dma_dummy_tx; | ||
49 | dma_addr_t dma_dummy_rx; | ||
50 | |||
51 | /* functions to deal with different sized buffers */ | ||
52 | void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); | ||
53 | u32(*get_tx) (struct mpc8xxx_spi *); | ||
54 | |||
55 | /* hooks for different controller driver */ | ||
56 | void (*spi_do_one_msg) (struct spi_message *m); | ||
57 | void (*spi_remove) (struct mpc8xxx_spi *mspi); | ||
58 | |||
59 | unsigned int count; | ||
60 | unsigned int irq; | ||
61 | |||
62 | unsigned nsecs; /* (clock cycle time)/2 */ | ||
63 | |||
64 | u32 spibrg; /* SPIBRG input clock */ | ||
65 | u32 rx_shift; /* RX data reg shift when in qe mode */ | ||
66 | u32 tx_shift; /* TX data reg shift when in qe mode */ | ||
67 | |||
68 | unsigned int flags; | ||
69 | |||
70 | struct workqueue_struct *workqueue; | ||
71 | struct work_struct work; | ||
72 | |||
73 | struct list_head queue; | ||
74 | spinlock_t lock; | ||
75 | |||
76 | struct completion done; | ||
77 | }; | ||
78 | |||
79 | struct spi_mpc8xxx_cs { | ||
80 | /* functions to deal with different sized buffers */ | ||
81 | void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); | ||
82 | u32 (*get_tx) (struct mpc8xxx_spi *); | ||
83 | u32 rx_shift; /* RX data reg shift when in qe mode */ | ||
84 | u32 tx_shift; /* TX data reg shift when in qe mode */ | ||
85 | u32 hw_mode; /* Holds HW mode register settings */ | ||
86 | }; | ||
87 | |||
88 | static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val) | ||
89 | { | ||
90 | out_be32(reg, val); | ||
91 | } | ||
92 | |||
93 | static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) | ||
94 | { | ||
95 | return in_be32(reg); | ||
96 | } | ||
97 | |||
98 | struct mpc8xxx_spi_probe_info { | ||
99 | struct fsl_spi_platform_data pdata; | ||
100 | int *gpios; | ||
101 | bool *alow_flags; | ||
102 | }; | ||
103 | |||
104 | extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi); | ||
105 | extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi); | ||
106 | extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi); | ||
107 | extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi); | ||
108 | extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi); | ||
109 | extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi); | ||
110 | |||
111 | extern struct mpc8xxx_spi_probe_info *to_of_pinfo( | ||
112 | struct fsl_spi_platform_data *pdata); | ||
113 | extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi, | ||
114 | struct spi_transfer *t, unsigned int len); | ||
115 | extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m); | ||
116 | extern void mpc8xxx_spi_cleanup(struct spi_device *spi); | ||
117 | extern const char *mpc8xxx_spi_strmode(unsigned int flags); | ||
118 | extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, | ||
119 | unsigned int irq); | ||
120 | extern int mpc8xxx_spi_remove(struct device *dev); | ||
121 | extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev, | ||
122 | const struct of_device_id *ofid); | ||
123 | |||
124 | #endif /* __SPI_FSL_LIB_H__ */ | ||
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_fsl_spi.c index 1dd86b835cd8..7ca52d3ae8f8 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_fsl_spi.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * MPC8xxx SPI controller driver. | 2 | * Freescale SPI controller driver. |
3 | * | 3 | * |
4 | * Maintainer: Kumar Gala | 4 | * Maintainer: Kumar Gala |
5 | * | 5 | * |
6 | * Copyright (C) 2006 Polycom, Inc. | 6 | * Copyright (C) 2006 Polycom, Inc. |
7 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
7 | * | 8 | * |
8 | * CPM SPI and QE buffer descriptors mode support: | 9 | * CPM SPI and QE buffer descriptors mode support: |
9 | * Copyright (c) 2009 MontaVista Software, Inc. | 10 | * Copyright (c) 2009 MontaVista Software, Inc. |
@@ -15,18 +16,11 @@ | |||
15 | * option) any later version. | 16 | * option) any later version. |
16 | */ | 17 | */ |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/init.h> | ||
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/bug.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/completion.h> | ||
26 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
27 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
28 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
29 | #include <linux/device.h> | ||
30 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
31 | #include <linux/spi/spi_bitbang.h> | 25 | #include <linux/spi/spi_bitbang.h> |
32 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
@@ -38,12 +32,12 @@ | |||
38 | #include <linux/of_platform.h> | 32 | #include <linux/of_platform.h> |
39 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
40 | #include <linux/of_gpio.h> | 34 | #include <linux/of_gpio.h> |
41 | #include <linux/slab.h> | ||
42 | 35 | ||
43 | #include <sysdev/fsl_soc.h> | 36 | #include <sysdev/fsl_soc.h> |
44 | #include <asm/cpm.h> | 37 | #include <asm/cpm.h> |
45 | #include <asm/qe.h> | 38 | #include <asm/qe.h> |
46 | #include <asm/irq.h> | 39 | |
40 | #include "spi_fsl_lib.h" | ||
47 | 41 | ||
48 | /* CPM1 and CPM2 are mutually exclusive. */ | 42 | /* CPM1 and CPM2 are mutually exclusive. */ |
49 | #ifdef CONFIG_CPM1 | 43 | #ifdef CONFIG_CPM1 |
@@ -55,7 +49,7 @@ | |||
55 | #endif | 49 | #endif |
56 | 50 | ||
57 | /* SPI Controller registers */ | 51 | /* SPI Controller registers */ |
58 | struct mpc8xxx_spi_reg { | 52 | struct fsl_spi_reg { |
59 | u8 res1[0x20]; | 53 | u8 res1[0x20]; |
60 | __be32 mode; | 54 | __be32 mode; |
61 | __be32 event; | 55 | __be32 event; |
@@ -80,7 +74,7 @@ struct mpc8xxx_spi_reg { | |||
80 | 74 | ||
81 | /* | 75 | /* |
82 | * Default for SPI Mode: | 76 | * Default for SPI Mode: |
83 | * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk | 77 | * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk |
84 | */ | 78 | */ |
85 | #define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ | 79 | #define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ |
86 | SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) | 80 | SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) |
@@ -102,112 +96,16 @@ struct mpc8xxx_spi_reg { | |||
102 | #define SPI_PRAM_SIZE 0x100 | 96 | #define SPI_PRAM_SIZE 0x100 |
103 | #define SPI_MRBLR ((unsigned int)PAGE_SIZE) | 97 | #define SPI_MRBLR ((unsigned int)PAGE_SIZE) |
104 | 98 | ||
105 | /* SPI Controller driver's private data. */ | 99 | static void *fsl_dummy_rx; |
106 | struct mpc8xxx_spi { | 100 | static DEFINE_MUTEX(fsl_dummy_rx_lock); |
107 | struct device *dev; | 101 | static int fsl_dummy_rx_refcnt; |
108 | struct mpc8xxx_spi_reg __iomem *base; | ||
109 | |||
110 | /* rx & tx bufs from the spi_transfer */ | ||
111 | const void *tx; | ||
112 | void *rx; | ||
113 | |||
114 | int subblock; | ||
115 | struct spi_pram __iomem *pram; | ||
116 | struct cpm_buf_desc __iomem *tx_bd; | ||
117 | struct cpm_buf_desc __iomem *rx_bd; | ||
118 | |||
119 | struct spi_transfer *xfer_in_progress; | ||
120 | |||
121 | /* dma addresses for CPM transfers */ | ||
122 | dma_addr_t tx_dma; | ||
123 | dma_addr_t rx_dma; | ||
124 | bool map_tx_dma; | ||
125 | bool map_rx_dma; | ||
126 | |||
127 | dma_addr_t dma_dummy_tx; | ||
128 | dma_addr_t dma_dummy_rx; | ||
129 | |||
130 | /* functions to deal with different sized buffers */ | ||
131 | void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); | ||
132 | u32(*get_tx) (struct mpc8xxx_spi *); | ||
133 | |||
134 | unsigned int count; | ||
135 | unsigned int irq; | ||
136 | |||
137 | unsigned nsecs; /* (clock cycle time)/2 */ | ||
138 | |||
139 | u32 spibrg; /* SPIBRG input clock */ | ||
140 | u32 rx_shift; /* RX data reg shift when in qe mode */ | ||
141 | u32 tx_shift; /* TX data reg shift when in qe mode */ | ||
142 | |||
143 | unsigned int flags; | ||
144 | |||
145 | struct workqueue_struct *workqueue; | ||
146 | struct work_struct work; | ||
147 | |||
148 | struct list_head queue; | ||
149 | spinlock_t lock; | ||
150 | |||
151 | struct completion done; | ||
152 | }; | ||
153 | |||
154 | static void *mpc8xxx_dummy_rx; | ||
155 | static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock); | ||
156 | static int mpc8xxx_dummy_rx_refcnt; | ||
157 | |||
158 | struct spi_mpc8xxx_cs { | ||
159 | /* functions to deal with different sized buffers */ | ||
160 | void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); | ||
161 | u32 (*get_tx) (struct mpc8xxx_spi *); | ||
162 | u32 rx_shift; /* RX data reg shift when in qe mode */ | ||
163 | u32 tx_shift; /* TX data reg shift when in qe mode */ | ||
164 | u32 hw_mode; /* Holds HW mode register settings */ | ||
165 | }; | ||
166 | |||
167 | static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val) | ||
168 | { | ||
169 | out_be32(reg, val); | ||
170 | } | ||
171 | |||
172 | static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) | ||
173 | { | ||
174 | return in_be32(reg); | ||
175 | } | ||
176 | |||
177 | #define MPC83XX_SPI_RX_BUF(type) \ | ||
178 | static \ | ||
179 | void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \ | ||
180 | { \ | ||
181 | type *rx = mpc8xxx_spi->rx; \ | ||
182 | *rx++ = (type)(data >> mpc8xxx_spi->rx_shift); \ | ||
183 | mpc8xxx_spi->rx = rx; \ | ||
184 | } | ||
185 | |||
186 | #define MPC83XX_SPI_TX_BUF(type) \ | ||
187 | static \ | ||
188 | u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi) \ | ||
189 | { \ | ||
190 | u32 data; \ | ||
191 | const type *tx = mpc8xxx_spi->tx; \ | ||
192 | if (!tx) \ | ||
193 | return 0; \ | ||
194 | data = *tx++ << mpc8xxx_spi->tx_shift; \ | ||
195 | mpc8xxx_spi->tx = tx; \ | ||
196 | return data; \ | ||
197 | } | ||
198 | 102 | ||
199 | MPC83XX_SPI_RX_BUF(u8) | 103 | static void fsl_spi_change_mode(struct spi_device *spi) |
200 | MPC83XX_SPI_RX_BUF(u16) | ||
201 | MPC83XX_SPI_RX_BUF(u32) | ||
202 | MPC83XX_SPI_TX_BUF(u8) | ||
203 | MPC83XX_SPI_TX_BUF(u16) | ||
204 | MPC83XX_SPI_TX_BUF(u32) | ||
205 | |||
206 | static void mpc8xxx_spi_change_mode(struct spi_device *spi) | ||
207 | { | 104 | { |
208 | struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); | 105 | struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); |
209 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | 106 | struct spi_mpc8xxx_cs *cs = spi->controller_state; |
210 | __be32 __iomem *mode = &mspi->base->mode; | 107 | struct fsl_spi_reg *reg_base = mspi->reg_base; |
108 | __be32 __iomem *mode = ®_base->mode; | ||
211 | unsigned long flags; | 109 | unsigned long flags; |
212 | 110 | ||
213 | if (cs->hw_mode == mpc8xxx_spi_read_reg(mode)) | 111 | if (cs->hw_mode == mpc8xxx_spi_read_reg(mode)) |
@@ -238,7 +136,7 @@ static void mpc8xxx_spi_change_mode(struct spi_device *spi) | |||
238 | local_irq_restore(flags); | 136 | local_irq_restore(flags); |
239 | } | 137 | } |
240 | 138 | ||
241 | static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) | 139 | static void fsl_spi_chipselect(struct spi_device *spi, int value) |
242 | { | 140 | { |
243 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | 141 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); |
244 | struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; | 142 | struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; |
@@ -256,18 +154,17 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) | |||
256 | mpc8xxx_spi->get_rx = cs->get_rx; | 154 | mpc8xxx_spi->get_rx = cs->get_rx; |
257 | mpc8xxx_spi->get_tx = cs->get_tx; | 155 | mpc8xxx_spi->get_tx = cs->get_tx; |
258 | 156 | ||
259 | mpc8xxx_spi_change_mode(spi); | 157 | fsl_spi_change_mode(spi); |
260 | 158 | ||
261 | if (pdata->cs_control) | 159 | if (pdata->cs_control) |
262 | pdata->cs_control(spi, pol); | 160 | pdata->cs_control(spi, pol); |
263 | } | 161 | } |
264 | } | 162 | } |
265 | 163 | ||
266 | static int | 164 | static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, |
267 | mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, | 165 | struct spi_device *spi, |
268 | struct spi_device *spi, | 166 | struct mpc8xxx_spi *mpc8xxx_spi, |
269 | struct mpc8xxx_spi *mpc8xxx_spi, | 167 | int bits_per_word) |
270 | int bits_per_word) | ||
271 | { | 168 | { |
272 | cs->rx_shift = 0; | 169 | cs->rx_shift = 0; |
273 | cs->tx_shift = 0; | 170 | cs->tx_shift = 0; |
@@ -307,10 +204,9 @@ mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, | |||
307 | return bits_per_word; | 204 | return bits_per_word; |
308 | } | 205 | } |
309 | 206 | ||
310 | static int | 207 | static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs, |
311 | mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs, | 208 | struct spi_device *spi, |
312 | struct spi_device *spi, | 209 | int bits_per_word) |
313 | int bits_per_word) | ||
314 | { | 210 | { |
315 | /* QE uses Little Endian for words > 8 | 211 | /* QE uses Little Endian for words > 8 |
316 | * so transform all words > 8 into 8 bits | 212 | * so transform all words > 8 into 8 bits |
@@ -326,13 +222,13 @@ mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs, | |||
326 | return bits_per_word; | 222 | return bits_per_word; |
327 | } | 223 | } |
328 | 224 | ||
329 | static | 225 | static int fsl_spi_setup_transfer(struct spi_device *spi, |
330 | int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | 226 | struct spi_transfer *t) |
331 | { | 227 | { |
332 | struct mpc8xxx_spi *mpc8xxx_spi; | 228 | struct mpc8xxx_spi *mpc8xxx_spi; |
333 | int bits_per_word; | 229 | int bits_per_word = 0; |
334 | u8 pm; | 230 | u8 pm; |
335 | u32 hz; | 231 | u32 hz = 0; |
336 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | 232 | struct spi_mpc8xxx_cs *cs = spi->controller_state; |
337 | 233 | ||
338 | mpc8xxx_spi = spi_master_get_devdata(spi->master); | 234 | mpc8xxx_spi = spi_master_get_devdata(spi->master); |
@@ -340,9 +236,6 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
340 | if (t) { | 236 | if (t) { |
341 | bits_per_word = t->bits_per_word; | 237 | bits_per_word = t->bits_per_word; |
342 | hz = t->speed_hz; | 238 | hz = t->speed_hz; |
343 | } else { | ||
344 | bits_per_word = 0; | ||
345 | hz = 0; | ||
346 | } | 239 | } |
347 | 240 | ||
348 | /* spi_transfer level calls that work per-word */ | 241 | /* spi_transfer level calls that work per-word */ |
@@ -388,23 +281,25 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
388 | hz, mpc8xxx_spi->spibrg / 1024); | 281 | hz, mpc8xxx_spi->spibrg / 1024); |
389 | if (pm > 16) | 282 | if (pm > 16) |
390 | pm = 16; | 283 | pm = 16; |
391 | } else | 284 | } else { |
392 | pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1; | 285 | pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1; |
286 | } | ||
393 | if (pm) | 287 | if (pm) |
394 | pm--; | 288 | pm--; |
395 | 289 | ||
396 | cs->hw_mode |= SPMODE_PM(pm); | 290 | cs->hw_mode |= SPMODE_PM(pm); |
397 | 291 | ||
398 | mpc8xxx_spi_change_mode(spi); | 292 | fsl_spi_change_mode(spi); |
399 | return 0; | 293 | return 0; |
400 | } | 294 | } |
401 | 295 | ||
402 | static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) | 296 | static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) |
403 | { | 297 | { |
404 | struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; | 298 | struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd; |
405 | struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; | 299 | struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; |
406 | unsigned int xfer_len = min(mspi->count, SPI_MRBLR); | 300 | unsigned int xfer_len = min(mspi->count, SPI_MRBLR); |
407 | unsigned int xfer_ofs; | 301 | unsigned int xfer_ofs; |
302 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
408 | 303 | ||
409 | xfer_ofs = mspi->xfer_in_progress->len - mspi->count; | 304 | xfer_ofs = mspi->xfer_in_progress->len - mspi->count; |
410 | 305 | ||
@@ -424,13 +319,14 @@ static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) | |||
424 | BD_SC_LAST); | 319 | BD_SC_LAST); |
425 | 320 | ||
426 | /* start transfer */ | 321 | /* start transfer */ |
427 | mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR); | 322 | mpc8xxx_spi_write_reg(®_base->command, SPCOM_STR); |
428 | } | 323 | } |
429 | 324 | ||
430 | static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi, | 325 | static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, |
431 | struct spi_transfer *t, bool is_dma_mapped) | 326 | struct spi_transfer *t, bool is_dma_mapped) |
432 | { | 327 | { |
433 | struct device *dev = mspi->dev; | 328 | struct device *dev = mspi->dev; |
329 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
434 | 330 | ||
435 | if (is_dma_mapped) { | 331 | if (is_dma_mapped) { |
436 | mspi->map_tx_dma = 0; | 332 | mspi->map_tx_dma = 0; |
@@ -475,13 +371,13 @@ static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi, | |||
475 | } | 371 | } |
476 | 372 | ||
477 | /* enable rx ints */ | 373 | /* enable rx ints */ |
478 | mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB); | 374 | mpc8xxx_spi_write_reg(®_base->mask, SPIE_RXB); |
479 | 375 | ||
480 | mspi->xfer_in_progress = t; | 376 | mspi->xfer_in_progress = t; |
481 | mspi->count = t->len; | 377 | mspi->count = t->len; |
482 | 378 | ||
483 | /* start CPM transfers */ | 379 | /* start CPM transfers */ |
484 | mpc8xxx_spi_cpm_bufs_start(mspi); | 380 | fsl_spi_cpm_bufs_start(mspi); |
485 | 381 | ||
486 | return 0; | 382 | return 0; |
487 | 383 | ||
@@ -491,7 +387,7 @@ err_rx_dma: | |||
491 | return -ENOMEM; | 387 | return -ENOMEM; |
492 | } | 388 | } |
493 | 389 | ||
494 | static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) | 390 | static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) |
495 | { | 391 | { |
496 | struct device *dev = mspi->dev; | 392 | struct device *dev = mspi->dev; |
497 | struct spi_transfer *t = mspi->xfer_in_progress; | 393 | struct spi_transfer *t = mspi->xfer_in_progress; |
@@ -503,31 +399,34 @@ static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi) | |||
503 | mspi->xfer_in_progress = NULL; | 399 | mspi->xfer_in_progress = NULL; |
504 | } | 400 | } |
505 | 401 | ||
506 | static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi, | 402 | static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, |
507 | struct spi_transfer *t, unsigned int len) | 403 | struct spi_transfer *t, unsigned int len) |
508 | { | 404 | { |
509 | u32 word; | 405 | u32 word; |
406 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
510 | 407 | ||
511 | mspi->count = len; | 408 | mspi->count = len; |
512 | 409 | ||
513 | /* enable rx ints */ | 410 | /* enable rx ints */ |
514 | mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE); | 411 | mpc8xxx_spi_write_reg(®_base->mask, SPIM_NE); |
515 | 412 | ||
516 | /* transmit word */ | 413 | /* transmit word */ |
517 | word = mspi->get_tx(mspi); | 414 | word = mspi->get_tx(mspi); |
518 | mpc8xxx_spi_write_reg(&mspi->base->transmit, word); | 415 | mpc8xxx_spi_write_reg(®_base->transmit, word); |
519 | 416 | ||
520 | return 0; | 417 | return 0; |
521 | } | 418 | } |
522 | 419 | ||
523 | static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t, | 420 | static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, |
524 | bool is_dma_mapped) | 421 | bool is_dma_mapped) |
525 | { | 422 | { |
526 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | 423 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); |
424 | struct fsl_spi_reg *reg_base; | ||
527 | unsigned int len = t->len; | 425 | unsigned int len = t->len; |
528 | u8 bits_per_word; | 426 | u8 bits_per_word; |
529 | int ret; | 427 | int ret; |
530 | 428 | ||
429 | reg_base = mpc8xxx_spi->reg_base; | ||
531 | bits_per_word = spi->bits_per_word; | 430 | bits_per_word = spi->bits_per_word; |
532 | if (t->bits_per_word) | 431 | if (t->bits_per_word) |
533 | bits_per_word = t->bits_per_word; | 432 | bits_per_word = t->bits_per_word; |
@@ -551,24 +450,24 @@ static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t, | |||
551 | INIT_COMPLETION(mpc8xxx_spi->done); | 450 | INIT_COMPLETION(mpc8xxx_spi->done); |
552 | 451 | ||
553 | if (mpc8xxx_spi->flags & SPI_CPM_MODE) | 452 | if (mpc8xxx_spi->flags & SPI_CPM_MODE) |
554 | ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped); | 453 | ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped); |
555 | else | 454 | else |
556 | ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len); | 455 | ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len); |
557 | if (ret) | 456 | if (ret) |
558 | return ret; | 457 | return ret; |
559 | 458 | ||
560 | wait_for_completion(&mpc8xxx_spi->done); | 459 | wait_for_completion(&mpc8xxx_spi->done); |
561 | 460 | ||
562 | /* disable rx ints */ | 461 | /* disable rx ints */ |
563 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0); | 462 | mpc8xxx_spi_write_reg(®_base->mask, 0); |
564 | 463 | ||
565 | if (mpc8xxx_spi->flags & SPI_CPM_MODE) | 464 | if (mpc8xxx_spi->flags & SPI_CPM_MODE) |
566 | mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi); | 465 | fsl_spi_cpm_bufs_complete(mpc8xxx_spi); |
567 | 466 | ||
568 | return mpc8xxx_spi->count; | 467 | return mpc8xxx_spi->count; |
569 | } | 468 | } |
570 | 469 | ||
571 | static void mpc8xxx_spi_do_one_msg(struct spi_message *m) | 470 | static void fsl_spi_do_one_msg(struct spi_message *m) |
572 | { | 471 | { |
573 | struct spi_device *spi = m->spi; | 472 | struct spi_device *spi = m->spi; |
574 | struct spi_transfer *t; | 473 | struct spi_transfer *t; |
@@ -584,18 +483,18 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m) | |||
584 | status = -EINVAL; | 483 | status = -EINVAL; |
585 | 484 | ||
586 | if (cs_change) | 485 | if (cs_change) |
587 | status = mpc8xxx_spi_setup_transfer(spi, t); | 486 | status = fsl_spi_setup_transfer(spi, t); |
588 | if (status < 0) | 487 | if (status < 0) |
589 | break; | 488 | break; |
590 | } | 489 | } |
591 | 490 | ||
592 | if (cs_change) { | 491 | if (cs_change) { |
593 | mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE); | 492 | fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE); |
594 | ndelay(nsecs); | 493 | ndelay(nsecs); |
595 | } | 494 | } |
596 | cs_change = t->cs_change; | 495 | cs_change = t->cs_change; |
597 | if (t->len) | 496 | if (t->len) |
598 | status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped); | 497 | status = fsl_spi_bufs(spi, t, m->is_dma_mapped); |
599 | if (status) { | 498 | if (status) { |
600 | status = -EMSGSIZE; | 499 | status = -EMSGSIZE; |
601 | break; | 500 | break; |
@@ -607,7 +506,7 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m) | |||
607 | 506 | ||
608 | if (cs_change) { | 507 | if (cs_change) { |
609 | ndelay(nsecs); | 508 | ndelay(nsecs); |
610 | mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE); | 509 | fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); |
611 | ndelay(nsecs); | 510 | ndelay(nsecs); |
612 | } | 511 | } |
613 | } | 512 | } |
@@ -617,35 +516,16 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m) | |||
617 | 516 | ||
618 | if (status || !cs_change) { | 517 | if (status || !cs_change) { |
619 | ndelay(nsecs); | 518 | ndelay(nsecs); |
620 | mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE); | 519 | fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); |
621 | } | 520 | } |
622 | 521 | ||
623 | mpc8xxx_spi_setup_transfer(spi, NULL); | 522 | fsl_spi_setup_transfer(spi, NULL); |
624 | } | ||
625 | |||
626 | static void mpc8xxx_spi_work(struct work_struct *work) | ||
627 | { | ||
628 | struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi, | ||
629 | work); | ||
630 | |||
631 | spin_lock_irq(&mpc8xxx_spi->lock); | ||
632 | while (!list_empty(&mpc8xxx_spi->queue)) { | ||
633 | struct spi_message *m = container_of(mpc8xxx_spi->queue.next, | ||
634 | struct spi_message, queue); | ||
635 | |||
636 | list_del_init(&m->queue); | ||
637 | spin_unlock_irq(&mpc8xxx_spi->lock); | ||
638 | |||
639 | mpc8xxx_spi_do_one_msg(m); | ||
640 | |||
641 | spin_lock_irq(&mpc8xxx_spi->lock); | ||
642 | } | ||
643 | spin_unlock_irq(&mpc8xxx_spi->lock); | ||
644 | } | 523 | } |
645 | 524 | ||
646 | static int mpc8xxx_spi_setup(struct spi_device *spi) | 525 | static int fsl_spi_setup(struct spi_device *spi) |
647 | { | 526 | { |
648 | struct mpc8xxx_spi *mpc8xxx_spi; | 527 | struct mpc8xxx_spi *mpc8xxx_spi; |
528 | struct fsl_spi_reg *reg_base; | ||
649 | int retval; | 529 | int retval; |
650 | u32 hw_mode; | 530 | u32 hw_mode; |
651 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | 531 | struct spi_mpc8xxx_cs *cs = spi->controller_state; |
@@ -661,8 +541,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi) | |||
661 | } | 541 | } |
662 | mpc8xxx_spi = spi_master_get_devdata(spi->master); | 542 | mpc8xxx_spi = spi_master_get_devdata(spi->master); |
663 | 543 | ||
544 | reg_base = mpc8xxx_spi->reg_base; | ||
545 | |||
664 | hw_mode = cs->hw_mode; /* Save original settings */ | 546 | hw_mode = cs->hw_mode; /* Save original settings */ |
665 | cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode); | 547 | cs->hw_mode = mpc8xxx_spi_read_reg(®_base->mode); |
666 | /* mask out bits we are going to set */ | 548 | /* mask out bits we are going to set */ |
667 | cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH | 549 | cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH |
668 | | SPMODE_REV | SPMODE_LOOP); | 550 | | SPMODE_REV | SPMODE_LOOP); |
@@ -676,7 +558,7 @@ static int mpc8xxx_spi_setup(struct spi_device *spi) | |||
676 | if (spi->mode & SPI_LOOP) | 558 | if (spi->mode & SPI_LOOP) |
677 | cs->hw_mode |= SPMODE_LOOP; | 559 | cs->hw_mode |= SPMODE_LOOP; |
678 | 560 | ||
679 | retval = mpc8xxx_spi_setup_transfer(spi, NULL); | 561 | retval = fsl_spi_setup_transfer(spi, NULL); |
680 | if (retval < 0) { | 562 | if (retval < 0) { |
681 | cs->hw_mode = hw_mode; /* Restore settings */ | 563 | cs->hw_mode = hw_mode; /* Restore settings */ |
682 | return retval; | 564 | return retval; |
@@ -684,9 +566,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi) | |||
684 | return 0; | 566 | return 0; |
685 | } | 567 | } |
686 | 568 | ||
687 | static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) | 569 | static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) |
688 | { | 570 | { |
689 | u16 len; | 571 | u16 len; |
572 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
690 | 573 | ||
691 | dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, | 574 | dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, |
692 | in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); | 575 | in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); |
@@ -698,20 +581,22 @@ static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) | |||
698 | } | 581 | } |
699 | 582 | ||
700 | /* Clear the events */ | 583 | /* Clear the events */ |
701 | mpc8xxx_spi_write_reg(&mspi->base->event, events); | 584 | mpc8xxx_spi_write_reg(®_base->event, events); |
702 | 585 | ||
703 | mspi->count -= len; | 586 | mspi->count -= len; |
704 | if (mspi->count) | 587 | if (mspi->count) |
705 | mpc8xxx_spi_cpm_bufs_start(mspi); | 588 | fsl_spi_cpm_bufs_start(mspi); |
706 | else | 589 | else |
707 | complete(&mspi->done); | 590 | complete(&mspi->done); |
708 | } | 591 | } |
709 | 592 | ||
710 | static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | 593 | static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) |
711 | { | 594 | { |
595 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
596 | |||
712 | /* We need handle RX first */ | 597 | /* We need handle RX first */ |
713 | if (events & SPIE_NE) { | 598 | if (events & SPIE_NE) { |
714 | u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive); | 599 | u32 rx_data = mpc8xxx_spi_read_reg(®_base->receive); |
715 | 600 | ||
716 | if (mspi->rx) | 601 | if (mspi->rx) |
717 | mspi->get_rx(rx_data, mspi); | 602 | mspi->get_rx(rx_data, mspi); |
@@ -720,102 +605,80 @@ static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | |||
720 | if ((events & SPIE_NF) == 0) | 605 | if ((events & SPIE_NF) == 0) |
721 | /* spin until TX is done */ | 606 | /* spin until TX is done */ |
722 | while (((events = | 607 | while (((events = |
723 | mpc8xxx_spi_read_reg(&mspi->base->event)) & | 608 | mpc8xxx_spi_read_reg(®_base->event)) & |
724 | SPIE_NF) == 0) | 609 | SPIE_NF) == 0) |
725 | cpu_relax(); | 610 | cpu_relax(); |
726 | 611 | ||
727 | /* Clear the events */ | 612 | /* Clear the events */ |
728 | mpc8xxx_spi_write_reg(&mspi->base->event, events); | 613 | mpc8xxx_spi_write_reg(®_base->event, events); |
729 | 614 | ||
730 | mspi->count -= 1; | 615 | mspi->count -= 1; |
731 | if (mspi->count) { | 616 | if (mspi->count) { |
732 | u32 word = mspi->get_tx(mspi); | 617 | u32 word = mspi->get_tx(mspi); |
733 | 618 | ||
734 | mpc8xxx_spi_write_reg(&mspi->base->transmit, word); | 619 | mpc8xxx_spi_write_reg(®_base->transmit, word); |
735 | } else { | 620 | } else { |
736 | complete(&mspi->done); | 621 | complete(&mspi->done); |
737 | } | 622 | } |
738 | } | 623 | } |
739 | 624 | ||
740 | static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data) | 625 | static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) |
741 | { | 626 | { |
742 | struct mpc8xxx_spi *mspi = context_data; | 627 | struct mpc8xxx_spi *mspi = context_data; |
743 | irqreturn_t ret = IRQ_NONE; | 628 | irqreturn_t ret = IRQ_NONE; |
744 | u32 events; | 629 | u32 events; |
630 | struct fsl_spi_reg *reg_base = mspi->reg_base; | ||
745 | 631 | ||
746 | /* Get interrupt events(tx/rx) */ | 632 | /* Get interrupt events(tx/rx) */ |
747 | events = mpc8xxx_spi_read_reg(&mspi->base->event); | 633 | events = mpc8xxx_spi_read_reg(®_base->event); |
748 | if (events) | 634 | if (events) |
749 | ret = IRQ_HANDLED; | 635 | ret = IRQ_HANDLED; |
750 | 636 | ||
751 | dev_dbg(mspi->dev, "%s: events %x\n", __func__, events); | 637 | dev_dbg(mspi->dev, "%s: events %x\n", __func__, events); |
752 | 638 | ||
753 | if (mspi->flags & SPI_CPM_MODE) | 639 | if (mspi->flags & SPI_CPM_MODE) |
754 | mpc8xxx_spi_cpm_irq(mspi, events); | 640 | fsl_spi_cpm_irq(mspi, events); |
755 | else | 641 | else |
756 | mpc8xxx_spi_cpu_irq(mspi, events); | 642 | fsl_spi_cpu_irq(mspi, events); |
757 | 643 | ||
758 | return ret; | 644 | return ret; |
759 | } | 645 | } |
760 | 646 | ||
761 | static int mpc8xxx_spi_transfer(struct spi_device *spi, | 647 | static void *fsl_spi_alloc_dummy_rx(void) |
762 | struct spi_message *m) | ||
763 | { | 648 | { |
764 | struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); | 649 | mutex_lock(&fsl_dummy_rx_lock); |
765 | unsigned long flags; | ||
766 | 650 | ||
767 | m->actual_length = 0; | 651 | if (!fsl_dummy_rx) |
768 | m->status = -EINPROGRESS; | 652 | fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); |
653 | if (fsl_dummy_rx) | ||
654 | fsl_dummy_rx_refcnt++; | ||
769 | 655 | ||
770 | spin_lock_irqsave(&mpc8xxx_spi->lock, flags); | 656 | mutex_unlock(&fsl_dummy_rx_lock); |
771 | list_add_tail(&m->queue, &mpc8xxx_spi->queue); | ||
772 | queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work); | ||
773 | spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags); | ||
774 | 657 | ||
775 | return 0; | 658 | return fsl_dummy_rx; |
776 | } | 659 | } |
777 | 660 | ||
778 | 661 | static void fsl_spi_free_dummy_rx(void) | |
779 | static void mpc8xxx_spi_cleanup(struct spi_device *spi) | ||
780 | { | 662 | { |
781 | kfree(spi->controller_state); | 663 | mutex_lock(&fsl_dummy_rx_lock); |
782 | } | ||
783 | 664 | ||
784 | static void *mpc8xxx_spi_alloc_dummy_rx(void) | 665 | switch (fsl_dummy_rx_refcnt) { |
785 | { | ||
786 | mutex_lock(&mpc8xxx_dummy_rx_lock); | ||
787 | |||
788 | if (!mpc8xxx_dummy_rx) | ||
789 | mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL); | ||
790 | if (mpc8xxx_dummy_rx) | ||
791 | mpc8xxx_dummy_rx_refcnt++; | ||
792 | |||
793 | mutex_unlock(&mpc8xxx_dummy_rx_lock); | ||
794 | |||
795 | return mpc8xxx_dummy_rx; | ||
796 | } | ||
797 | |||
798 | static void mpc8xxx_spi_free_dummy_rx(void) | ||
799 | { | ||
800 | mutex_lock(&mpc8xxx_dummy_rx_lock); | ||
801 | |||
802 | switch (mpc8xxx_dummy_rx_refcnt) { | ||
803 | case 0: | 666 | case 0: |
804 | WARN_ON(1); | 667 | WARN_ON(1); |
805 | break; | 668 | break; |
806 | case 1: | 669 | case 1: |
807 | kfree(mpc8xxx_dummy_rx); | 670 | kfree(fsl_dummy_rx); |
808 | mpc8xxx_dummy_rx = NULL; | 671 | fsl_dummy_rx = NULL; |
809 | /* fall through */ | 672 | /* fall through */ |
810 | default: | 673 | default: |
811 | mpc8xxx_dummy_rx_refcnt--; | 674 | fsl_dummy_rx_refcnt--; |
812 | break; | 675 | break; |
813 | } | 676 | } |
814 | 677 | ||
815 | mutex_unlock(&mpc8xxx_dummy_rx_lock); | 678 | mutex_unlock(&fsl_dummy_rx_lock); |
816 | } | 679 | } |
817 | 680 | ||
818 | static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) | 681 | static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) |
819 | { | 682 | { |
820 | struct device *dev = mspi->dev; | 683 | struct device *dev = mspi->dev; |
821 | struct device_node *np = dev->of_node; | 684 | struct device_node *np = dev->of_node; |
@@ -869,7 +732,7 @@ static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi) | |||
869 | return pram_ofs; | 732 | return pram_ofs; |
870 | } | 733 | } |
871 | 734 | ||
872 | static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi) | 735 | static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) |
873 | { | 736 | { |
874 | struct device *dev = mspi->dev; | 737 | struct device *dev = mspi->dev; |
875 | struct device_node *np = dev->of_node; | 738 | struct device_node *np = dev->of_node; |
@@ -881,7 +744,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi) | |||
881 | if (!(mspi->flags & SPI_CPM_MODE)) | 744 | if (!(mspi->flags & SPI_CPM_MODE)) |
882 | return 0; | 745 | return 0; |
883 | 746 | ||
884 | if (!mpc8xxx_spi_alloc_dummy_rx()) | 747 | if (!fsl_spi_alloc_dummy_rx()) |
885 | return -ENOMEM; | 748 | return -ENOMEM; |
886 | 749 | ||
887 | if (mspi->flags & SPI_QE) { | 750 | if (mspi->flags & SPI_QE) { |
@@ -902,7 +765,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi) | |||
902 | } | 765 | } |
903 | } | 766 | } |
904 | 767 | ||
905 | pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi); | 768 | pram_ofs = fsl_spi_cpm_get_pram(mspi); |
906 | if (IS_ERR_VALUE(pram_ofs)) { | 769 | if (IS_ERR_VALUE(pram_ofs)) { |
907 | dev_err(dev, "can't allocate spi parameter ram\n"); | 770 | dev_err(dev, "can't allocate spi parameter ram\n"); |
908 | goto err_pram; | 771 | goto err_pram; |
@@ -922,7 +785,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi) | |||
922 | goto err_dummy_tx; | 785 | goto err_dummy_tx; |
923 | } | 786 | } |
924 | 787 | ||
925 | mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR, | 788 | mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR, |
926 | DMA_FROM_DEVICE); | 789 | DMA_FROM_DEVICE); |
927 | if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { | 790 | if (dma_mapping_error(dev, mspi->dma_dummy_rx)) { |
928 | dev_err(dev, "unable to map dummy rx buffer\n"); | 791 | dev_err(dev, "unable to map dummy rx buffer\n"); |
@@ -960,11 +823,11 @@ err_dummy_tx: | |||
960 | err_bds: | 823 | err_bds: |
961 | cpm_muram_free(pram_ofs); | 824 | cpm_muram_free(pram_ofs); |
962 | err_pram: | 825 | err_pram: |
963 | mpc8xxx_spi_free_dummy_rx(); | 826 | fsl_spi_free_dummy_rx(); |
964 | return -ENOMEM; | 827 | return -ENOMEM; |
965 | } | 828 | } |
966 | 829 | ||
967 | static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi) | 830 | static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) |
968 | { | 831 | { |
969 | struct device *dev = mspi->dev; | 832 | struct device *dev = mspi->dev; |
970 | 833 | ||
@@ -972,30 +835,22 @@ static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi) | |||
972 | dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); | 835 | dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); |
973 | cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); | 836 | cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); |
974 | cpm_muram_free(cpm_muram_offset(mspi->pram)); | 837 | cpm_muram_free(cpm_muram_offset(mspi->pram)); |
975 | mpc8xxx_spi_free_dummy_rx(); | 838 | fsl_spi_free_dummy_rx(); |
976 | } | 839 | } |
977 | 840 | ||
978 | static const char *mpc8xxx_spi_strmode(unsigned int flags) | 841 | static void fsl_spi_remove(struct mpc8xxx_spi *mspi) |
979 | { | 842 | { |
980 | if (flags & SPI_QE_CPU_MODE) { | 843 | iounmap(mspi->reg_base); |
981 | return "QE CPU"; | 844 | fsl_spi_cpm_free(mspi); |
982 | } else if (flags & SPI_CPM_MODE) { | ||
983 | if (flags & SPI_QE) | ||
984 | return "QE"; | ||
985 | else if (flags & SPI_CPM2) | ||
986 | return "CPM2"; | ||
987 | else | ||
988 | return "CPM1"; | ||
989 | } | ||
990 | return "CPU"; | ||
991 | } | 845 | } |
992 | 846 | ||
993 | static struct spi_master * __devinit | 847 | static struct spi_master * __devinit fsl_spi_probe(struct device *dev, |
994 | mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) | 848 | struct resource *mem, unsigned int irq) |
995 | { | 849 | { |
996 | struct fsl_spi_platform_data *pdata = dev->platform_data; | 850 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
997 | struct spi_master *master; | 851 | struct spi_master *master; |
998 | struct mpc8xxx_spi *mpc8xxx_spi; | 852 | struct mpc8xxx_spi *mpc8xxx_spi; |
853 | struct fsl_spi_reg *reg_base; | ||
999 | u32 regval; | 854 | u32 regval; |
1000 | int ret = 0; | 855 | int ret = 0; |
1001 | 856 | ||
@@ -1007,132 +862,77 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) | |||
1007 | 862 | ||
1008 | dev_set_drvdata(dev, master); | 863 | dev_set_drvdata(dev, master); |
1009 | 864 | ||
1010 | /* the spi->mode bits understood by this driver: */ | 865 | ret = mpc8xxx_spi_probe(dev, mem, irq); |
1011 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | 866 | if (ret) |
1012 | | SPI_LSB_FIRST | SPI_LOOP; | 867 | goto err_probe; |
1013 | 868 | ||
1014 | master->setup = mpc8xxx_spi_setup; | 869 | master->setup = fsl_spi_setup; |
1015 | master->transfer = mpc8xxx_spi_transfer; | ||
1016 | master->cleanup = mpc8xxx_spi_cleanup; | ||
1017 | master->dev.of_node = dev->of_node; | ||
1018 | 870 | ||
1019 | mpc8xxx_spi = spi_master_get_devdata(master); | 871 | mpc8xxx_spi = spi_master_get_devdata(master); |
1020 | mpc8xxx_spi->dev = dev; | 872 | mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg; |
1021 | mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; | 873 | mpc8xxx_spi->spi_remove = fsl_spi_remove; |
1022 | mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8; | 874 | |
1023 | mpc8xxx_spi->flags = pdata->flags; | ||
1024 | mpc8xxx_spi->spibrg = pdata->sysclk; | ||
1025 | 875 | ||
1026 | ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi); | 876 | ret = fsl_spi_cpm_init(mpc8xxx_spi); |
1027 | if (ret) | 877 | if (ret) |
1028 | goto err_cpm_init; | 878 | goto err_cpm_init; |
1029 | 879 | ||
1030 | mpc8xxx_spi->rx_shift = 0; | ||
1031 | mpc8xxx_spi->tx_shift = 0; | ||
1032 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { | 880 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { |
1033 | mpc8xxx_spi->rx_shift = 16; | 881 | mpc8xxx_spi->rx_shift = 16; |
1034 | mpc8xxx_spi->tx_shift = 24; | 882 | mpc8xxx_spi->tx_shift = 24; |
1035 | } | 883 | } |
1036 | 884 | ||
1037 | init_completion(&mpc8xxx_spi->done); | 885 | mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); |
1038 | 886 | if (mpc8xxx_spi->reg_base == NULL) { | |
1039 | mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem)); | ||
1040 | if (mpc8xxx_spi->base == NULL) { | ||
1041 | ret = -ENOMEM; | 887 | ret = -ENOMEM; |
1042 | goto err_ioremap; | 888 | goto err_ioremap; |
1043 | } | 889 | } |
1044 | 890 | ||
1045 | mpc8xxx_spi->irq = irq; | ||
1046 | |||
1047 | /* Register for SPI Interrupt */ | 891 | /* Register for SPI Interrupt */ |
1048 | ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq, | 892 | ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq, |
1049 | 0, "mpc8xxx_spi", mpc8xxx_spi); | 893 | 0, "fsl_spi", mpc8xxx_spi); |
1050 | 894 | ||
1051 | if (ret != 0) | 895 | if (ret != 0) |
1052 | goto unmap_io; | 896 | goto free_irq; |
1053 | 897 | ||
1054 | master->bus_num = pdata->bus_num; | 898 | reg_base = mpc8xxx_spi->reg_base; |
1055 | master->num_chipselect = pdata->max_chipselect; | ||
1056 | 899 | ||
1057 | /* SPI controller initializations */ | 900 | /* SPI controller initializations */ |
1058 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0); | 901 | mpc8xxx_spi_write_reg(®_base->mode, 0); |
1059 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0); | 902 | mpc8xxx_spi_write_reg(®_base->mask, 0); |
1060 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0); | 903 | mpc8xxx_spi_write_reg(®_base->command, 0); |
1061 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff); | 904 | mpc8xxx_spi_write_reg(®_base->event, 0xffffffff); |
1062 | 905 | ||
1063 | /* Enable SPI interface */ | 906 | /* Enable SPI interface */ |
1064 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; | 907 | regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; |
1065 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) | 908 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) |
1066 | regval |= SPMODE_OP; | 909 | regval |= SPMODE_OP; |
1067 | 910 | ||
1068 | mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval); | 911 | mpc8xxx_spi_write_reg(®_base->mode, regval); |
1069 | spin_lock_init(&mpc8xxx_spi->lock); | ||
1070 | init_completion(&mpc8xxx_spi->done); | ||
1071 | INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work); | ||
1072 | INIT_LIST_HEAD(&mpc8xxx_spi->queue); | ||
1073 | |||
1074 | mpc8xxx_spi->workqueue = create_singlethread_workqueue( | ||
1075 | dev_name(master->dev.parent)); | ||
1076 | if (mpc8xxx_spi->workqueue == NULL) { | ||
1077 | ret = -EBUSY; | ||
1078 | goto free_irq; | ||
1079 | } | ||
1080 | 912 | ||
1081 | ret = spi_register_master(master); | 913 | ret = spi_register_master(master); |
1082 | if (ret < 0) | 914 | if (ret < 0) |
1083 | goto unreg_master; | 915 | goto unreg_master; |
1084 | 916 | ||
1085 | dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base, | 917 | dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base, |
1086 | mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); | 918 | mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); |
1087 | 919 | ||
1088 | return master; | 920 | return master; |
1089 | 921 | ||
1090 | unreg_master: | 922 | unreg_master: |
1091 | destroy_workqueue(mpc8xxx_spi->workqueue); | ||
1092 | free_irq: | ||
1093 | free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | 923 | free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); |
1094 | unmap_io: | 924 | free_irq: |
1095 | iounmap(mpc8xxx_spi->base); | 925 | iounmap(mpc8xxx_spi->reg_base); |
1096 | err_ioremap: | 926 | err_ioremap: |
1097 | mpc8xxx_spi_cpm_free(mpc8xxx_spi); | 927 | fsl_spi_cpm_free(mpc8xxx_spi); |
1098 | err_cpm_init: | 928 | err_cpm_init: |
929 | err_probe: | ||
1099 | spi_master_put(master); | 930 | spi_master_put(master); |
1100 | err: | 931 | err: |
1101 | return ERR_PTR(ret); | 932 | return ERR_PTR(ret); |
1102 | } | 933 | } |
1103 | 934 | ||
1104 | static int __devexit mpc8xxx_spi_remove(struct device *dev) | 935 | static void fsl_spi_cs_control(struct spi_device *spi, bool on) |
1105 | { | ||
1106 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
1107 | struct spi_master *master; | ||
1108 | |||
1109 | master = dev_get_drvdata(dev); | ||
1110 | mpc8xxx_spi = spi_master_get_devdata(master); | ||
1111 | |||
1112 | flush_workqueue(mpc8xxx_spi->workqueue); | ||
1113 | destroy_workqueue(mpc8xxx_spi->workqueue); | ||
1114 | spi_unregister_master(master); | ||
1115 | |||
1116 | free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); | ||
1117 | iounmap(mpc8xxx_spi->base); | ||
1118 | mpc8xxx_spi_cpm_free(mpc8xxx_spi); | ||
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | struct mpc8xxx_spi_probe_info { | ||
1124 | struct fsl_spi_platform_data pdata; | ||
1125 | int *gpios; | ||
1126 | bool *alow_flags; | ||
1127 | }; | ||
1128 | |||
1129 | static struct mpc8xxx_spi_probe_info * | ||
1130 | to_of_pinfo(struct fsl_spi_platform_data *pdata) | ||
1131 | { | ||
1132 | return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata); | ||
1133 | } | ||
1134 | |||
1135 | static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on) | ||
1136 | { | 936 | { |
1137 | struct device *dev = spi->dev.parent; | 937 | struct device *dev = spi->dev.parent; |
1138 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data); | 938 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data); |
@@ -1143,7 +943,7 @@ static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on) | |||
1143 | gpio_set_value(gpio, on ^ alow); | 943 | gpio_set_value(gpio, on ^ alow); |
1144 | } | 944 | } |
1145 | 945 | ||
1146 | static int of_mpc8xxx_spi_get_chipselects(struct device *dev) | 946 | static int of_fsl_spi_get_chipselects(struct device *dev) |
1147 | { | 947 | { |
1148 | struct device_node *np = dev->of_node; | 948 | struct device_node *np = dev->of_node; |
1149 | struct fsl_spi_platform_data *pdata = dev->platform_data; | 949 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
@@ -1204,7 +1004,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev) | |||
1204 | } | 1004 | } |
1205 | 1005 | ||
1206 | pdata->max_chipselect = ngpios; | 1006 | pdata->max_chipselect = ngpios; |
1207 | pdata->cs_control = mpc8xxx_spi_cs_control; | 1007 | pdata->cs_control = fsl_spi_cs_control; |
1208 | 1008 | ||
1209 | return 0; | 1009 | return 0; |
1210 | 1010 | ||
@@ -1223,7 +1023,7 @@ err_alloc_flags: | |||
1223 | return ret; | 1023 | return ret; |
1224 | } | 1024 | } |
1225 | 1025 | ||
1226 | static int of_mpc8xxx_spi_free_chipselects(struct device *dev) | 1026 | static int of_fsl_spi_free_chipselects(struct device *dev) |
1227 | { | 1027 | { |
1228 | struct fsl_spi_platform_data *pdata = dev->platform_data; | 1028 | struct fsl_spi_platform_data *pdata = dev->platform_data; |
1229 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); | 1029 | struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); |
@@ -1242,50 +1042,21 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev) | |||
1242 | return 0; | 1042 | return 0; |
1243 | } | 1043 | } |
1244 | 1044 | ||
1245 | static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, | 1045 | static int __devinit of_fsl_spi_probe(struct platform_device *ofdev, |
1246 | const struct of_device_id *ofid) | 1046 | const struct of_device_id *ofid) |
1247 | { | 1047 | { |
1248 | struct device *dev = &ofdev->dev; | 1048 | struct device *dev = &ofdev->dev; |
1249 | struct device_node *np = ofdev->dev.of_node; | 1049 | struct device_node *np = ofdev->dev.of_node; |
1250 | struct mpc8xxx_spi_probe_info *pinfo; | ||
1251 | struct fsl_spi_platform_data *pdata; | ||
1252 | struct spi_master *master; | 1050 | struct spi_master *master; |
1253 | struct resource mem; | 1051 | struct resource mem; |
1254 | struct resource irq; | 1052 | struct resource irq; |
1255 | const void *prop; | ||
1256 | int ret = -ENOMEM; | 1053 | int ret = -ENOMEM; |
1257 | 1054 | ||
1258 | pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); | 1055 | ret = of_mpc8xxx_spi_probe(ofdev, ofid); |
1259 | if (!pinfo) | 1056 | if (ret) |
1260 | return -ENOMEM; | 1057 | return ret; |
1261 | |||
1262 | pdata = &pinfo->pdata; | ||
1263 | dev->platform_data = pdata; | ||
1264 | |||
1265 | /* Allocate bus num dynamically. */ | ||
1266 | pdata->bus_num = -1; | ||
1267 | |||
1268 | /* SPI controller is either clocked from QE or SoC clock. */ | ||
1269 | pdata->sysclk = get_brgfreq(); | ||
1270 | if (pdata->sysclk == -1) { | ||
1271 | pdata->sysclk = fsl_get_sys_freq(); | ||
1272 | if (pdata->sysclk == -1) { | ||
1273 | ret = -ENODEV; | ||
1274 | goto err_clk; | ||
1275 | } | ||
1276 | } | ||
1277 | 1058 | ||
1278 | prop = of_get_property(np, "mode", NULL); | 1059 | ret = of_fsl_spi_get_chipselects(dev); |
1279 | if (prop && !strcmp(prop, "cpu-qe")) | ||
1280 | pdata->flags = SPI_QE_CPU_MODE; | ||
1281 | else if (prop && !strcmp(prop, "qe")) | ||
1282 | pdata->flags = SPI_CPM_MODE | SPI_QE; | ||
1283 | else if (of_device_is_compatible(np, "fsl,cpm2-spi")) | ||
1284 | pdata->flags = SPI_CPM_MODE | SPI_CPM2; | ||
1285 | else if (of_device_is_compatible(np, "fsl,cpm1-spi")) | ||
1286 | pdata->flags = SPI_CPM_MODE | SPI_CPM1; | ||
1287 | |||
1288 | ret = of_mpc8xxx_spi_get_chipselects(dev); | ||
1289 | if (ret) | 1060 | if (ret) |
1290 | goto err; | 1061 | goto err; |
1291 | 1062 | ||
@@ -1299,7 +1070,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, | |||
1299 | goto err; | 1070 | goto err; |
1300 | } | 1071 | } |
1301 | 1072 | ||
1302 | master = mpc8xxx_spi_probe(dev, &mem, irq.start); | 1073 | master = fsl_spi_probe(dev, &mem, irq.start); |
1303 | if (IS_ERR(master)) { | 1074 | if (IS_ERR(master)) { |
1304 | ret = PTR_ERR(master); | 1075 | ret = PTR_ERR(master); |
1305 | goto err; | 1076 | goto err; |
@@ -1308,42 +1079,40 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, | |||
1308 | return 0; | 1079 | return 0; |
1309 | 1080 | ||
1310 | err: | 1081 | err: |
1311 | of_mpc8xxx_spi_free_chipselects(dev); | 1082 | of_fsl_spi_free_chipselects(dev); |
1312 | err_clk: | ||
1313 | kfree(pinfo); | ||
1314 | return ret; | 1083 | return ret; |
1315 | } | 1084 | } |
1316 | 1085 | ||
1317 | static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev) | 1086 | static int __devexit of_fsl_spi_remove(struct platform_device *ofdev) |
1318 | { | 1087 | { |
1319 | int ret; | 1088 | int ret; |
1320 | 1089 | ||
1321 | ret = mpc8xxx_spi_remove(&ofdev->dev); | 1090 | ret = mpc8xxx_spi_remove(&ofdev->dev); |
1322 | if (ret) | 1091 | if (ret) |
1323 | return ret; | 1092 | return ret; |
1324 | of_mpc8xxx_spi_free_chipselects(&ofdev->dev); | 1093 | of_fsl_spi_free_chipselects(&ofdev->dev); |
1325 | return 0; | 1094 | return 0; |
1326 | } | 1095 | } |
1327 | 1096 | ||
1328 | static const struct of_device_id of_mpc8xxx_spi_match[] = { | 1097 | static const struct of_device_id of_fsl_spi_match[] = { |
1329 | { .compatible = "fsl,spi" }, | 1098 | { .compatible = "fsl,spi" }, |
1330 | {}, | 1099 | {} |
1331 | }; | 1100 | }; |
1332 | MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match); | 1101 | MODULE_DEVICE_TABLE(of, of_fsl_spi_match); |
1333 | 1102 | ||
1334 | static struct of_platform_driver of_mpc8xxx_spi_driver = { | 1103 | static struct of_platform_driver of_fsl_spi_driver = { |
1335 | .driver = { | 1104 | .driver = { |
1336 | .name = "mpc8xxx_spi", | 1105 | .name = "fsl_spi", |
1337 | .owner = THIS_MODULE, | 1106 | .owner = THIS_MODULE, |
1338 | .of_match_table = of_mpc8xxx_spi_match, | 1107 | .of_match_table = of_fsl_spi_match, |
1339 | }, | 1108 | }, |
1340 | .probe = of_mpc8xxx_spi_probe, | 1109 | .probe = of_fsl_spi_probe, |
1341 | .remove = __devexit_p(of_mpc8xxx_spi_remove), | 1110 | .remove = __devexit_p(of_fsl_spi_remove), |
1342 | }; | 1111 | }; |
1343 | 1112 | ||
1344 | #ifdef CONFIG_MPC832x_RDB | 1113 | #ifdef CONFIG_MPC832x_RDB |
1345 | /* | 1114 | /* |
1346 | * XXX XXX XXX | 1115 | * XXX XXX XXX |
1347 | * This is "legacy" platform driver, was used by the MPC8323E-RDB boards | 1116 | * This is "legacy" platform driver, was used by the MPC8323E-RDB boards |
1348 | * only. The driver should go away soon, since newer MPC8323E-RDB's device | 1117 | * only. The driver should go away soon, since newer MPC8323E-RDB's device |
1349 | * tree can work with OpenFirmware driver. But for now we support old trees | 1118 | * tree can work with OpenFirmware driver. But for now we support old trees |
@@ -1366,7 +1135,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev) | |||
1366 | if (irq <= 0) | 1135 | if (irq <= 0) |
1367 | return -EINVAL; | 1136 | return -EINVAL; |
1368 | 1137 | ||
1369 | master = mpc8xxx_spi_probe(&pdev->dev, mem, irq); | 1138 | master = fsl_spi_probe(&pdev->dev, mem, irq); |
1370 | if (IS_ERR(master)) | 1139 | if (IS_ERR(master)) |
1371 | return PTR_ERR(master); | 1140 | return PTR_ERR(master); |
1372 | return 0; | 1141 | return 0; |
@@ -1405,21 +1174,20 @@ static void __init legacy_driver_register(void) {} | |||
1405 | static void __exit legacy_driver_unregister(void) {} | 1174 | static void __exit legacy_driver_unregister(void) {} |
1406 | #endif /* CONFIG_MPC832x_RDB */ | 1175 | #endif /* CONFIG_MPC832x_RDB */ |
1407 | 1176 | ||
1408 | static int __init mpc8xxx_spi_init(void) | 1177 | static int __init fsl_spi_init(void) |
1409 | { | 1178 | { |
1410 | legacy_driver_register(); | 1179 | legacy_driver_register(); |
1411 | return of_register_platform_driver(&of_mpc8xxx_spi_driver); | 1180 | return of_register_platform_driver(&of_fsl_spi_driver); |
1412 | } | 1181 | } |
1182 | module_init(fsl_spi_init); | ||
1413 | 1183 | ||
1414 | static void __exit mpc8xxx_spi_exit(void) | 1184 | static void __exit fsl_spi_exit(void) |
1415 | { | 1185 | { |
1416 | of_unregister_platform_driver(&of_mpc8xxx_spi_driver); | 1186 | of_unregister_platform_driver(&of_fsl_spi_driver); |
1417 | legacy_driver_unregister(); | 1187 | legacy_driver_unregister(); |
1418 | } | 1188 | } |
1419 | 1189 | module_exit(fsl_spi_exit); | |
1420 | module_init(mpc8xxx_spi_init); | ||
1421 | module_exit(mpc8xxx_spi_exit); | ||
1422 | 1190 | ||
1423 | MODULE_AUTHOR("Kumar Gala"); | 1191 | MODULE_AUTHOR("Kumar Gala"); |
1424 | MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver"); | 1192 | MODULE_DESCRIPTION("Simple Freescale SPI Driver"); |
1425 | MODULE_LICENSE("GPL"); | 1193 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 7972e9077473..55a38e2c6c13 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
@@ -56,7 +56,28 @@ struct spi_imx_config { | |||
56 | unsigned int speed_hz; | 56 | unsigned int speed_hz; |
57 | unsigned int bpw; | 57 | unsigned int bpw; |
58 | unsigned int mode; | 58 | unsigned int mode; |
59 | int cs; | 59 | u8 cs; |
60 | }; | ||
61 | |||
62 | enum spi_imx_devtype { | ||
63 | SPI_IMX_VER_IMX1, | ||
64 | SPI_IMX_VER_0_0, | ||
65 | SPI_IMX_VER_0_4, | ||
66 | SPI_IMX_VER_0_5, | ||
67 | SPI_IMX_VER_0_7, | ||
68 | SPI_IMX_VER_2_3, | ||
69 | SPI_IMX_VER_AUTODETECT, | ||
70 | }; | ||
71 | |||
72 | struct spi_imx_data; | ||
73 | |||
74 | struct spi_imx_devtype_data { | ||
75 | void (*intctrl)(struct spi_imx_data *, int); | ||
76 | int (*config)(struct spi_imx_data *, struct spi_imx_config *); | ||
77 | void (*trigger)(struct spi_imx_data *); | ||
78 | int (*rx_available)(struct spi_imx_data *); | ||
79 | void (*reset)(struct spi_imx_data *); | ||
80 | unsigned int fifosize; | ||
60 | }; | 81 | }; |
61 | 82 | ||
62 | struct spi_imx_data { | 83 | struct spi_imx_data { |
@@ -76,11 +97,7 @@ struct spi_imx_data { | |||
76 | const void *tx_buf; | 97 | const void *tx_buf; |
77 | unsigned int txfifo; /* number of words pushed in tx FIFO */ | 98 | unsigned int txfifo; /* number of words pushed in tx FIFO */ |
78 | 99 | ||
79 | /* SoC specific functions */ | 100 | struct spi_imx_devtype_data devtype_data; |
80 | void (*intctrl)(struct spi_imx_data *, int); | ||
81 | int (*config)(struct spi_imx_data *, struct spi_imx_config *); | ||
82 | void (*trigger)(struct spi_imx_data *); | ||
83 | int (*rx_available)(struct spi_imx_data *); | ||
84 | }; | 101 | }; |
85 | 102 | ||
86 | #define MXC_SPI_BUF_RX(type) \ | 103 | #define MXC_SPI_BUF_RX(type) \ |
@@ -140,7 +157,7 @@ static unsigned int spi_imx_clkdiv_1(unsigned int fin, | |||
140 | return max; | 157 | return max; |
141 | } | 158 | } |
142 | 159 | ||
143 | /* MX1, MX31, MX35 */ | 160 | /* MX1, MX31, MX35, MX51 CSPI */ |
144 | static unsigned int spi_imx_clkdiv_2(unsigned int fin, | 161 | static unsigned int spi_imx_clkdiv_2(unsigned int fin, |
145 | unsigned int fspi) | 162 | unsigned int fspi) |
146 | { | 163 | { |
@@ -155,6 +172,128 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
155 | return 7; | 172 | return 7; |
156 | } | 173 | } |
157 | 174 | ||
175 | #define SPI_IMX2_3_CTRL 0x08 | ||
176 | #define SPI_IMX2_3_CTRL_ENABLE (1 << 0) | ||
177 | #define SPI_IMX2_3_CTRL_XCH (1 << 2) | ||
178 | #define SPI_IMX2_3_CTRL_MODE(cs) (1 << ((cs) + 4)) | ||
179 | #define SPI_IMX2_3_CTRL_POSTDIV_OFFSET 8 | ||
180 | #define SPI_IMX2_3_CTRL_PREDIV_OFFSET 12 | ||
181 | #define SPI_IMX2_3_CTRL_CS(cs) ((cs) << 18) | ||
182 | #define SPI_IMX2_3_CTRL_BL_OFFSET 20 | ||
183 | |||
184 | #define SPI_IMX2_3_CONFIG 0x0c | ||
185 | #define SPI_IMX2_3_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0)) | ||
186 | #define SPI_IMX2_3_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4)) | ||
187 | #define SPI_IMX2_3_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8)) | ||
188 | #define SPI_IMX2_3_CONFIG_SSBPOL(cs) (1 << ((cs) + 12)) | ||
189 | |||
190 | #define SPI_IMX2_3_INT 0x10 | ||
191 | #define SPI_IMX2_3_INT_TEEN (1 << 0) | ||
192 | #define SPI_IMX2_3_INT_RREN (1 << 3) | ||
193 | |||
194 | #define SPI_IMX2_3_STAT 0x18 | ||
195 | #define SPI_IMX2_3_STAT_RR (1 << 3) | ||
196 | |||
197 | /* MX51 eCSPI */ | ||
198 | static unsigned int spi_imx2_3_clkdiv(unsigned int fin, unsigned int fspi) | ||
199 | { | ||
200 | /* | ||
201 | * there are two 4-bit dividers, the pre-divider divides by | ||
202 | * $pre, the post-divider by 2^$post | ||
203 | */ | ||
204 | unsigned int pre, post; | ||
205 | |||
206 | if (unlikely(fspi > fin)) | ||
207 | return 0; | ||
208 | |||
209 | post = fls(fin) - fls(fspi); | ||
210 | if (fin > fspi << post) | ||
211 | post++; | ||
212 | |||
213 | /* now we have: (fin <= fspi << post) with post being minimal */ | ||
214 | |||
215 | post = max(4U, post) - 4; | ||
216 | if (unlikely(post > 0xf)) { | ||
217 | pr_err("%s: cannot set clock freq: %u (base freq: %u)\n", | ||
218 | __func__, fspi, fin); | ||
219 | return 0xff; | ||
220 | } | ||
221 | |||
222 | pre = DIV_ROUND_UP(fin, fspi << post) - 1; | ||
223 | |||
224 | pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n", | ||
225 | __func__, fin, fspi, post, pre); | ||
226 | return (pre << SPI_IMX2_3_CTRL_PREDIV_OFFSET) | | ||
227 | (post << SPI_IMX2_3_CTRL_POSTDIV_OFFSET); | ||
228 | } | ||
229 | |||
230 | static void __maybe_unused spi_imx2_3_intctrl(struct spi_imx_data *spi_imx, int enable) | ||
231 | { | ||
232 | unsigned val = 0; | ||
233 | |||
234 | if (enable & MXC_INT_TE) | ||
235 | val |= SPI_IMX2_3_INT_TEEN; | ||
236 | |||
237 | if (enable & MXC_INT_RR) | ||
238 | val |= SPI_IMX2_3_INT_RREN; | ||
239 | |||
240 | writel(val, spi_imx->base + SPI_IMX2_3_INT); | ||
241 | } | ||
242 | |||
243 | static void __maybe_unused spi_imx2_3_trigger(struct spi_imx_data *spi_imx) | ||
244 | { | ||
245 | u32 reg; | ||
246 | |||
247 | reg = readl(spi_imx->base + SPI_IMX2_3_CTRL); | ||
248 | reg |= SPI_IMX2_3_CTRL_XCH; | ||
249 | writel(reg, spi_imx->base + SPI_IMX2_3_CTRL); | ||
250 | } | ||
251 | |||
252 | static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx, | ||
253 | struct spi_imx_config *config) | ||
254 | { | ||
255 | u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0; | ||
256 | |||
257 | /* set master mode */ | ||
258 | ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs); | ||
259 | |||
260 | /* set clock speed */ | ||
261 | ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz); | ||
262 | |||
263 | /* set chip select to use */ | ||
264 | ctrl |= SPI_IMX2_3_CTRL_CS(config->cs); | ||
265 | |||
266 | ctrl |= (config->bpw - 1) << SPI_IMX2_3_CTRL_BL_OFFSET; | ||
267 | |||
268 | cfg |= SPI_IMX2_3_CONFIG_SBBCTRL(config->cs); | ||
269 | |||
270 | if (config->mode & SPI_CPHA) | ||
271 | cfg |= SPI_IMX2_3_CONFIG_SCLKPHA(config->cs); | ||
272 | |||
273 | if (config->mode & SPI_CPOL) | ||
274 | cfg |= SPI_IMX2_3_CONFIG_SCLKPOL(config->cs); | ||
275 | |||
276 | if (config->mode & SPI_CS_HIGH) | ||
277 | cfg |= SPI_IMX2_3_CONFIG_SSBPOL(config->cs); | ||
278 | |||
279 | writel(ctrl, spi_imx->base + SPI_IMX2_3_CTRL); | ||
280 | writel(cfg, spi_imx->base + SPI_IMX2_3_CONFIG); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int __maybe_unused spi_imx2_3_rx_available(struct spi_imx_data *spi_imx) | ||
286 | { | ||
287 | return readl(spi_imx->base + SPI_IMX2_3_STAT) & SPI_IMX2_3_STAT_RR; | ||
288 | } | ||
289 | |||
290 | static void __maybe_unused spi_imx2_3_reset(struct spi_imx_data *spi_imx) | ||
291 | { | ||
292 | /* drain receive buffer */ | ||
293 | while (spi_imx2_3_rx_available(spi_imx)) | ||
294 | readl(spi_imx->base + MXC_CSPIRXDATA); | ||
295 | } | ||
296 | |||
158 | #define MX31_INTREG_TEEN (1 << 0) | 297 | #define MX31_INTREG_TEEN (1 << 0) |
159 | #define MX31_INTREG_RREN (1 << 3) | 298 | #define MX31_INTREG_RREN (1 << 3) |
160 | 299 | ||
@@ -178,7 +317,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
178 | * the i.MX35 has a slightly different register layout for bits | 317 | * the i.MX35 has a slightly different register layout for bits |
179 | * we do not use here. | 318 | * we do not use here. |
180 | */ | 319 | */ |
181 | static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable) | 320 | static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable) |
182 | { | 321 | { |
183 | unsigned int val = 0; | 322 | unsigned int val = 0; |
184 | 323 | ||
@@ -190,7 +329,7 @@ static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable) | |||
190 | writel(val, spi_imx->base + MXC_CSPIINT); | 329 | writel(val, spi_imx->base + MXC_CSPIINT); |
191 | } | 330 | } |
192 | 331 | ||
193 | static void mx31_trigger(struct spi_imx_data *spi_imx) | 332 | static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx) |
194 | { | 333 | { |
195 | unsigned int reg; | 334 | unsigned int reg; |
196 | 335 | ||
@@ -199,20 +338,16 @@ static void mx31_trigger(struct spi_imx_data *spi_imx) | |||
199 | writel(reg, spi_imx->base + MXC_CSPICTRL); | 338 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
200 | } | 339 | } |
201 | 340 | ||
202 | static int mx31_config(struct spi_imx_data *spi_imx, | 341 | static int __maybe_unused spi_imx0_4_config(struct spi_imx_data *spi_imx, |
203 | struct spi_imx_config *config) | 342 | struct spi_imx_config *config) |
204 | { | 343 | { |
205 | unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; | 344 | unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; |
345 | int cs = spi_imx->chipselect[config->cs]; | ||
206 | 346 | ||
207 | reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << | 347 | reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << |
208 | MX31_CSPICTRL_DR_SHIFT; | 348 | MX31_CSPICTRL_DR_SHIFT; |
209 | 349 | ||
210 | if (cpu_is_mx31()) | 350 | reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; |
211 | reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; | ||
212 | else if (cpu_is_mx25() || cpu_is_mx35()) { | ||
213 | reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; | ||
214 | reg |= MX31_CSPICTRL_SSCTL; | ||
215 | } | ||
216 | 351 | ||
217 | if (config->mode & SPI_CPHA) | 352 | if (config->mode & SPI_CPHA) |
218 | reg |= MX31_CSPICTRL_PHA; | 353 | reg |= MX31_CSPICTRL_PHA; |
@@ -220,23 +355,52 @@ static int mx31_config(struct spi_imx_data *spi_imx, | |||
220 | reg |= MX31_CSPICTRL_POL; | 355 | reg |= MX31_CSPICTRL_POL; |
221 | if (config->mode & SPI_CS_HIGH) | 356 | if (config->mode & SPI_CS_HIGH) |
222 | reg |= MX31_CSPICTRL_SSPOL; | 357 | reg |= MX31_CSPICTRL_SSPOL; |
223 | if (config->cs < 0) { | 358 | if (cs < 0) |
224 | if (cpu_is_mx31()) | 359 | reg |= (cs + 32) << MX31_CSPICTRL_CS_SHIFT; |
225 | reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT; | 360 | |
226 | else if (cpu_is_mx25() || cpu_is_mx35()) | 361 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
227 | reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT; | 362 | |
228 | } | 363 | return 0; |
364 | } | ||
365 | |||
366 | static int __maybe_unused spi_imx0_7_config(struct spi_imx_data *spi_imx, | ||
367 | struct spi_imx_config *config) | ||
368 | { | ||
369 | unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; | ||
370 | int cs = spi_imx->chipselect[config->cs]; | ||
371 | |||
372 | reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << | ||
373 | MX31_CSPICTRL_DR_SHIFT; | ||
374 | |||
375 | reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; | ||
376 | reg |= MX31_CSPICTRL_SSCTL; | ||
377 | |||
378 | if (config->mode & SPI_CPHA) | ||
379 | reg |= MX31_CSPICTRL_PHA; | ||
380 | if (config->mode & SPI_CPOL) | ||
381 | reg |= MX31_CSPICTRL_POL; | ||
382 | if (config->mode & SPI_CS_HIGH) | ||
383 | reg |= MX31_CSPICTRL_SSPOL; | ||
384 | if (cs < 0) | ||
385 | reg |= (cs + 32) << MX35_CSPICTRL_CS_SHIFT; | ||
229 | 386 | ||
230 | writel(reg, spi_imx->base + MXC_CSPICTRL); | 387 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
231 | 388 | ||
232 | return 0; | 389 | return 0; |
233 | } | 390 | } |
234 | 391 | ||
235 | static int mx31_rx_available(struct spi_imx_data *spi_imx) | 392 | static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx) |
236 | { | 393 | { |
237 | return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR; | 394 | return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR; |
238 | } | 395 | } |
239 | 396 | ||
397 | static void __maybe_unused spi_imx0_4_reset(struct spi_imx_data *spi_imx) | ||
398 | { | ||
399 | /* drain receive buffer */ | ||
400 | while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) | ||
401 | readl(spi_imx->base + MXC_CSPIRXDATA); | ||
402 | } | ||
403 | |||
240 | #define MX27_INTREG_RR (1 << 4) | 404 | #define MX27_INTREG_RR (1 << 4) |
241 | #define MX27_INTREG_TEEN (1 << 9) | 405 | #define MX27_INTREG_TEEN (1 << 9) |
242 | #define MX27_INTREG_RREN (1 << 13) | 406 | #define MX27_INTREG_RREN (1 << 13) |
@@ -250,7 +414,7 @@ static int mx31_rx_available(struct spi_imx_data *spi_imx) | |||
250 | #define MX27_CSPICTRL_DR_SHIFT 14 | 414 | #define MX27_CSPICTRL_DR_SHIFT 14 |
251 | #define MX27_CSPICTRL_CS_SHIFT 19 | 415 | #define MX27_CSPICTRL_CS_SHIFT 19 |
252 | 416 | ||
253 | static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable) | 417 | static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable) |
254 | { | 418 | { |
255 | unsigned int val = 0; | 419 | unsigned int val = 0; |
256 | 420 | ||
@@ -262,7 +426,7 @@ static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable) | |||
262 | writel(val, spi_imx->base + MXC_CSPIINT); | 426 | writel(val, spi_imx->base + MXC_CSPIINT); |
263 | } | 427 | } |
264 | 428 | ||
265 | static void mx27_trigger(struct spi_imx_data *spi_imx) | 429 | static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx) |
266 | { | 430 | { |
267 | unsigned int reg; | 431 | unsigned int reg; |
268 | 432 | ||
@@ -271,10 +435,11 @@ static void mx27_trigger(struct spi_imx_data *spi_imx) | |||
271 | writel(reg, spi_imx->base + MXC_CSPICTRL); | 435 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
272 | } | 436 | } |
273 | 437 | ||
274 | static int mx27_config(struct spi_imx_data *spi_imx, | 438 | static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx, |
275 | struct spi_imx_config *config) | 439 | struct spi_imx_config *config) |
276 | { | 440 | { |
277 | unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER; | 441 | unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER; |
442 | int cs = spi_imx->chipselect[config->cs]; | ||
278 | 443 | ||
279 | reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) << | 444 | reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) << |
280 | MX27_CSPICTRL_DR_SHIFT; | 445 | MX27_CSPICTRL_DR_SHIFT; |
@@ -286,19 +451,24 @@ static int mx27_config(struct spi_imx_data *spi_imx, | |||
286 | reg |= MX27_CSPICTRL_POL; | 451 | reg |= MX27_CSPICTRL_POL; |
287 | if (config->mode & SPI_CS_HIGH) | 452 | if (config->mode & SPI_CS_HIGH) |
288 | reg |= MX27_CSPICTRL_SSPOL; | 453 | reg |= MX27_CSPICTRL_SSPOL; |
289 | if (config->cs < 0) | 454 | if (cs < 0) |
290 | reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT; | 455 | reg |= (cs + 32) << MX27_CSPICTRL_CS_SHIFT; |
291 | 456 | ||
292 | writel(reg, spi_imx->base + MXC_CSPICTRL); | 457 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
293 | 458 | ||
294 | return 0; | 459 | return 0; |
295 | } | 460 | } |
296 | 461 | ||
297 | static int mx27_rx_available(struct spi_imx_data *spi_imx) | 462 | static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx) |
298 | { | 463 | { |
299 | return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR; | 464 | return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR; |
300 | } | 465 | } |
301 | 466 | ||
467 | static void __maybe_unused spi_imx0_0_reset(struct spi_imx_data *spi_imx) | ||
468 | { | ||
469 | writel(1, spi_imx->base + MXC_RESET); | ||
470 | } | ||
471 | |||
302 | #define MX1_INTREG_RR (1 << 3) | 472 | #define MX1_INTREG_RR (1 << 3) |
303 | #define MX1_INTREG_TEEN (1 << 8) | 473 | #define MX1_INTREG_TEEN (1 << 8) |
304 | #define MX1_INTREG_RREN (1 << 11) | 474 | #define MX1_INTREG_RREN (1 << 11) |
@@ -310,7 +480,7 @@ static int mx27_rx_available(struct spi_imx_data *spi_imx) | |||
310 | #define MX1_CSPICTRL_MASTER (1 << 10) | 480 | #define MX1_CSPICTRL_MASTER (1 << 10) |
311 | #define MX1_CSPICTRL_DR_SHIFT 13 | 481 | #define MX1_CSPICTRL_DR_SHIFT 13 |
312 | 482 | ||
313 | static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable) | 483 | static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable) |
314 | { | 484 | { |
315 | unsigned int val = 0; | 485 | unsigned int val = 0; |
316 | 486 | ||
@@ -322,7 +492,7 @@ static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable) | |||
322 | writel(val, spi_imx->base + MXC_CSPIINT); | 492 | writel(val, spi_imx->base + MXC_CSPIINT); |
323 | } | 493 | } |
324 | 494 | ||
325 | static void mx1_trigger(struct spi_imx_data *spi_imx) | 495 | static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx) |
326 | { | 496 | { |
327 | unsigned int reg; | 497 | unsigned int reg; |
328 | 498 | ||
@@ -331,7 +501,7 @@ static void mx1_trigger(struct spi_imx_data *spi_imx) | |||
331 | writel(reg, spi_imx->base + MXC_CSPICTRL); | 501 | writel(reg, spi_imx->base + MXC_CSPICTRL); |
332 | } | 502 | } |
333 | 503 | ||
334 | static int mx1_config(struct spi_imx_data *spi_imx, | 504 | static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx, |
335 | struct spi_imx_config *config) | 505 | struct spi_imx_config *config) |
336 | { | 506 | { |
337 | unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; | 507 | unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; |
@@ -350,11 +520,73 @@ static int mx1_config(struct spi_imx_data *spi_imx, | |||
350 | return 0; | 520 | return 0; |
351 | } | 521 | } |
352 | 522 | ||
353 | static int mx1_rx_available(struct spi_imx_data *spi_imx) | 523 | static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx) |
354 | { | 524 | { |
355 | return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR; | 525 | return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR; |
356 | } | 526 | } |
357 | 527 | ||
528 | static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx) | ||
529 | { | ||
530 | writel(1, spi_imx->base + MXC_RESET); | ||
531 | } | ||
532 | |||
533 | /* | ||
534 | * These version numbers are taken from the Freescale driver. Unfortunately it | ||
535 | * doesn't support i.MX1, so this entry doesn't match the scheme. :-( | ||
536 | */ | ||
537 | static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = { | ||
538 | #ifdef CONFIG_SPI_IMX_VER_IMX1 | ||
539 | [SPI_IMX_VER_IMX1] = { | ||
540 | .intctrl = mx1_intctrl, | ||
541 | .config = mx1_config, | ||
542 | .trigger = mx1_trigger, | ||
543 | .rx_available = mx1_rx_available, | ||
544 | .reset = mx1_reset, | ||
545 | .fifosize = 8, | ||
546 | }, | ||
547 | #endif | ||
548 | #ifdef CONFIG_SPI_IMX_VER_0_0 | ||
549 | [SPI_IMX_VER_0_0] = { | ||
550 | .intctrl = mx27_intctrl, | ||
551 | .config = mx27_config, | ||
552 | .trigger = mx27_trigger, | ||
553 | .rx_available = mx27_rx_available, | ||
554 | .reset = spi_imx0_0_reset, | ||
555 | .fifosize = 8, | ||
556 | }, | ||
557 | #endif | ||
558 | #ifdef CONFIG_SPI_IMX_VER_0_4 | ||
559 | [SPI_IMX_VER_0_4] = { | ||
560 | .intctrl = mx31_intctrl, | ||
561 | .config = spi_imx0_4_config, | ||
562 | .trigger = mx31_trigger, | ||
563 | .rx_available = mx31_rx_available, | ||
564 | .reset = spi_imx0_4_reset, | ||
565 | .fifosize = 8, | ||
566 | }, | ||
567 | #endif | ||
568 | #ifdef CONFIG_SPI_IMX_VER_0_7 | ||
569 | [SPI_IMX_VER_0_7] = { | ||
570 | .intctrl = mx31_intctrl, | ||
571 | .config = spi_imx0_7_config, | ||
572 | .trigger = mx31_trigger, | ||
573 | .rx_available = mx31_rx_available, | ||
574 | .reset = spi_imx0_4_reset, | ||
575 | .fifosize = 8, | ||
576 | }, | ||
577 | #endif | ||
578 | #ifdef CONFIG_SPI_IMX_VER_2_3 | ||
579 | [SPI_IMX_VER_2_3] = { | ||
580 | .intctrl = spi_imx2_3_intctrl, | ||
581 | .config = spi_imx2_3_config, | ||
582 | .trigger = spi_imx2_3_trigger, | ||
583 | .rx_available = spi_imx2_3_rx_available, | ||
584 | .reset = spi_imx2_3_reset, | ||
585 | .fifosize = 64, | ||
586 | }, | ||
587 | #endif | ||
588 | }; | ||
589 | |||
358 | static void spi_imx_chipselect(struct spi_device *spi, int is_active) | 590 | static void spi_imx_chipselect(struct spi_device *spi, int is_active) |
359 | { | 591 | { |
360 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); | 592 | struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); |
@@ -370,21 +602,21 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active) | |||
370 | 602 | ||
371 | static void spi_imx_push(struct spi_imx_data *spi_imx) | 603 | static void spi_imx_push(struct spi_imx_data *spi_imx) |
372 | { | 604 | { |
373 | while (spi_imx->txfifo < 8) { | 605 | while (spi_imx->txfifo < spi_imx->devtype_data.fifosize) { |
374 | if (!spi_imx->count) | 606 | if (!spi_imx->count) |
375 | break; | 607 | break; |
376 | spi_imx->tx(spi_imx); | 608 | spi_imx->tx(spi_imx); |
377 | spi_imx->txfifo++; | 609 | spi_imx->txfifo++; |
378 | } | 610 | } |
379 | 611 | ||
380 | spi_imx->trigger(spi_imx); | 612 | spi_imx->devtype_data.trigger(spi_imx); |
381 | } | 613 | } |
382 | 614 | ||
383 | static irqreturn_t spi_imx_isr(int irq, void *dev_id) | 615 | static irqreturn_t spi_imx_isr(int irq, void *dev_id) |
384 | { | 616 | { |
385 | struct spi_imx_data *spi_imx = dev_id; | 617 | struct spi_imx_data *spi_imx = dev_id; |
386 | 618 | ||
387 | while (spi_imx->rx_available(spi_imx)) { | 619 | while (spi_imx->devtype_data.rx_available(spi_imx)) { |
388 | spi_imx->rx(spi_imx); | 620 | spi_imx->rx(spi_imx); |
389 | spi_imx->txfifo--; | 621 | spi_imx->txfifo--; |
390 | } | 622 | } |
@@ -398,11 +630,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id) | |||
398 | /* No data left to push, but still waiting for rx data, | 630 | /* No data left to push, but still waiting for rx data, |
399 | * enable receive data available interrupt. | 631 | * enable receive data available interrupt. |
400 | */ | 632 | */ |
401 | spi_imx->intctrl(spi_imx, MXC_INT_RR); | 633 | spi_imx->devtype_data.intctrl( |
634 | spi_imx, MXC_INT_RR); | ||
402 | return IRQ_HANDLED; | 635 | return IRQ_HANDLED; |
403 | } | 636 | } |
404 | 637 | ||
405 | spi_imx->intctrl(spi_imx, 0); | 638 | spi_imx->devtype_data.intctrl(spi_imx, 0); |
406 | complete(&spi_imx->xfer_done); | 639 | complete(&spi_imx->xfer_done); |
407 | 640 | ||
408 | return IRQ_HANDLED; | 641 | return IRQ_HANDLED; |
@@ -417,7 +650,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, | |||
417 | config.bpw = t ? t->bits_per_word : spi->bits_per_word; | 650 | config.bpw = t ? t->bits_per_word : spi->bits_per_word; |
418 | config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; | 651 | config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; |
419 | config.mode = spi->mode; | 652 | config.mode = spi->mode; |
420 | config.cs = spi_imx->chipselect[spi->chip_select]; | 653 | config.cs = spi->chip_select; |
421 | 654 | ||
422 | if (!config.speed_hz) | 655 | if (!config.speed_hz) |
423 | config.speed_hz = spi->max_speed_hz; | 656 | config.speed_hz = spi->max_speed_hz; |
@@ -439,7 +672,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, | |||
439 | } else | 672 | } else |
440 | BUG(); | 673 | BUG(); |
441 | 674 | ||
442 | spi_imx->config(spi_imx, &config); | 675 | spi_imx->devtype_data.config(spi_imx, &config); |
443 | 676 | ||
444 | return 0; | 677 | return 0; |
445 | } | 678 | } |
@@ -458,7 +691,7 @@ static int spi_imx_transfer(struct spi_device *spi, | |||
458 | 691 | ||
459 | spi_imx_push(spi_imx); | 692 | spi_imx_push(spi_imx); |
460 | 693 | ||
461 | spi_imx->intctrl(spi_imx, MXC_INT_TE); | 694 | spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE); |
462 | 695 | ||
463 | wait_for_completion(&spi_imx->xfer_done); | 696 | wait_for_completion(&spi_imx->xfer_done); |
464 | 697 | ||
@@ -485,6 +718,39 @@ static void spi_imx_cleanup(struct spi_device *spi) | |||
485 | { | 718 | { |
486 | } | 719 | } |
487 | 720 | ||
721 | static struct platform_device_id spi_imx_devtype[] = { | ||
722 | { | ||
723 | .name = DRIVER_NAME, | ||
724 | .driver_data = SPI_IMX_VER_AUTODETECT, | ||
725 | }, { | ||
726 | .name = "imx1-cspi", | ||
727 | .driver_data = SPI_IMX_VER_IMX1, | ||
728 | }, { | ||
729 | .name = "imx21-cspi", | ||
730 | .driver_data = SPI_IMX_VER_0_0, | ||
731 | }, { | ||
732 | .name = "imx25-cspi", | ||
733 | .driver_data = SPI_IMX_VER_0_7, | ||
734 | }, { | ||
735 | .name = "imx27-cspi", | ||
736 | .driver_data = SPI_IMX_VER_0_0, | ||
737 | }, { | ||
738 | .name = "imx31-cspi", | ||
739 | .driver_data = SPI_IMX_VER_0_4, | ||
740 | }, { | ||
741 | .name = "imx35-cspi", | ||
742 | .driver_data = SPI_IMX_VER_0_7, | ||
743 | }, { | ||
744 | .name = "imx51-cspi", | ||
745 | .driver_data = SPI_IMX_VER_0_7, | ||
746 | }, { | ||
747 | .name = "imx51-ecspi", | ||
748 | .driver_data = SPI_IMX_VER_2_3, | ||
749 | }, { | ||
750 | /* sentinel */ | ||
751 | } | ||
752 | }; | ||
753 | |||
488 | static int __devinit spi_imx_probe(struct platform_device *pdev) | 754 | static int __devinit spi_imx_probe(struct platform_device *pdev) |
489 | { | 755 | { |
490 | struct spi_imx_master *mxc_platform_info; | 756 | struct spi_imx_master *mxc_platform_info; |
@@ -536,6 +802,31 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
536 | 802 | ||
537 | init_completion(&spi_imx->xfer_done); | 803 | init_completion(&spi_imx->xfer_done); |
538 | 804 | ||
805 | if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) { | ||
806 | if (cpu_is_mx25() || cpu_is_mx35()) | ||
807 | spi_imx->devtype_data = | ||
808 | spi_imx_devtype_data[SPI_IMX_VER_0_7]; | ||
809 | else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) | ||
810 | spi_imx->devtype_data = | ||
811 | spi_imx_devtype_data[SPI_IMX_VER_0_4]; | ||
812 | else if (cpu_is_mx27() || cpu_is_mx21()) | ||
813 | spi_imx->devtype_data = | ||
814 | spi_imx_devtype_data[SPI_IMX_VER_0_0]; | ||
815 | else if (cpu_is_mx1()) | ||
816 | spi_imx->devtype_data = | ||
817 | spi_imx_devtype_data[SPI_IMX_VER_IMX1]; | ||
818 | else | ||
819 | BUG(); | ||
820 | } else | ||
821 | spi_imx->devtype_data = | ||
822 | spi_imx_devtype_data[pdev->id_entry->driver_data]; | ||
823 | |||
824 | if (!spi_imx->devtype_data.intctrl) { | ||
825 | dev_err(&pdev->dev, "no support for this device compiled in\n"); | ||
826 | ret = -ENODEV; | ||
827 | goto out_gpio_free; | ||
828 | } | ||
829 | |||
539 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 830 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
540 | if (!res) { | 831 | if (!res) { |
541 | dev_err(&pdev->dev, "can't get platform resource\n"); | 832 | dev_err(&pdev->dev, "can't get platform resource\n"); |
@@ -567,24 +858,6 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
567 | goto out_iounmap; | 858 | goto out_iounmap; |
568 | } | 859 | } |
569 | 860 | ||
570 | if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) { | ||
571 | spi_imx->intctrl = mx31_intctrl; | ||
572 | spi_imx->config = mx31_config; | ||
573 | spi_imx->trigger = mx31_trigger; | ||
574 | spi_imx->rx_available = mx31_rx_available; | ||
575 | } else if (cpu_is_mx27() || cpu_is_mx21()) { | ||
576 | spi_imx->intctrl = mx27_intctrl; | ||
577 | spi_imx->config = mx27_config; | ||
578 | spi_imx->trigger = mx27_trigger; | ||
579 | spi_imx->rx_available = mx27_rx_available; | ||
580 | } else if (cpu_is_mx1()) { | ||
581 | spi_imx->intctrl = mx1_intctrl; | ||
582 | spi_imx->config = mx1_config; | ||
583 | spi_imx->trigger = mx1_trigger; | ||
584 | spi_imx->rx_available = mx1_rx_available; | ||
585 | } else | ||
586 | BUG(); | ||
587 | |||
588 | spi_imx->clk = clk_get(&pdev->dev, NULL); | 861 | spi_imx->clk = clk_get(&pdev->dev, NULL); |
589 | if (IS_ERR(spi_imx->clk)) { | 862 | if (IS_ERR(spi_imx->clk)) { |
590 | dev_err(&pdev->dev, "unable to get clock\n"); | 863 | dev_err(&pdev->dev, "unable to get clock\n"); |
@@ -595,15 +868,9 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
595 | clk_enable(spi_imx->clk); | 868 | clk_enable(spi_imx->clk); |
596 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk); | 869 | spi_imx->spi_clk = clk_get_rate(spi_imx->clk); |
597 | 870 | ||
598 | if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) | 871 | spi_imx->devtype_data.reset(spi_imx); |
599 | writel(1, spi_imx->base + MXC_RESET); | ||
600 | |||
601 | /* drain receive buffer */ | ||
602 | if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) | ||
603 | while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) | ||
604 | readl(spi_imx->base + MXC_CSPIRXDATA); | ||
605 | 872 | ||
606 | spi_imx->intctrl(spi_imx, 0); | 873 | spi_imx->devtype_data.intctrl(spi_imx, 0); |
607 | 874 | ||
608 | ret = spi_bitbang_start(&spi_imx->bitbang); | 875 | ret = spi_bitbang_start(&spi_imx->bitbang); |
609 | if (ret) { | 876 | if (ret) { |
@@ -668,6 +935,7 @@ static struct platform_driver spi_imx_driver = { | |||
668 | .name = DRIVER_NAME, | 935 | .name = DRIVER_NAME, |
669 | .owner = THIS_MODULE, | 936 | .owner = THIS_MODULE, |
670 | }, | 937 | }, |
938 | .id_table = spi_imx_devtype, | ||
671 | .probe = spi_imx_probe, | 939 | .probe = spi_imx_probe, |
672 | .remove = __devexit_p(spi_imx_remove), | 940 | .remove = __devexit_p(spi_imx_remove), |
673 | }; | 941 | }; |
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index c3038da2648a..795828b90f45 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c | |||
@@ -261,15 +261,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, | |||
261 | chcfg |= S3C64XX_SPI_CH_TXCH_ON; | 261 | chcfg |= S3C64XX_SPI_CH_TXCH_ON; |
262 | if (dma_mode) { | 262 | if (dma_mode) { |
263 | modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; | 263 | modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; |
264 | s3c2410_dma_config(sdd->tx_dmach, 1); | 264 | s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8); |
265 | s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, | 265 | s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, |
266 | xfer->tx_dma, xfer->len); | 266 | xfer->tx_dma, xfer->len); |
267 | s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); | 267 | s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); |
268 | } else { | 268 | } else { |
269 | unsigned char *buf = (unsigned char *) xfer->tx_buf; | 269 | switch (sdd->cur_bpw) { |
270 | int i = 0; | 270 | case 32: |
271 | while (i < xfer->len) | 271 | iowrite32_rep(regs + S3C64XX_SPI_TX_DATA, |
272 | writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA); | 272 | xfer->tx_buf, xfer->len / 4); |
273 | break; | ||
274 | case 16: | ||
275 | iowrite16_rep(regs + S3C64XX_SPI_TX_DATA, | ||
276 | xfer->tx_buf, xfer->len / 2); | ||
277 | break; | ||
278 | default: | ||
279 | iowrite8_rep(regs + S3C64XX_SPI_TX_DATA, | ||
280 | xfer->tx_buf, xfer->len); | ||
281 | break; | ||
282 | } | ||
273 | } | 283 | } |
274 | } | 284 | } |
275 | 285 | ||
@@ -286,7 +296,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, | |||
286 | writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) | 296 | writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) |
287 | | S3C64XX_SPI_PACKET_CNT_EN, | 297 | | S3C64XX_SPI_PACKET_CNT_EN, |
288 | regs + S3C64XX_SPI_PACKET_CNT); | 298 | regs + S3C64XX_SPI_PACKET_CNT); |
289 | s3c2410_dma_config(sdd->rx_dmach, 1); | 299 | s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8); |
290 | s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, | 300 | s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, |
291 | xfer->rx_dma, xfer->len); | 301 | xfer->rx_dma, xfer->len); |
292 | s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); | 302 | s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); |
@@ -366,20 +376,26 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, | |||
366 | return -EIO; | 376 | return -EIO; |
367 | } | 377 | } |
368 | } else { | 378 | } else { |
369 | unsigned char *buf; | ||
370 | int i; | ||
371 | |||
372 | /* If it was only Tx */ | 379 | /* If it was only Tx */ |
373 | if (xfer->rx_buf == NULL) { | 380 | if (xfer->rx_buf == NULL) { |
374 | sdd->state &= ~TXBUSY; | 381 | sdd->state &= ~TXBUSY; |
375 | return 0; | 382 | return 0; |
376 | } | 383 | } |
377 | 384 | ||
378 | i = 0; | 385 | switch (sdd->cur_bpw) { |
379 | buf = xfer->rx_buf; | 386 | case 32: |
380 | while (i < xfer->len) | 387 | ioread32_rep(regs + S3C64XX_SPI_RX_DATA, |
381 | buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); | 388 | xfer->rx_buf, xfer->len / 4); |
382 | 389 | break; | |
390 | case 16: | ||
391 | ioread16_rep(regs + S3C64XX_SPI_RX_DATA, | ||
392 | xfer->rx_buf, xfer->len / 2); | ||
393 | break; | ||
394 | default: | ||
395 | ioread8_rep(regs + S3C64XX_SPI_RX_DATA, | ||
396 | xfer->rx_buf, xfer->len); | ||
397 | break; | ||
398 | } | ||
383 | sdd->state &= ~RXBUSY; | 399 | sdd->state &= ~RXBUSY; |
384 | } | 400 | } |
385 | 401 | ||
@@ -399,13 +415,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, | |||
399 | 415 | ||
400 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | 416 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) |
401 | { | 417 | { |
418 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; | ||
402 | void __iomem *regs = sdd->regs; | 419 | void __iomem *regs = sdd->regs; |
403 | u32 val; | 420 | u32 val; |
404 | 421 | ||
405 | /* Disable Clock */ | 422 | /* Disable Clock */ |
406 | val = readl(regs + S3C64XX_SPI_CLK_CFG); | 423 | if (sci->clk_from_cmu) { |
407 | val &= ~S3C64XX_SPI_ENCLK_ENABLE; | 424 | clk_disable(sdd->src_clk); |
408 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | 425 | } else { |
426 | val = readl(regs + S3C64XX_SPI_CLK_CFG); | ||
427 | val &= ~S3C64XX_SPI_ENCLK_ENABLE; | ||
428 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | ||
429 | } | ||
409 | 430 | ||
410 | /* Set Polarity and Phase */ | 431 | /* Set Polarity and Phase */ |
411 | val = readl(regs + S3C64XX_SPI_CH_CFG); | 432 | val = readl(regs + S3C64XX_SPI_CH_CFG); |
@@ -429,29 +450,39 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | |||
429 | switch (sdd->cur_bpw) { | 450 | switch (sdd->cur_bpw) { |
430 | case 32: | 451 | case 32: |
431 | val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; | 452 | val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD; |
453 | val |= S3C64XX_SPI_MODE_CH_TSZ_WORD; | ||
432 | break; | 454 | break; |
433 | case 16: | 455 | case 16: |
434 | val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; | 456 | val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD; |
457 | val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD; | ||
435 | break; | 458 | break; |
436 | default: | 459 | default: |
437 | val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; | 460 | val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE; |
461 | val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; | ||
438 | break; | 462 | break; |
439 | } | 463 | } |
440 | val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */ | ||
441 | 464 | ||
442 | writel(val, regs + S3C64XX_SPI_MODE_CFG); | 465 | writel(val, regs + S3C64XX_SPI_MODE_CFG); |
443 | 466 | ||
444 | /* Configure Clock */ | 467 | if (sci->clk_from_cmu) { |
445 | val = readl(regs + S3C64XX_SPI_CLK_CFG); | 468 | /* Configure Clock */ |
446 | val &= ~S3C64XX_SPI_PSR_MASK; | 469 | /* There is half-multiplier before the SPI */ |
447 | val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1) | 470 | clk_set_rate(sdd->src_clk, sdd->cur_speed * 2); |
448 | & S3C64XX_SPI_PSR_MASK); | 471 | /* Enable Clock */ |
449 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | 472 | clk_enable(sdd->src_clk); |
450 | 473 | } else { | |
451 | /* Enable Clock */ | 474 | /* Configure Clock */ |
452 | val = readl(regs + S3C64XX_SPI_CLK_CFG); | 475 | val = readl(regs + S3C64XX_SPI_CLK_CFG); |
453 | val |= S3C64XX_SPI_ENCLK_ENABLE; | 476 | val &= ~S3C64XX_SPI_PSR_MASK; |
454 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | 477 | val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1) |
478 | & S3C64XX_SPI_PSR_MASK); | ||
479 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | ||
480 | |||
481 | /* Enable Clock */ | ||
482 | val = readl(regs + S3C64XX_SPI_CLK_CFG); | ||
483 | val |= S3C64XX_SPI_ENCLK_ENABLE; | ||
484 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | ||
485 | } | ||
455 | } | 486 | } |
456 | 487 | ||
457 | static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, | 488 | static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, |
@@ -499,6 +530,7 @@ static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, | |||
499 | static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, | 530 | static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, |
500 | struct spi_message *msg) | 531 | struct spi_message *msg) |
501 | { | 532 | { |
533 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; | ||
502 | struct device *dev = &sdd->pdev->dev; | 534 | struct device *dev = &sdd->pdev->dev; |
503 | struct spi_transfer *xfer; | 535 | struct spi_transfer *xfer; |
504 | 536 | ||
@@ -514,6 +546,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
514 | /* Map until end or first fail */ | 546 | /* Map until end or first fail */ |
515 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 547 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
516 | 548 | ||
549 | if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) | ||
550 | continue; | ||
551 | |||
517 | if (xfer->tx_buf != NULL) { | 552 | if (xfer->tx_buf != NULL) { |
518 | xfer->tx_dma = dma_map_single(dev, | 553 | xfer->tx_dma = dma_map_single(dev, |
519 | (void *)xfer->tx_buf, xfer->len, | 554 | (void *)xfer->tx_buf, xfer->len, |
@@ -545,6 +580,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
545 | static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, | 580 | static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, |
546 | struct spi_message *msg) | 581 | struct spi_message *msg) |
547 | { | 582 | { |
583 | struct s3c64xx_spi_info *sci = sdd->cntrlr_info; | ||
548 | struct device *dev = &sdd->pdev->dev; | 584 | struct device *dev = &sdd->pdev->dev; |
549 | struct spi_transfer *xfer; | 585 | struct spi_transfer *xfer; |
550 | 586 | ||
@@ -553,6 +589,9 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
553 | 589 | ||
554 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 590 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
555 | 591 | ||
592 | if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) | ||
593 | continue; | ||
594 | |||
556 | if (xfer->rx_buf != NULL | 595 | if (xfer->rx_buf != NULL |
557 | && xfer->rx_dma != XFER_DMAADDR_INVALID) | 596 | && xfer->rx_dma != XFER_DMAADDR_INVALID) |
558 | dma_unmap_single(dev, xfer->rx_dma, | 597 | dma_unmap_single(dev, xfer->rx_dma, |
@@ -608,6 +647,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd, | |||
608 | bpw = xfer->bits_per_word ? : spi->bits_per_word; | 647 | bpw = xfer->bits_per_word ? : spi->bits_per_word; |
609 | speed = xfer->speed_hz ? : spi->max_speed_hz; | 648 | speed = xfer->speed_hz ? : spi->max_speed_hz; |
610 | 649 | ||
650 | if (xfer->len % (bpw / 8)) { | ||
651 | dev_err(&spi->dev, | ||
652 | "Xfer length(%u) not a multiple of word size(%u)\n", | ||
653 | xfer->len, bpw / 8); | ||
654 | status = -EIO; | ||
655 | goto out; | ||
656 | } | ||
657 | |||
611 | if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { | 658 | if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { |
612 | sdd->cur_bpw = bpw; | 659 | sdd->cur_bpw = bpw; |
613 | sdd->cur_speed = speed; | 660 | sdd->cur_speed = speed; |
@@ -798,7 +845,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
798 | struct s3c64xx_spi_driver_data *sdd; | 845 | struct s3c64xx_spi_driver_data *sdd; |
799 | struct s3c64xx_spi_info *sci; | 846 | struct s3c64xx_spi_info *sci; |
800 | struct spi_message *msg; | 847 | struct spi_message *msg; |
801 | u32 psr, speed; | ||
802 | unsigned long flags; | 848 | unsigned long flags; |
803 | int err = 0; | 849 | int err = 0; |
804 | 850 | ||
@@ -841,32 +887,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
841 | } | 887 | } |
842 | 888 | ||
843 | /* Check if we can provide the requested rate */ | 889 | /* Check if we can provide the requested rate */ |
844 | speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */ | 890 | if (!sci->clk_from_cmu) { |
845 | 891 | u32 psr, speed; | |
846 | if (spi->max_speed_hz > speed) | 892 | |
847 | spi->max_speed_hz = speed; | 893 | /* Max possible */ |
848 | 894 | speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); | |
849 | psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1; | 895 | |
850 | psr &= S3C64XX_SPI_PSR_MASK; | 896 | if (spi->max_speed_hz > speed) |
851 | if (psr == S3C64XX_SPI_PSR_MASK) | 897 | spi->max_speed_hz = speed; |
852 | psr--; | 898 | |
899 | psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1; | ||
900 | psr &= S3C64XX_SPI_PSR_MASK; | ||
901 | if (psr == S3C64XX_SPI_PSR_MASK) | ||
902 | psr--; | ||
903 | |||
904 | speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); | ||
905 | if (spi->max_speed_hz < speed) { | ||
906 | if (psr+1 < S3C64XX_SPI_PSR_MASK) { | ||
907 | psr++; | ||
908 | } else { | ||
909 | err = -EINVAL; | ||
910 | goto setup_exit; | ||
911 | } | ||
912 | } | ||
853 | 913 | ||
854 | speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); | 914 | speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); |
855 | if (spi->max_speed_hz < speed) { | 915 | if (spi->max_speed_hz >= speed) |
856 | if (psr+1 < S3C64XX_SPI_PSR_MASK) { | 916 | spi->max_speed_hz = speed; |
857 | psr++; | 917 | else |
858 | } else { | ||
859 | err = -EINVAL; | 918 | err = -EINVAL; |
860 | goto setup_exit; | ||
861 | } | ||
862 | } | 919 | } |
863 | 920 | ||
864 | speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); | ||
865 | if (spi->max_speed_hz >= speed) | ||
866 | spi->max_speed_hz = speed; | ||
867 | else | ||
868 | err = -EINVAL; | ||
869 | |||
870 | setup_exit: | 921 | setup_exit: |
871 | 922 | ||
872 | /* setup() returns with device de-selected */ | 923 | /* setup() returns with device de-selected */ |
@@ -888,7 +939,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) | |||
888 | /* Disable Interrupts - we use Polling if not DMA mode */ | 939 | /* Disable Interrupts - we use Polling if not DMA mode */ |
889 | writel(0, regs + S3C64XX_SPI_INT_EN); | 940 | writel(0, regs + S3C64XX_SPI_INT_EN); |
890 | 941 | ||
891 | writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT, | 942 | if (!sci->clk_from_cmu) |
943 | writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT, | ||
892 | regs + S3C64XX_SPI_CLK_CFG); | 944 | regs + S3C64XX_SPI_CLK_CFG); |
893 | writel(0, regs + S3C64XX_SPI_MODE_CFG); | 945 | writel(0, regs + S3C64XX_SPI_MODE_CFG); |
894 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); | 946 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); |
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi_topcliff_pch.c new file mode 100644 index 000000000000..58e187f45ec7 --- /dev/null +++ b/drivers/spi/spi_topcliff_pch.c | |||
@@ -0,0 +1,1303 @@ | |||
1 | /* | ||
2 | * SPI bus driver for the Topcliff PCH used by Intel SoCs | ||
3 | * | ||
4 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/spi/spidev.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/device.h> | ||
29 | |||
30 | /* Register offsets */ | ||
31 | #define PCH_SPCR 0x00 /* SPI control register */ | ||
32 | #define PCH_SPBRR 0x04 /* SPI baud rate register */ | ||
33 | #define PCH_SPSR 0x08 /* SPI status register */ | ||
34 | #define PCH_SPDWR 0x0C /* SPI write data register */ | ||
35 | #define PCH_SPDRR 0x10 /* SPI read data register */ | ||
36 | #define PCH_SSNXCR 0x18 /* SSN Expand Control Register */ | ||
37 | #define PCH_SRST 0x1C /* SPI reset register */ | ||
38 | |||
39 | #define PCH_SPSR_TFD 0x000007C0 | ||
40 | #define PCH_SPSR_RFD 0x0000F800 | ||
41 | |||
42 | #define PCH_READABLE(x) (((x) & PCH_SPSR_RFD)>>11) | ||
43 | #define PCH_WRITABLE(x) (((x) & PCH_SPSR_TFD)>>6) | ||
44 | |||
45 | #define PCH_RX_THOLD 7 | ||
46 | #define PCH_RX_THOLD_MAX 15 | ||
47 | |||
48 | #define PCH_MAX_BAUDRATE 5000000 | ||
49 | #define PCH_MAX_FIFO_DEPTH 16 | ||
50 | |||
51 | #define STATUS_RUNNING 1 | ||
52 | #define STATUS_EXITING 2 | ||
53 | #define PCH_SLEEP_TIME 10 | ||
54 | |||
55 | #define PCH_ADDRESS_SIZE 0x20 | ||
56 | |||
57 | #define SSN_LOW 0x02U | ||
58 | #define SSN_NO_CONTROL 0x00U | ||
59 | #define PCH_MAX_CS 0xFF | ||
60 | #define PCI_DEVICE_ID_GE_SPI 0x8816 | ||
61 | |||
62 | #define SPCR_SPE_BIT (1 << 0) | ||
63 | #define SPCR_MSTR_BIT (1 << 1) | ||
64 | #define SPCR_LSBF_BIT (1 << 4) | ||
65 | #define SPCR_CPHA_BIT (1 << 5) | ||
66 | #define SPCR_CPOL_BIT (1 << 6) | ||
67 | #define SPCR_TFIE_BIT (1 << 8) | ||
68 | #define SPCR_RFIE_BIT (1 << 9) | ||
69 | #define SPCR_FIE_BIT (1 << 10) | ||
70 | #define SPCR_ORIE_BIT (1 << 11) | ||
71 | #define SPCR_MDFIE_BIT (1 << 12) | ||
72 | #define SPCR_FICLR_BIT (1 << 24) | ||
73 | #define SPSR_TFI_BIT (1 << 0) | ||
74 | #define SPSR_RFI_BIT (1 << 1) | ||
75 | #define SPSR_FI_BIT (1 << 2) | ||
76 | #define SPBRR_SIZE_BIT (1 << 10) | ||
77 | |||
78 | #define PCH_ALL (SPCR_TFIE_BIT|SPCR_RFIE_BIT|SPCR_FIE_BIT|SPCR_ORIE_BIT|SPCR_MDFIE_BIT) | ||
79 | |||
80 | #define SPCR_RFIC_FIELD 20 | ||
81 | #define SPCR_TFIC_FIELD 16 | ||
82 | |||
83 | #define SPSR_INT_BITS 0x1F | ||
84 | #define MASK_SPBRR_SPBR_BITS (~((1 << 10) - 1)) | ||
85 | #define MASK_RFIC_SPCR_BITS (~(0xf << 20)) | ||
86 | #define MASK_TFIC_SPCR_BITS (~(0xf000f << 12)) | ||
87 | |||
88 | #define PCH_CLOCK_HZ 50000000 | ||
89 | #define PCH_MAX_SPBR 1023 | ||
90 | |||
91 | |||
92 | /** | ||
93 | * struct pch_spi_data - Holds the SPI channel specific details | ||
94 | * @io_remap_addr: The remapped PCI base address | ||
95 | * @master: Pointer to the SPI master structure | ||
96 | * @work: Reference to work queue handler | ||
97 | * @wk: Workqueue for carrying out execution of the | ||
98 | * requests | ||
99 | * @wait: Wait queue for waking up upon receiving an | ||
100 | * interrupt. | ||
101 | * @transfer_complete: Status of SPI Transfer | ||
102 | * @bcurrent_msg_processing: Status flag for message processing | ||
103 | * @lock: Lock for protecting this structure | ||
104 | * @queue: SPI Message queue | ||
105 | * @status: Status of the SPI driver | ||
106 | * @bpw_len: Length of data to be transferred in bits per | ||
107 | * word | ||
108 | * @transfer_active: Flag showing active transfer | ||
109 | * @tx_index: Transmit data count; for bookkeeping during | ||
110 | * transfer | ||
111 | * @rx_index: Receive data count; for bookkeeping during | ||
112 | * transfer | ||
113 | * @tx_buff: Buffer for data to be transmitted | ||
114 | * @rx_index: Buffer for Received data | ||
115 | * @n_curnt_chip: The chip number that this SPI driver currently | ||
116 | * operates on | ||
117 | * @current_chip: Reference to the current chip that this SPI | ||
118 | * driver currently operates on | ||
119 | * @current_msg: The current message that this SPI driver is | ||
120 | * handling | ||
121 | * @cur_trans: The current transfer that this SPI driver is | ||
122 | * handling | ||
123 | * @board_dat: Reference to the SPI device data structure | ||
124 | */ | ||
125 | struct pch_spi_data { | ||
126 | void __iomem *io_remap_addr; | ||
127 | struct spi_master *master; | ||
128 | struct work_struct work; | ||
129 | struct workqueue_struct *wk; | ||
130 | wait_queue_head_t wait; | ||
131 | u8 transfer_complete; | ||
132 | u8 bcurrent_msg_processing; | ||
133 | spinlock_t lock; | ||
134 | struct list_head queue; | ||
135 | u8 status; | ||
136 | u32 bpw_len; | ||
137 | u8 transfer_active; | ||
138 | u32 tx_index; | ||
139 | u32 rx_index; | ||
140 | u16 *pkt_tx_buff; | ||
141 | u16 *pkt_rx_buff; | ||
142 | u8 n_curnt_chip; | ||
143 | struct spi_device *current_chip; | ||
144 | struct spi_message *current_msg; | ||
145 | struct spi_transfer *cur_trans; | ||
146 | struct pch_spi_board_data *board_dat; | ||
147 | }; | ||
148 | |||
149 | /** | ||
150 | * struct pch_spi_board_data - Holds the SPI device specific details | ||
151 | * @pdev: Pointer to the PCI device | ||
152 | * @irq_reg_sts: Status of IRQ registration | ||
153 | * @pci_req_sts: Status of pci_request_regions | ||
154 | * @suspend_sts: Status of suspend | ||
155 | * @data: Pointer to SPI channel data structure | ||
156 | */ | ||
157 | struct pch_spi_board_data { | ||
158 | struct pci_dev *pdev; | ||
159 | u8 irq_reg_sts; | ||
160 | u8 pci_req_sts; | ||
161 | u8 suspend_sts; | ||
162 | struct pch_spi_data *data; | ||
163 | }; | ||
164 | |||
165 | static struct pci_device_id pch_spi_pcidev_id[] = { | ||
166 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_SPI)}, | ||
167 | {0,} | ||
168 | }; | ||
169 | |||
170 | /** | ||
171 | * pch_spi_writereg() - Performs register writes | ||
172 | * @master: Pointer to struct spi_master. | ||
173 | * @idx: Register offset. | ||
174 | * @val: Value to be written to register. | ||
175 | */ | ||
176 | static inline void pch_spi_writereg(struct spi_master *master, int idx, u32 val) | ||
177 | { | ||
178 | struct pch_spi_data *data = spi_master_get_devdata(master); | ||
179 | iowrite32(val, (data->io_remap_addr + idx)); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * pch_spi_readreg() - Performs register reads | ||
184 | * @master: Pointer to struct spi_master. | ||
185 | * @idx: Register offset. | ||
186 | */ | ||
187 | static inline u32 pch_spi_readreg(struct spi_master *master, int idx) | ||
188 | { | ||
189 | struct pch_spi_data *data = spi_master_get_devdata(master); | ||
190 | return ioread32(data->io_remap_addr + idx); | ||
191 | } | ||
192 | |||
193 | static inline void pch_spi_setclr_reg(struct spi_master *master, int idx, | ||
194 | u32 set, u32 clr) | ||
195 | { | ||
196 | u32 tmp = pch_spi_readreg(master, idx); | ||
197 | tmp = (tmp & ~clr) | set; | ||
198 | pch_spi_writereg(master, idx, tmp); | ||
199 | } | ||
200 | |||
201 | static void pch_spi_set_master_mode(struct spi_master *master) | ||
202 | { | ||
203 | pch_spi_setclr_reg(master, PCH_SPCR, SPCR_MSTR_BIT, 0); | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * pch_spi_clear_fifo() - Clears the Transmit and Receive FIFOs | ||
208 | * @master: Pointer to struct spi_master. | ||
209 | */ | ||
210 | static void pch_spi_clear_fifo(struct spi_master *master) | ||
211 | { | ||
212 | pch_spi_setclr_reg(master, PCH_SPCR, SPCR_FICLR_BIT, 0); | ||
213 | pch_spi_setclr_reg(master, PCH_SPCR, 0, SPCR_FICLR_BIT); | ||
214 | } | ||
215 | |||
216 | static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val, | ||
217 | void __iomem *io_remap_addr) | ||
218 | { | ||
219 | u32 n_read, tx_index, rx_index, bpw_len; | ||
220 | u16 *pkt_rx_buffer, *pkt_tx_buff; | ||
221 | int read_cnt; | ||
222 | u32 reg_spcr_val; | ||
223 | void __iomem *spsr; | ||
224 | void __iomem *spdrr; | ||
225 | void __iomem *spdwr; | ||
226 | |||
227 | spsr = io_remap_addr + PCH_SPSR; | ||
228 | iowrite32(reg_spsr_val, spsr); | ||
229 | |||
230 | if (data->transfer_active) { | ||
231 | rx_index = data->rx_index; | ||
232 | tx_index = data->tx_index; | ||
233 | bpw_len = data->bpw_len; | ||
234 | pkt_rx_buffer = data->pkt_rx_buff; | ||
235 | pkt_tx_buff = data->pkt_tx_buff; | ||
236 | |||
237 | spdrr = io_remap_addr + PCH_SPDRR; | ||
238 | spdwr = io_remap_addr + PCH_SPDWR; | ||
239 | |||
240 | n_read = PCH_READABLE(reg_spsr_val); | ||
241 | |||
242 | for (read_cnt = 0; (read_cnt < n_read); read_cnt++) { | ||
243 | pkt_rx_buffer[rx_index++] = ioread32(spdrr); | ||
244 | if (tx_index < bpw_len) | ||
245 | iowrite32(pkt_tx_buff[tx_index++], spdwr); | ||
246 | } | ||
247 | |||
248 | /* disable RFI if not needed */ | ||
249 | if ((bpw_len - rx_index) <= PCH_MAX_FIFO_DEPTH) { | ||
250 | reg_spcr_val = ioread32(io_remap_addr + PCH_SPCR); | ||
251 | reg_spcr_val &= ~SPCR_RFIE_BIT; /* disable RFI */ | ||
252 | |||
253 | /* reset rx threshold */ | ||
254 | reg_spcr_val &= MASK_RFIC_SPCR_BITS; | ||
255 | reg_spcr_val |= (PCH_RX_THOLD_MAX << SPCR_RFIC_FIELD); | ||
256 | iowrite32(((reg_spcr_val) &= (~(SPCR_RFIE_BIT))), | ||
257 | (io_remap_addr + PCH_SPCR)); | ||
258 | } | ||
259 | |||
260 | /* update counts */ | ||
261 | data->tx_index = tx_index; | ||
262 | data->rx_index = rx_index; | ||
263 | |||
264 | } | ||
265 | |||
266 | /* if transfer complete interrupt */ | ||
267 | if (reg_spsr_val & SPSR_FI_BIT) { | ||
268 | /* disable FI & RFI interrupts */ | ||
269 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, | ||
270 | SPCR_FIE_BIT | SPCR_TFIE_BIT); | ||
271 | |||
272 | /* transfer is completed;inform pch_spi_process_messages */ | ||
273 | data->transfer_complete = true; | ||
274 | wake_up(&data->wait); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * pch_spi_handler() - Interrupt handler | ||
280 | * @irq: The interrupt number. | ||
281 | * @dev_id: Pointer to struct pch_spi_board_data. | ||
282 | */ | ||
283 | static irqreturn_t pch_spi_handler(int irq, void *dev_id) | ||
284 | { | ||
285 | u32 reg_spsr_val; | ||
286 | struct pch_spi_data *data; | ||
287 | void __iomem *spsr; | ||
288 | void __iomem *io_remap_addr; | ||
289 | irqreturn_t ret = IRQ_NONE; | ||
290 | struct pch_spi_board_data *board_dat = dev_id; | ||
291 | |||
292 | if (board_dat->suspend_sts) { | ||
293 | dev_dbg(&board_dat->pdev->dev, | ||
294 | "%s returning due to suspend\n", __func__); | ||
295 | return IRQ_NONE; | ||
296 | } | ||
297 | |||
298 | data = board_dat->data; | ||
299 | io_remap_addr = data->io_remap_addr; | ||
300 | spsr = io_remap_addr + PCH_SPSR; | ||
301 | |||
302 | reg_spsr_val = ioread32(spsr); | ||
303 | |||
304 | /* Check if the interrupt is for SPI device */ | ||
305 | if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { | ||
306 | pch_spi_handler_sub(data, reg_spsr_val, io_remap_addr); | ||
307 | ret = IRQ_HANDLED; | ||
308 | } | ||
309 | |||
310 | dev_dbg(&board_dat->pdev->dev, "%s EXIT return value=%d\n", | ||
311 | __func__, ret); | ||
312 | |||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * pch_spi_set_baud_rate() - Sets SPBR field in SPBRR | ||
318 | * @master: Pointer to struct spi_master. | ||
319 | * @speed_hz: Baud rate. | ||
320 | */ | ||
321 | static void pch_spi_set_baud_rate(struct spi_master *master, u32 speed_hz) | ||
322 | { | ||
323 | u32 n_spbr = PCH_CLOCK_HZ / (speed_hz * 2); | ||
324 | |||
325 | /* if baud rate is less than we can support limit it */ | ||
326 | if (n_spbr > PCH_MAX_SPBR) | ||
327 | n_spbr = PCH_MAX_SPBR; | ||
328 | |||
329 | pch_spi_setclr_reg(master, PCH_SPBRR, n_spbr, ~MASK_SPBRR_SPBR_BITS); | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * pch_spi_set_bits_per_word() - Sets SIZE field in SPBRR | ||
334 | * @master: Pointer to struct spi_master. | ||
335 | * @bits_per_word: Bits per word for SPI transfer. | ||
336 | */ | ||
337 | static void pch_spi_set_bits_per_word(struct spi_master *master, | ||
338 | u8 bits_per_word) | ||
339 | { | ||
340 | if (bits_per_word == 8) | ||
341 | pch_spi_setclr_reg(master, PCH_SPBRR, 0, SPBRR_SIZE_BIT); | ||
342 | else | ||
343 | pch_spi_setclr_reg(master, PCH_SPBRR, SPBRR_SIZE_BIT, 0); | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * pch_spi_setup_transfer() - Configures the PCH SPI hardware for transfer | ||
348 | * @spi: Pointer to struct spi_device. | ||
349 | */ | ||
350 | static void pch_spi_setup_transfer(struct spi_device *spi) | ||
351 | { | ||
352 | u32 flags = 0; | ||
353 | |||
354 | dev_dbg(&spi->dev, "%s SPBRR content =%x setting baud rate=%d\n", | ||
355 | __func__, pch_spi_readreg(spi->master, PCH_SPBRR), | ||
356 | spi->max_speed_hz); | ||
357 | pch_spi_set_baud_rate(spi->master, spi->max_speed_hz); | ||
358 | |||
359 | /* set bits per word */ | ||
360 | pch_spi_set_bits_per_word(spi->master, spi->bits_per_word); | ||
361 | |||
362 | if (!(spi->mode & SPI_LSB_FIRST)) | ||
363 | flags |= SPCR_LSBF_BIT; | ||
364 | if (spi->mode & SPI_CPOL) | ||
365 | flags |= SPCR_CPOL_BIT; | ||
366 | if (spi->mode & SPI_CPHA) | ||
367 | flags |= SPCR_CPHA_BIT; | ||
368 | pch_spi_setclr_reg(spi->master, PCH_SPCR, flags, | ||
369 | (SPCR_LSBF_BIT | SPCR_CPOL_BIT | SPCR_CPHA_BIT)); | ||
370 | |||
371 | /* Clear the FIFO by toggling FICLR to 1 and back to 0 */ | ||
372 | pch_spi_clear_fifo(spi->master); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * pch_spi_reset() - Clears SPI registers | ||
377 | * @master: Pointer to struct spi_master. | ||
378 | */ | ||
379 | static void pch_spi_reset(struct spi_master *master) | ||
380 | { | ||
381 | /* write 1 to reset SPI */ | ||
382 | pch_spi_writereg(master, PCH_SRST, 0x1); | ||
383 | |||
384 | /* clear reset */ | ||
385 | pch_spi_writereg(master, PCH_SRST, 0x0); | ||
386 | } | ||
387 | |||
388 | static int pch_spi_setup(struct spi_device *pspi) | ||
389 | { | ||
390 | /* check bits per word */ | ||
391 | if (pspi->bits_per_word == 0) { | ||
392 | pspi->bits_per_word = 8; | ||
393 | dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__); | ||
394 | } | ||
395 | |||
396 | if ((pspi->bits_per_word != 8) && (pspi->bits_per_word != 16)) { | ||
397 | dev_err(&pspi->dev, "%s Invalid bits per word\n", __func__); | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | |||
401 | /* Check baud rate setting */ | ||
402 | /* if baud rate of chip is greater than | ||
403 | max we can support,return error */ | ||
404 | if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE) | ||
405 | pspi->max_speed_hz = PCH_MAX_BAUDRATE; | ||
406 | |||
407 | dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__, | ||
408 | (pspi->mode) & (SPI_CPOL | SPI_CPHA)); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg) | ||
414 | { | ||
415 | |||
416 | struct spi_transfer *transfer; | ||
417 | struct pch_spi_data *data = spi_master_get_devdata(pspi->master); | ||
418 | int retval; | ||
419 | unsigned long flags; | ||
420 | |||
421 | /* validate spi message and baud rate */ | ||
422 | if (unlikely(list_empty(&pmsg->transfers) == 1)) { | ||
423 | dev_err(&pspi->dev, "%s list empty\n", __func__); | ||
424 | retval = -EINVAL; | ||
425 | goto err_out; | ||
426 | } | ||
427 | |||
428 | if (unlikely(pspi->max_speed_hz == 0)) { | ||
429 | dev_err(&pspi->dev, "%s pch_spi_tranfer maxspeed=%d\n", | ||
430 | __func__, pspi->max_speed_hz); | ||
431 | retval = -EINVAL; | ||
432 | goto err_out; | ||
433 | } | ||
434 | |||
435 | dev_dbg(&pspi->dev, "%s Transfer List not empty. " | ||
436 | "Transfer Speed is set.\n", __func__); | ||
437 | |||
438 | /* validate Tx/Rx buffers and Transfer length */ | ||
439 | list_for_each_entry(transfer, &pmsg->transfers, transfer_list) { | ||
440 | if (!transfer->tx_buf && !transfer->rx_buf) { | ||
441 | dev_err(&pspi->dev, | ||
442 | "%s Tx and Rx buffer NULL\n", __func__); | ||
443 | retval = -EINVAL; | ||
444 | goto err_out; | ||
445 | } | ||
446 | |||
447 | if (!transfer->len) { | ||
448 | dev_err(&pspi->dev, "%s Transfer length invalid\n", | ||
449 | __func__); | ||
450 | retval = -EINVAL; | ||
451 | goto err_out; | ||
452 | } | ||
453 | |||
454 | dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length" | ||
455 | " valid\n", __func__); | ||
456 | |||
457 | /* if baud rate hs been specified validate the same */ | ||
458 | if (transfer->speed_hz > PCH_MAX_BAUDRATE) | ||
459 | transfer->speed_hz = PCH_MAX_BAUDRATE; | ||
460 | |||
461 | /* if bits per word has been specified validate the same */ | ||
462 | if (transfer->bits_per_word) { | ||
463 | if ((transfer->bits_per_word != 8) | ||
464 | && (transfer->bits_per_word != 16)) { | ||
465 | retval = -EINVAL; | ||
466 | dev_err(&pspi->dev, | ||
467 | "%s Invalid bits per word\n", __func__); | ||
468 | goto err_out; | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | |||
473 | spin_lock_irqsave(&data->lock, flags); | ||
474 | |||
475 | /* We won't process any messages if we have been asked to terminate */ | ||
476 | if (data->status == STATUS_EXITING) { | ||
477 | dev_err(&pspi->dev, "%s status = STATUS_EXITING.\n", __func__); | ||
478 | retval = -ESHUTDOWN; | ||
479 | goto err_return_spinlock; | ||
480 | } | ||
481 | |||
482 | /* If suspended ,return -EINVAL */ | ||
483 | if (data->board_dat->suspend_sts) { | ||
484 | dev_err(&pspi->dev, "%s suspend; returning EINVAL\n", __func__); | ||
485 | retval = -EINVAL; | ||
486 | goto err_return_spinlock; | ||
487 | } | ||
488 | |||
489 | /* set status of message */ | ||
490 | pmsg->actual_length = 0; | ||
491 | dev_dbg(&pspi->dev, "%s - pmsg->status =%d\n", __func__, pmsg->status); | ||
492 | |||
493 | pmsg->status = -EINPROGRESS; | ||
494 | |||
495 | /* add message to queue */ | ||
496 | list_add_tail(&pmsg->queue, &data->queue); | ||
497 | dev_dbg(&pspi->dev, "%s - Invoked list_add_tail\n", __func__); | ||
498 | |||
499 | /* schedule work queue to run */ | ||
500 | queue_work(data->wk, &data->work); | ||
501 | dev_dbg(&pspi->dev, "%s - Invoked queue work\n", __func__); | ||
502 | |||
503 | retval = 0; | ||
504 | |||
505 | err_return_spinlock: | ||
506 | spin_unlock_irqrestore(&data->lock, flags); | ||
507 | err_out: | ||
508 | dev_dbg(&pspi->dev, "%s RETURN=%d\n", __func__, retval); | ||
509 | return retval; | ||
510 | } | ||
511 | |||
512 | static inline void pch_spi_select_chip(struct pch_spi_data *data, | ||
513 | struct spi_device *pspi) | ||
514 | { | ||
515 | if (data->current_chip != NULL) { | ||
516 | if (pspi->chip_select != data->n_curnt_chip) { | ||
517 | dev_dbg(&pspi->dev, "%s : different slave\n", __func__); | ||
518 | data->current_chip = NULL; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | data->current_chip = pspi; | ||
523 | |||
524 | data->n_curnt_chip = data->current_chip->chip_select; | ||
525 | |||
526 | dev_dbg(&pspi->dev, "%s :Invoking pch_spi_setup_transfer\n", __func__); | ||
527 | pch_spi_setup_transfer(pspi); | ||
528 | } | ||
529 | |||
530 | static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw, | ||
531 | struct spi_message **ppmsg) | ||
532 | { | ||
533 | int size; | ||
534 | u32 n_writes; | ||
535 | int j; | ||
536 | struct spi_message *pmsg; | ||
537 | const u8 *tx_buf; | ||
538 | const u16 *tx_sbuf; | ||
539 | |||
540 | pmsg = *ppmsg; | ||
541 | |||
542 | /* set baud rate if needed */ | ||
543 | if (data->cur_trans->speed_hz) { | ||
544 | dev_dbg(&data->master->dev, "%s:setting baud rate\n", __func__); | ||
545 | pch_spi_set_baud_rate(data->master, data->cur_trans->speed_hz); | ||
546 | } | ||
547 | |||
548 | /* set bits per word if needed */ | ||
549 | if (data->cur_trans->bits_per_word && | ||
550 | (data->current_msg->spi->bits_per_word != data->cur_trans->bits_per_word)) { | ||
551 | dev_dbg(&data->master->dev, "%s:set bits per word\n", __func__); | ||
552 | pch_spi_set_bits_per_word(data->master, | ||
553 | data->cur_trans->bits_per_word); | ||
554 | *bpw = data->cur_trans->bits_per_word; | ||
555 | } else { | ||
556 | *bpw = data->current_msg->spi->bits_per_word; | ||
557 | } | ||
558 | |||
559 | /* reset Tx/Rx index */ | ||
560 | data->tx_index = 0; | ||
561 | data->rx_index = 0; | ||
562 | |||
563 | data->bpw_len = data->cur_trans->len / (*bpw / 8); | ||
564 | |||
565 | /* find alloc size */ | ||
566 | size = data->cur_trans->len * sizeof(*data->pkt_tx_buff); | ||
567 | |||
568 | /* allocate memory for pkt_tx_buff & pkt_rx_buffer */ | ||
569 | data->pkt_tx_buff = kzalloc(size, GFP_KERNEL); | ||
570 | if (data->pkt_tx_buff != NULL) { | ||
571 | data->pkt_rx_buff = kzalloc(size, GFP_KERNEL); | ||
572 | if (!data->pkt_rx_buff) | ||
573 | kfree(data->pkt_tx_buff); | ||
574 | } | ||
575 | |||
576 | if (!data->pkt_rx_buff) { | ||
577 | /* flush queue and set status of all transfers to -ENOMEM */ | ||
578 | dev_err(&data->master->dev, "%s :kzalloc failed\n", __func__); | ||
579 | list_for_each_entry(pmsg, data->queue.next, queue) { | ||
580 | pmsg->status = -ENOMEM; | ||
581 | |||
582 | if (pmsg->complete != 0) | ||
583 | pmsg->complete(pmsg->context); | ||
584 | |||
585 | /* delete from queue */ | ||
586 | list_del_init(&pmsg->queue); | ||
587 | } | ||
588 | return; | ||
589 | } | ||
590 | |||
591 | /* copy Tx Data */ | ||
592 | if (data->cur_trans->tx_buf != NULL) { | ||
593 | if (*bpw == 8) { | ||
594 | tx_buf = data->cur_trans->tx_buf; | ||
595 | for (j = 0; j < data->bpw_len; j++) | ||
596 | data->pkt_tx_buff[j] = *tx_buf++; | ||
597 | } else { | ||
598 | tx_sbuf = data->cur_trans->tx_buf; | ||
599 | for (j = 0; j < data->bpw_len; j++) | ||
600 | data->pkt_tx_buff[j] = *tx_sbuf++; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* if len greater than PCH_MAX_FIFO_DEPTH, write 16,else len bytes */ | ||
605 | n_writes = data->bpw_len; | ||
606 | if (n_writes > PCH_MAX_FIFO_DEPTH) | ||
607 | n_writes = PCH_MAX_FIFO_DEPTH; | ||
608 | |||
609 | dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing " | ||
610 | "0x2 to SSNXCR\n", __func__); | ||
611 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW); | ||
612 | |||
613 | for (j = 0; j < n_writes; j++) | ||
614 | pch_spi_writereg(data->master, PCH_SPDWR, data->pkt_tx_buff[j]); | ||
615 | |||
616 | /* update tx_index */ | ||
617 | data->tx_index = j; | ||
618 | |||
619 | /* reset transfer complete flag */ | ||
620 | data->transfer_complete = false; | ||
621 | data->transfer_active = true; | ||
622 | } | ||
623 | |||
624 | |||
625 | static void pch_spi_nomore_transfer(struct pch_spi_data *data, | ||
626 | struct spi_message *pmsg) | ||
627 | { | ||
628 | dev_dbg(&data->master->dev, "%s called\n", __func__); | ||
629 | /* Invoke complete callback | ||
630 | * [To the spi core..indicating end of transfer] */ | ||
631 | data->current_msg->status = 0; | ||
632 | |||
633 | if (data->current_msg->complete != 0) { | ||
634 | dev_dbg(&data->master->dev, | ||
635 | "%s:Invoking callback of SPI core\n", __func__); | ||
636 | data->current_msg->complete(data->current_msg->context); | ||
637 | } | ||
638 | |||
639 | /* update status in global variable */ | ||
640 | data->bcurrent_msg_processing = false; | ||
641 | |||
642 | dev_dbg(&data->master->dev, | ||
643 | "%s:data->bcurrent_msg_processing = false\n", __func__); | ||
644 | |||
645 | data->current_msg = NULL; | ||
646 | data->cur_trans = NULL; | ||
647 | |||
648 | /* check if we have items in list and not suspending | ||
649 | * return 1 if list empty */ | ||
650 | if ((list_empty(&data->queue) == 0) && | ||
651 | (!data->board_dat->suspend_sts) && | ||
652 | (data->status != STATUS_EXITING)) { | ||
653 | /* We have some more work to do (either there is more tranint | ||
654 | * bpw;sfer requests in the current message or there are | ||
655 | *more messages) | ||
656 | */ | ||
657 | dev_dbg(&data->master->dev, "%s:Invoke queue_work\n", __func__); | ||
658 | queue_work(data->wk, &data->work); | ||
659 | } else if (data->board_dat->suspend_sts || | ||
660 | data->status == STATUS_EXITING) { | ||
661 | dev_dbg(&data->master->dev, | ||
662 | "%s suspend/remove initiated, flushing queue\n", | ||
663 | __func__); | ||
664 | list_for_each_entry(pmsg, data->queue.next, queue) { | ||
665 | pmsg->status = -EIO; | ||
666 | |||
667 | if (pmsg->complete) | ||
668 | pmsg->complete(pmsg->context); | ||
669 | |||
670 | /* delete from queue */ | ||
671 | list_del_init(&pmsg->queue); | ||
672 | } | ||
673 | } | ||
674 | } | ||
675 | |||
676 | static void pch_spi_set_ir(struct pch_spi_data *data) | ||
677 | { | ||
678 | /* enable interrupts */ | ||
679 | if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) { | ||
680 | /* set receive threhold to PCH_RX_THOLD */ | ||
681 | pch_spi_setclr_reg(data->master, PCH_SPCR, | ||
682 | PCH_RX_THOLD << SPCR_TFIC_FIELD, | ||
683 | ~MASK_TFIC_SPCR_BITS); | ||
684 | /* enable FI and RFI interrupts */ | ||
685 | pch_spi_setclr_reg(data->master, PCH_SPCR, | ||
686 | SPCR_RFIE_BIT | SPCR_TFIE_BIT, 0); | ||
687 | } else { | ||
688 | /* set receive threhold to maximum */ | ||
689 | pch_spi_setclr_reg(data->master, PCH_SPCR, | ||
690 | PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD, | ||
691 | ~MASK_TFIC_SPCR_BITS); | ||
692 | /* enable FI interrupt */ | ||
693 | pch_spi_setclr_reg(data->master, PCH_SPCR, SPCR_FIE_BIT, 0); | ||
694 | } | ||
695 | |||
696 | dev_dbg(&data->master->dev, | ||
697 | "%s:invoking pch_spi_set_enable to enable SPI\n", __func__); | ||
698 | |||
699 | /* SPI set enable */ | ||
700 | pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, SPCR_SPE_BIT, 0); | ||
701 | |||
702 | /* Wait until the transfer completes; go to sleep after | ||
703 | initiating the transfer. */ | ||
704 | dev_dbg(&data->master->dev, | ||
705 | "%s:waiting for transfer to get over\n", __func__); | ||
706 | |||
707 | wait_event_interruptible(data->wait, data->transfer_complete); | ||
708 | |||
709 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); | ||
710 | dev_dbg(&data->master->dev, | ||
711 | "%s:no more control over SSN-writing 0 to SSNXCR.", __func__); | ||
712 | |||
713 | data->transfer_active = false; | ||
714 | dev_dbg(&data->master->dev, | ||
715 | "%s set data->transfer_active = false\n", __func__); | ||
716 | |||
717 | /* clear all interrupts */ | ||
718 | pch_spi_writereg(data->master, PCH_SPSR, | ||
719 | pch_spi_readreg(data->master, PCH_SPSR)); | ||
720 | /* disable interrupts */ | ||
721 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); | ||
722 | } | ||
723 | |||
724 | static void pch_spi_copy_rx_data(struct pch_spi_data *data, int bpw) | ||
725 | { | ||
726 | int j; | ||
727 | u8 *rx_buf; | ||
728 | u16 *rx_sbuf; | ||
729 | |||
730 | /* copy Rx Data */ | ||
731 | if (!data->cur_trans->rx_buf) | ||
732 | return; | ||
733 | |||
734 | if (bpw == 8) { | ||
735 | rx_buf = data->cur_trans->rx_buf; | ||
736 | for (j = 0; j < data->bpw_len; j++) | ||
737 | *rx_buf++ = data->pkt_rx_buff[j] & 0xFF; | ||
738 | } else { | ||
739 | rx_sbuf = data->cur_trans->rx_buf; | ||
740 | for (j = 0; j < data->bpw_len; j++) | ||
741 | *rx_sbuf++ = data->pkt_rx_buff[j]; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | |||
746 | static void pch_spi_process_messages(struct work_struct *pwork) | ||
747 | { | ||
748 | struct spi_message *pmsg; | ||
749 | struct pch_spi_data *data; | ||
750 | int bpw; | ||
751 | |||
752 | data = container_of(pwork, struct pch_spi_data, work); | ||
753 | dev_dbg(&data->master->dev, "%s data initialized\n", __func__); | ||
754 | |||
755 | spin_lock(&data->lock); | ||
756 | |||
757 | /* check if suspend has been initiated;if yes flush queue */ | ||
758 | if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) { | ||
759 | dev_dbg(&data->master->dev, | ||
760 | "%s suspend/remove initiated,flushing queue\n", | ||
761 | __func__); | ||
762 | |||
763 | list_for_each_entry(pmsg, data->queue.next, queue) { | ||
764 | pmsg->status = -EIO; | ||
765 | |||
766 | if (pmsg->complete != 0) { | ||
767 | spin_unlock(&data->lock); | ||
768 | pmsg->complete(pmsg->context); | ||
769 | spin_lock(&data->lock); | ||
770 | } | ||
771 | |||
772 | /* delete from queue */ | ||
773 | list_del_init(&pmsg->queue); | ||
774 | } | ||
775 | |||
776 | spin_unlock(&data->lock); | ||
777 | return; | ||
778 | } | ||
779 | |||
780 | data->bcurrent_msg_processing = true; | ||
781 | dev_dbg(&data->master->dev, | ||
782 | "%s Set data->bcurrent_msg_processing= true\n", __func__); | ||
783 | |||
784 | /* Get the message from the queue and delete it from there. */ | ||
785 | data->current_msg = list_entry(data->queue.next, struct spi_message, | ||
786 | queue); | ||
787 | |||
788 | list_del_init(&data->current_msg->queue); | ||
789 | |||
790 | data->current_msg->status = 0; | ||
791 | |||
792 | pch_spi_select_chip(data, data->current_msg->spi); | ||
793 | |||
794 | spin_unlock(&data->lock); | ||
795 | |||
796 | do { | ||
797 | /* If we are already processing a message get the next | ||
798 | transfer structure from the message otherwise retrieve | ||
799 | the 1st transfer request from the message. */ | ||
800 | spin_lock(&data->lock); | ||
801 | |||
802 | if (data->cur_trans == NULL) { | ||
803 | data->cur_trans = | ||
804 | list_entry(data->current_msg->transfers. | ||
805 | next, struct spi_transfer, | ||
806 | transfer_list); | ||
807 | dev_dbg(&data->master->dev, | ||
808 | "%s :Getting 1st transfer message\n", __func__); | ||
809 | } else { | ||
810 | data->cur_trans = | ||
811 | list_entry(data->cur_trans->transfer_list.next, | ||
812 | struct spi_transfer, | ||
813 | transfer_list); | ||
814 | dev_dbg(&data->master->dev, | ||
815 | "%s :Getting next transfer message\n", | ||
816 | __func__); | ||
817 | } | ||
818 | |||
819 | spin_unlock(&data->lock); | ||
820 | |||
821 | pch_spi_set_tx(data, &bpw, &pmsg); | ||
822 | |||
823 | /* Control interrupt*/ | ||
824 | pch_spi_set_ir(data); | ||
825 | |||
826 | /* Disable SPI transfer */ | ||
827 | pch_spi_setclr_reg(data->current_chip->master, PCH_SPCR, 0, | ||
828 | SPCR_SPE_BIT); | ||
829 | |||
830 | /* clear FIFO */ | ||
831 | pch_spi_clear_fifo(data->master); | ||
832 | |||
833 | /* copy Rx Data */ | ||
834 | pch_spi_copy_rx_data(data, bpw); | ||
835 | |||
836 | /* free memory */ | ||
837 | kfree(data->pkt_rx_buff); | ||
838 | data->pkt_rx_buff = NULL; | ||
839 | |||
840 | kfree(data->pkt_tx_buff); | ||
841 | data->pkt_tx_buff = NULL; | ||
842 | |||
843 | /* increment message count */ | ||
844 | data->current_msg->actual_length += data->cur_trans->len; | ||
845 | |||
846 | dev_dbg(&data->master->dev, | ||
847 | "%s:data->current_msg->actual_length=%d\n", | ||
848 | __func__, data->current_msg->actual_length); | ||
849 | |||
850 | /* check for delay */ | ||
851 | if (data->cur_trans->delay_usecs) { | ||
852 | dev_dbg(&data->master->dev, "%s:" | ||
853 | "delay in usec=%d\n", __func__, | ||
854 | data->cur_trans->delay_usecs); | ||
855 | udelay(data->cur_trans->delay_usecs); | ||
856 | } | ||
857 | |||
858 | spin_lock(&data->lock); | ||
859 | |||
860 | /* No more transfer in this message. */ | ||
861 | if ((data->cur_trans->transfer_list.next) == | ||
862 | &(data->current_msg->transfers)) { | ||
863 | pch_spi_nomore_transfer(data, pmsg); | ||
864 | } | ||
865 | |||
866 | spin_unlock(&data->lock); | ||
867 | |||
868 | } while (data->cur_trans != NULL); | ||
869 | } | ||
870 | |||
871 | static void pch_spi_free_resources(struct pch_spi_board_data *board_dat) | ||
872 | { | ||
873 | dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__); | ||
874 | |||
875 | /* free workqueue */ | ||
876 | if (board_dat->data->wk != NULL) { | ||
877 | destroy_workqueue(board_dat->data->wk); | ||
878 | board_dat->data->wk = NULL; | ||
879 | dev_dbg(&board_dat->pdev->dev, | ||
880 | "%s destroy_workqueue invoked successfully\n", | ||
881 | __func__); | ||
882 | } | ||
883 | |||
884 | /* disable interrupts & free IRQ */ | ||
885 | if (board_dat->irq_reg_sts) { | ||
886 | /* disable interrupts */ | ||
887 | pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0, | ||
888 | PCH_ALL); | ||
889 | |||
890 | /* free IRQ */ | ||
891 | free_irq(board_dat->pdev->irq, board_dat); | ||
892 | |||
893 | dev_dbg(&board_dat->pdev->dev, | ||
894 | "%s free_irq invoked successfully\n", __func__); | ||
895 | |||
896 | board_dat->irq_reg_sts = false; | ||
897 | } | ||
898 | |||
899 | /* unmap PCI base address */ | ||
900 | if (board_dat->data->io_remap_addr != 0) { | ||
901 | pci_iounmap(board_dat->pdev, board_dat->data->io_remap_addr); | ||
902 | |||
903 | board_dat->data->io_remap_addr = 0; | ||
904 | |||
905 | dev_dbg(&board_dat->pdev->dev, | ||
906 | "%s pci_iounmap invoked successfully\n", __func__); | ||
907 | } | ||
908 | |||
909 | /* release PCI region */ | ||
910 | if (board_dat->pci_req_sts) { | ||
911 | pci_release_regions(board_dat->pdev); | ||
912 | dev_dbg(&board_dat->pdev->dev, | ||
913 | "%s pci_release_regions invoked successfully\n", | ||
914 | __func__); | ||
915 | board_dat->pci_req_sts = false; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | static int pch_spi_get_resources(struct pch_spi_board_data *board_dat) | ||
920 | { | ||
921 | void __iomem *io_remap_addr; | ||
922 | int retval; | ||
923 | dev_dbg(&board_dat->pdev->dev, "%s ENTRY\n", __func__); | ||
924 | |||
925 | /* create workqueue */ | ||
926 | board_dat->data->wk = create_singlethread_workqueue(KBUILD_MODNAME); | ||
927 | if (!board_dat->data->wk) { | ||
928 | dev_err(&board_dat->pdev->dev, | ||
929 | "%s create_singlet hread_workqueue failed\n", __func__); | ||
930 | retval = -EBUSY; | ||
931 | goto err_return; | ||
932 | } | ||
933 | |||
934 | dev_dbg(&board_dat->pdev->dev, | ||
935 | "%s create_singlethread_workqueue success\n", __func__); | ||
936 | |||
937 | retval = pci_request_regions(board_dat->pdev, KBUILD_MODNAME); | ||
938 | if (retval != 0) { | ||
939 | dev_err(&board_dat->pdev->dev, | ||
940 | "%s request_region failed\n", __func__); | ||
941 | goto err_return; | ||
942 | } | ||
943 | |||
944 | board_dat->pci_req_sts = true; | ||
945 | |||
946 | io_remap_addr = pci_iomap(board_dat->pdev, 1, 0); | ||
947 | if (io_remap_addr == 0) { | ||
948 | dev_err(&board_dat->pdev->dev, | ||
949 | "%s pci_iomap failed\n", __func__); | ||
950 | retval = -ENOMEM; | ||
951 | goto err_return; | ||
952 | } | ||
953 | |||
954 | /* calculate base address for all channels */ | ||
955 | board_dat->data->io_remap_addr = io_remap_addr; | ||
956 | |||
957 | /* reset PCH SPI h/w */ | ||
958 | pch_spi_reset(board_dat->data->master); | ||
959 | dev_dbg(&board_dat->pdev->dev, | ||
960 | "%s pch_spi_reset invoked successfully\n", __func__); | ||
961 | |||
962 | /* register IRQ */ | ||
963 | retval = request_irq(board_dat->pdev->irq, pch_spi_handler, | ||
964 | IRQF_SHARED, KBUILD_MODNAME, board_dat); | ||
965 | if (retval != 0) { | ||
966 | dev_err(&board_dat->pdev->dev, | ||
967 | "%s request_irq failed\n", __func__); | ||
968 | goto err_return; | ||
969 | } | ||
970 | |||
971 | dev_dbg(&board_dat->pdev->dev, "%s request_irq returned=%d\n", | ||
972 | __func__, retval); | ||
973 | |||
974 | board_dat->irq_reg_sts = true; | ||
975 | dev_dbg(&board_dat->pdev->dev, "%s data->irq_reg_sts=true\n", __func__); | ||
976 | |||
977 | err_return: | ||
978 | if (retval != 0) { | ||
979 | dev_err(&board_dat->pdev->dev, | ||
980 | "%s FAIL:invoking pch_spi_free_resources\n", __func__); | ||
981 | pch_spi_free_resources(board_dat); | ||
982 | } | ||
983 | |||
984 | dev_dbg(&board_dat->pdev->dev, "%s Return=%d\n", __func__, retval); | ||
985 | |||
986 | return retval; | ||
987 | } | ||
988 | |||
989 | static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
990 | { | ||
991 | |||
992 | struct spi_master *master; | ||
993 | |||
994 | struct pch_spi_board_data *board_dat; | ||
995 | int retval; | ||
996 | |||
997 | dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); | ||
998 | |||
999 | /* allocate memory for private data */ | ||
1000 | board_dat = kzalloc(sizeof(struct pch_spi_board_data), GFP_KERNEL); | ||
1001 | if (board_dat == NULL) { | ||
1002 | dev_err(&pdev->dev, | ||
1003 | " %s memory allocation for private data failed\n", | ||
1004 | __func__); | ||
1005 | retval = -ENOMEM; | ||
1006 | goto err_kmalloc; | ||
1007 | } | ||
1008 | |||
1009 | dev_dbg(&pdev->dev, | ||
1010 | "%s memory allocation for private data success\n", __func__); | ||
1011 | |||
1012 | /* enable PCI device */ | ||
1013 | retval = pci_enable_device(pdev); | ||
1014 | if (retval != 0) { | ||
1015 | dev_err(&pdev->dev, "%s pci_enable_device FAILED\n", __func__); | ||
1016 | |||
1017 | goto err_pci_en_device; | ||
1018 | } | ||
1019 | |||
1020 | dev_dbg(&pdev->dev, "%s pci_enable_device returned=%d\n", | ||
1021 | __func__, retval); | ||
1022 | |||
1023 | board_dat->pdev = pdev; | ||
1024 | |||
1025 | /* alllocate memory for SPI master */ | ||
1026 | master = spi_alloc_master(&pdev->dev, sizeof(struct pch_spi_data)); | ||
1027 | if (master == NULL) { | ||
1028 | retval = -ENOMEM; | ||
1029 | dev_err(&pdev->dev, "%s Fail.\n", __func__); | ||
1030 | goto err_spi_alloc_master; | ||
1031 | } | ||
1032 | |||
1033 | dev_dbg(&pdev->dev, | ||
1034 | "%s spi_alloc_master returned non NULL\n", __func__); | ||
1035 | |||
1036 | /* initialize members of SPI master */ | ||
1037 | master->bus_num = -1; | ||
1038 | master->num_chipselect = PCH_MAX_CS; | ||
1039 | master->setup = pch_spi_setup; | ||
1040 | master->transfer = pch_spi_transfer; | ||
1041 | dev_dbg(&pdev->dev, | ||
1042 | "%s transfer member of SPI master initialized\n", __func__); | ||
1043 | |||
1044 | board_dat->data = spi_master_get_devdata(master); | ||
1045 | |||
1046 | board_dat->data->master = master; | ||
1047 | board_dat->data->n_curnt_chip = 255; | ||
1048 | board_dat->data->board_dat = board_dat; | ||
1049 | board_dat->data->status = STATUS_RUNNING; | ||
1050 | |||
1051 | INIT_LIST_HEAD(&board_dat->data->queue); | ||
1052 | spin_lock_init(&board_dat->data->lock); | ||
1053 | INIT_WORK(&board_dat->data->work, pch_spi_process_messages); | ||
1054 | init_waitqueue_head(&board_dat->data->wait); | ||
1055 | |||
1056 | /* allocate resources for PCH SPI */ | ||
1057 | retval = pch_spi_get_resources(board_dat); | ||
1058 | if (retval) { | ||
1059 | dev_err(&pdev->dev, "%s fail(retval=%d)\n", __func__, retval); | ||
1060 | goto err_spi_get_resources; | ||
1061 | } | ||
1062 | |||
1063 | dev_dbg(&pdev->dev, "%s pch_spi_get_resources returned=%d\n", | ||
1064 | __func__, retval); | ||
1065 | |||
1066 | /* save private data in dev */ | ||
1067 | pci_set_drvdata(pdev, board_dat); | ||
1068 | dev_dbg(&pdev->dev, "%s invoked pci_set_drvdata\n", __func__); | ||
1069 | |||
1070 | /* set master mode */ | ||
1071 | pch_spi_set_master_mode(master); | ||
1072 | dev_dbg(&pdev->dev, | ||
1073 | "%s invoked pch_spi_set_master_mode\n", __func__); | ||
1074 | |||
1075 | /* Register the controller with the SPI core. */ | ||
1076 | retval = spi_register_master(master); | ||
1077 | if (retval != 0) { | ||
1078 | dev_err(&pdev->dev, | ||
1079 | "%s spi_register_master FAILED\n", __func__); | ||
1080 | goto err_spi_reg_master; | ||
1081 | } | ||
1082 | |||
1083 | dev_dbg(&pdev->dev, "%s spi_register_master returned=%d\n", | ||
1084 | __func__, retval); | ||
1085 | |||
1086 | |||
1087 | return 0; | ||
1088 | |||
1089 | err_spi_reg_master: | ||
1090 | spi_unregister_master(master); | ||
1091 | err_spi_get_resources: | ||
1092 | err_spi_alloc_master: | ||
1093 | spi_master_put(master); | ||
1094 | pci_disable_device(pdev); | ||
1095 | err_pci_en_device: | ||
1096 | kfree(board_dat); | ||
1097 | err_kmalloc: | ||
1098 | return retval; | ||
1099 | } | ||
1100 | |||
1101 | static void pch_spi_remove(struct pci_dev *pdev) | ||
1102 | { | ||
1103 | struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev); | ||
1104 | int count; | ||
1105 | |||
1106 | dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); | ||
1107 | |||
1108 | if (!board_dat) { | ||
1109 | dev_err(&pdev->dev, | ||
1110 | "%s pci_get_drvdata returned NULL\n", __func__); | ||
1111 | return; | ||
1112 | } | ||
1113 | |||
1114 | /* check for any pending messages; no action is taken if the queue | ||
1115 | * is still full; but at least we tried. Unload anyway */ | ||
1116 | count = 500; | ||
1117 | spin_lock(&board_dat->data->lock); | ||
1118 | board_dat->data->status = STATUS_EXITING; | ||
1119 | while ((list_empty(&board_dat->data->queue) == 0) && --count) { | ||
1120 | dev_dbg(&board_dat->pdev->dev, "%s :queue not empty\n", | ||
1121 | __func__); | ||
1122 | spin_unlock(&board_dat->data->lock); | ||
1123 | msleep(PCH_SLEEP_TIME); | ||
1124 | spin_lock(&board_dat->data->lock); | ||
1125 | } | ||
1126 | spin_unlock(&board_dat->data->lock); | ||
1127 | |||
1128 | /* Free resources allocated for PCH SPI */ | ||
1129 | pch_spi_free_resources(board_dat); | ||
1130 | |||
1131 | spi_unregister_master(board_dat->data->master); | ||
1132 | |||
1133 | /* free memory for private data */ | ||
1134 | kfree(board_dat); | ||
1135 | |||
1136 | pci_set_drvdata(pdev, NULL); | ||
1137 | |||
1138 | /* disable PCI device */ | ||
1139 | pci_disable_device(pdev); | ||
1140 | |||
1141 | dev_dbg(&pdev->dev, "%s invoked pci_disable_device\n", __func__); | ||
1142 | } | ||
1143 | |||
1144 | #ifdef CONFIG_PM | ||
1145 | static int pch_spi_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1146 | { | ||
1147 | u8 count; | ||
1148 | int retval; | ||
1149 | |||
1150 | struct pch_spi_board_data *board_dat = pci_get_drvdata(pdev); | ||
1151 | |||
1152 | dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); | ||
1153 | |||
1154 | if (!board_dat) { | ||
1155 | dev_err(&pdev->dev, | ||
1156 | "%s pci_get_drvdata returned NULL\n", __func__); | ||
1157 | return -EFAULT; | ||
1158 | } | ||
1159 | |||
1160 | retval = 0; | ||
1161 | board_dat->suspend_sts = true; | ||
1162 | |||
1163 | /* check if the current message is processed: | ||
1164 | Only after thats done the transfer will be suspended */ | ||
1165 | count = 255; | ||
1166 | while ((--count) > 0) { | ||
1167 | if (!(board_dat->data->bcurrent_msg_processing)) { | ||
1168 | dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_" | ||
1169 | "msg_processing = false\n", __func__); | ||
1170 | break; | ||
1171 | } else { | ||
1172 | dev_dbg(&pdev->dev, "%s board_dat->data->bCurrent_msg_" | ||
1173 | "processing = true\n", __func__); | ||
1174 | } | ||
1175 | msleep(PCH_SLEEP_TIME); | ||
1176 | } | ||
1177 | |||
1178 | /* Free IRQ */ | ||
1179 | if (board_dat->irq_reg_sts) { | ||
1180 | /* disable all interrupts */ | ||
1181 | pch_spi_setclr_reg(board_dat->data->master, PCH_SPCR, 0, | ||
1182 | PCH_ALL); | ||
1183 | pch_spi_reset(board_dat->data->master); | ||
1184 | |||
1185 | free_irq(board_dat->pdev->irq, board_dat); | ||
1186 | |||
1187 | board_dat->irq_reg_sts = false; | ||
1188 | dev_dbg(&pdev->dev, | ||
1189 | "%s free_irq invoked successfully.\n", __func__); | ||
1190 | } | ||
1191 | |||
1192 | /* save config space */ | ||
1193 | retval = pci_save_state(pdev); | ||
1194 | |||
1195 | if (retval == 0) { | ||
1196 | dev_dbg(&pdev->dev, "%s pci_save_state returned=%d\n", | ||
1197 | __func__, retval); | ||
1198 | /* disable PM notifications */ | ||
1199 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
1200 | dev_dbg(&pdev->dev, | ||
1201 | "%s pci_enable_wake invoked successfully\n", __func__); | ||
1202 | /* disable PCI device */ | ||
1203 | pci_disable_device(pdev); | ||
1204 | dev_dbg(&pdev->dev, | ||
1205 | "%s pci_disable_device invoked successfully\n", | ||
1206 | __func__); | ||
1207 | /* move device to D3hot state */ | ||
1208 | pci_set_power_state(pdev, PCI_D3hot); | ||
1209 | dev_dbg(&pdev->dev, | ||
1210 | "%s pci_set_power_state invoked successfully\n", | ||
1211 | __func__); | ||
1212 | } else { | ||
1213 | dev_err(&pdev->dev, "%s pci_save_state failed\n", __func__); | ||
1214 | } | ||
1215 | |||
1216 | dev_dbg(&pdev->dev, "%s return=%d\n", __func__, retval); | ||
1217 | |||
1218 | return retval; | ||
1219 | } | ||
1220 | |||
1221 | static int pch_spi_resume(struct pci_dev *pdev) | ||
1222 | { | ||
1223 | int retval; | ||
1224 | |||
1225 | struct pch_spi_board_data *board = pci_get_drvdata(pdev); | ||
1226 | dev_dbg(&pdev->dev, "%s ENTRY\n", __func__); | ||
1227 | |||
1228 | if (!board) { | ||
1229 | dev_err(&pdev->dev, | ||
1230 | "%s pci_get_drvdata returned NULL\n", __func__); | ||
1231 | return -EFAULT; | ||
1232 | } | ||
1233 | |||
1234 | /* move device to DO power state */ | ||
1235 | pci_set_power_state(pdev, PCI_D0); | ||
1236 | |||
1237 | /* restore state */ | ||
1238 | pci_restore_state(pdev); | ||
1239 | |||
1240 | retval = pci_enable_device(pdev); | ||
1241 | if (retval < 0) { | ||
1242 | dev_err(&pdev->dev, | ||
1243 | "%s pci_enable_device failed\n", __func__); | ||
1244 | } else { | ||
1245 | /* disable PM notifications */ | ||
1246 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
1247 | |||
1248 | /* register IRQ handler */ | ||
1249 | if (!board->irq_reg_sts) { | ||
1250 | /* register IRQ */ | ||
1251 | retval = request_irq(board->pdev->irq, pch_spi_handler, | ||
1252 | IRQF_SHARED, KBUILD_MODNAME, | ||
1253 | board); | ||
1254 | if (retval < 0) { | ||
1255 | dev_err(&pdev->dev, | ||
1256 | "%s request_irq failed\n", __func__); | ||
1257 | return retval; | ||
1258 | } | ||
1259 | board->irq_reg_sts = true; | ||
1260 | |||
1261 | /* reset PCH SPI h/w */ | ||
1262 | pch_spi_reset(board->data->master); | ||
1263 | pch_spi_set_master_mode(board->data->master); | ||
1264 | |||
1265 | /* set suspend status to false */ | ||
1266 | board->suspend_sts = false; | ||
1267 | |||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | dev_dbg(&pdev->dev, "%s returning=%d\n", __func__, retval); | ||
1272 | |||
1273 | return retval; | ||
1274 | } | ||
1275 | #else | ||
1276 | #define pch_spi_suspend NULL | ||
1277 | #define pch_spi_resume NULL | ||
1278 | |||
1279 | #endif | ||
1280 | |||
1281 | static struct pci_driver pch_spi_pcidev = { | ||
1282 | .name = "pch_spi", | ||
1283 | .id_table = pch_spi_pcidev_id, | ||
1284 | .probe = pch_spi_probe, | ||
1285 | .remove = pch_spi_remove, | ||
1286 | .suspend = pch_spi_suspend, | ||
1287 | .resume = pch_spi_resume, | ||
1288 | }; | ||
1289 | |||
1290 | static int __init pch_spi_init(void) | ||
1291 | { | ||
1292 | return pci_register_driver(&pch_spi_pcidev); | ||
1293 | } | ||
1294 | module_init(pch_spi_init); | ||
1295 | |||
1296 | static void __exit pch_spi_exit(void) | ||
1297 | { | ||
1298 | pci_unregister_driver(&pch_spi_pcidev); | ||
1299 | } | ||
1300 | module_exit(pch_spi_exit); | ||
1301 | |||
1302 | MODULE_LICENSE("GPL"); | ||
1303 | MODULE_DESCRIPTION("Topcliff PCH SPI PCI Driver"); | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 7892ac163522..c68b3dc19e11 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/mmc/sdio_func.h> | 20 | #include <linux/mmc/sdio_func.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | 22 | ||
23 | #include <pcmcia/cs.h> | ||
24 | #include <pcmcia/cistpl.h> | 23 | #include <pcmcia/cistpl.h> |
25 | #include <pcmcia/ds.h> | 24 | #include <pcmcia/ds.h> |
26 | 25 | ||
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index 526682d68de8..c7345dbf43fa 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
15 | 15 | ||
16 | #include <pcmcia/cs.h> | ||
17 | #include <pcmcia/cistpl.h> | 16 | #include <pcmcia/cistpl.h> |
18 | #include <pcmcia/ciscode.h> | 17 | #include <pcmcia/ciscode.h> |
19 | #include <pcmcia/ds.h> | 18 | #include <pcmcia/ds.h> |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 9738cad4ba13..ee079ab9fb28 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | 19 | ||
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/cistpl.h> | 20 | #include <pcmcia/cistpl.h> |
22 | #include <pcmcia/ds.h> | 21 | #include <pcmcia/ds.h> |
23 | 22 | ||
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index f8ede1182ccc..0345b4caba73 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c | |||
@@ -37,7 +37,6 @@ Status: experimental | |||
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
39 | 39 | ||
40 | #include <pcmcia/cs.h> | ||
41 | #include <pcmcia/cistpl.h> | 40 | #include <pcmcia/cistpl.h> |
42 | #include <pcmcia/ds.h> | 41 | #include <pcmcia/ds.h> |
43 | 42 | ||
@@ -692,10 +691,6 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link) | |||
692 | local->link = link; | 691 | local->link = link; |
693 | link->priv = local; | 692 | link->priv = local; |
694 | 693 | ||
695 | /* Initialize the pcmcia_device structure */ | ||
696 | link->conf.Attributes = 0; | ||
697 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
698 | |||
699 | cur_dev = link; | 694 | cur_dev = link; |
700 | 695 | ||
701 | das16cs_pcmcia_config(link); | 696 | das16cs_pcmcia_config(link); |
@@ -715,37 +710,12 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link) | |||
715 | 710 | ||
716 | 711 | ||
717 | static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, | 712 | static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, |
718 | cistpl_cftable_entry_t *cfg, | ||
719 | cistpl_cftable_entry_t *dflt, | ||
720 | unsigned int vcc, | ||
721 | void *priv_data) | 713 | void *priv_data) |
722 | { | 714 | { |
723 | if (cfg->index == 0) | 715 | if (p_dev->config_index == 0) |
724 | return -EINVAL; | 716 | return -EINVAL; |
725 | 717 | ||
726 | /* Do we need to allocate an interrupt? */ | 718 | return pcmcia_request_io(p_dev); |
727 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
728 | |||
729 | /* IO window settings */ | ||
730 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
731 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
732 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
733 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
734 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
735 | p_dev->resource[0]->flags |= | ||
736 | pcmcia_io_cfg_data_width(io->flags); | ||
737 | p_dev->resource[0]->start = io->win[0].base; | ||
738 | p_dev->resource[0]->end = io->win[0].len; | ||
739 | if (io->nwin > 1) { | ||
740 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
741 | p_dev->resource[1]->start = io->win[1].base; | ||
742 | p_dev->resource[1]->end = io->win[1].len; | ||
743 | } | ||
744 | /* This reserves IO space but doesn't actually enable it */ | ||
745 | return pcmcia_request_io(p_dev); | ||
746 | } | ||
747 | |||
748 | return 0; | ||
749 | } | 719 | } |
750 | 720 | ||
751 | static void das16cs_pcmcia_config(struct pcmcia_device *link) | 721 | static void das16cs_pcmcia_config(struct pcmcia_device *link) |
@@ -754,6 +724,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link) | |||
754 | 724 | ||
755 | dev_dbg(&link->dev, "das16cs_pcmcia_config\n"); | 725 | dev_dbg(&link->dev, "das16cs_pcmcia_config\n"); |
756 | 726 | ||
727 | /* Do we need to allocate an interrupt? */ | ||
728 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
729 | |||
757 | ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); | 730 | ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); |
758 | if (ret) { | 731 | if (ret) { |
759 | dev_warn(&link->dev, "no configuration found\n"); | 732 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -763,25 +736,10 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link) | |||
763 | if (!link->irq) | 736 | if (!link->irq) |
764 | goto failed; | 737 | goto failed; |
765 | 738 | ||
766 | /* | 739 | ret = pcmcia_enable_device(link); |
767 | This actually configures the PCMCIA socket -- setting up | ||
768 | the I/O windows and the interrupt mapping, and putting the | ||
769 | card and host interface into "Memory and IO" mode. | ||
770 | */ | ||
771 | ret = pcmcia_request_configuration(link, &link->conf); | ||
772 | if (ret) | 740 | if (ret) |
773 | goto failed; | 741 | goto failed; |
774 | 742 | ||
775 | /* Finally, report what we've done */ | ||
776 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
777 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
778 | printk(", irq %u", link->irq); | ||
779 | if (link->resource[0]) | ||
780 | printk(", io %pR", link->resource[0]); | ||
781 | if (link->resource[1]) | ||
782 | printk(", io %pR", link->resource[1]); | ||
783 | printk("\n"); | ||
784 | |||
785 | return; | 743 | return; |
786 | 744 | ||
787 | failed: | 745 | failed: |
@@ -832,9 +790,7 @@ struct pcmcia_driver das16cs_driver = { | |||
832 | .resume = das16cs_pcmcia_resume, | 790 | .resume = das16cs_pcmcia_resume, |
833 | .id_table = das16cs_id_table, | 791 | .id_table = das16cs_id_table, |
834 | .owner = THIS_MODULE, | 792 | .owner = THIS_MODULE, |
835 | .drv = { | 793 | .name = "cb_das16_cs", |
836 | .name = "cb_das16_cs", | ||
837 | }, | ||
838 | }; | 794 | }; |
839 | 795 | ||
840 | static int __init init_das16cs_pcmcia_cs(void) | 796 | static int __init init_das16cs_pcmcia_cs(void) |
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 48d9fb1227df..0b32a2df7768 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c | |||
@@ -48,7 +48,6 @@ Command support does not exist, but could be added for this board. | |||
48 | #include "das08.h" | 48 | #include "das08.h" |
49 | 49 | ||
50 | /* pcmcia includes */ | 50 | /* pcmcia includes */ |
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
54 | 53 | ||
@@ -115,40 +114,15 @@ static void das08_pcmcia_release(struct pcmcia_device *link); | |||
115 | static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); | 114 | static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); |
116 | static int das08_pcmcia_resume(struct pcmcia_device *p_dev); | 115 | static int das08_pcmcia_resume(struct pcmcia_device *p_dev); |
117 | 116 | ||
118 | /* | ||
119 | The attach() and detach() entry points are used to create and destroy | ||
120 | "instances" of the driver, where each instance represents everything | ||
121 | needed to manage one actual PCMCIA card. | ||
122 | */ | ||
123 | |||
124 | static int das08_pcmcia_attach(struct pcmcia_device *); | 117 | static int das08_pcmcia_attach(struct pcmcia_device *); |
125 | static void das08_pcmcia_detach(struct pcmcia_device *); | 118 | static void das08_pcmcia_detach(struct pcmcia_device *); |
126 | 119 | ||
127 | /* | ||
128 | You'll also need to prototype all the functions that will actually | ||
129 | be used to talk to your device. See 'memory_cs' for a good example | ||
130 | of a fully self-sufficient driver; the other drivers rely more or | ||
131 | less on other parts of the kernel. | ||
132 | */ | ||
133 | |||
134 | struct local_info_t { | 120 | struct local_info_t { |
135 | struct pcmcia_device *link; | 121 | struct pcmcia_device *link; |
136 | int stop; | 122 | int stop; |
137 | struct bus_operations *bus; | 123 | struct bus_operations *bus; |
138 | }; | 124 | }; |
139 | 125 | ||
140 | /*====================================================================== | ||
141 | |||
142 | das08_pcmcia_attach() creates an "instance" of the driver, allocating | ||
143 | local data structures for one device. The device is registered | ||
144 | with Card Services. | ||
145 | |||
146 | The dev_link structure is initialized, but we don't actually | ||
147 | configure the card at this point -- we wait until we receive a | ||
148 | card insertion event. | ||
149 | |||
150 | ======================================================================*/ | ||
151 | |||
152 | static int das08_pcmcia_attach(struct pcmcia_device *link) | 126 | static int das08_pcmcia_attach(struct pcmcia_device *link) |
153 | { | 127 | { |
154 | struct local_info_t *local; | 128 | struct local_info_t *local; |
@@ -162,16 +136,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link) | |||
162 | local->link = link; | 136 | local->link = link; |
163 | link->priv = local; | 137 | link->priv = local; |
164 | 138 | ||
165 | /* | ||
166 | General socket configuration defaults can go here. In this | ||
167 | client, we assume very little, and rely on the CIS for almost | ||
168 | everything. In most clients, many details (i.e., number, sizes, | ||
169 | and attributes of IO windows) are fixed by the nature of the | ||
170 | device, and can be hard-wired here. | ||
171 | */ | ||
172 | link->conf.Attributes = 0; | ||
173 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
174 | |||
175 | cur_dev = link; | 139 | cur_dev = link; |
176 | 140 | ||
177 | das08_pcmcia_config(link); | 141 | das08_pcmcia_config(link); |
@@ -179,15 +143,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link) | |||
179 | return 0; | 143 | return 0; |
180 | } /* das08_pcmcia_attach */ | 144 | } /* das08_pcmcia_attach */ |
181 | 145 | ||
182 | /*====================================================================== | ||
183 | |||
184 | This deletes a driver "instance". The device is de-registered | ||
185 | with Card Services. If it has been released, all local data | ||
186 | structures are freed. Otherwise, the structures will be freed | ||
187 | when the device is released. | ||
188 | |||
189 | ======================================================================*/ | ||
190 | |||
191 | static void das08_pcmcia_detach(struct pcmcia_device *link) | 146 | static void das08_pcmcia_detach(struct pcmcia_device *link) |
192 | { | 147 | { |
193 | 148 | ||
@@ -203,46 +158,13 @@ static void das08_pcmcia_detach(struct pcmcia_device *link) | |||
203 | 158 | ||
204 | 159 | ||
205 | static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, | 160 | static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, |
206 | cistpl_cftable_entry_t *cfg, | ||
207 | cistpl_cftable_entry_t *dflt, | ||
208 | unsigned int vcc, | ||
209 | void *priv_data) | 161 | void *priv_data) |
210 | { | 162 | { |
211 | if (cfg->index == 0) | 163 | if (p_dev->config_index == 0) |
212 | return -ENODEV; | 164 | return -EINVAL; |
213 | |||
214 | /* Do we need to allocate an interrupt? */ | ||
215 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
216 | |||
217 | /* IO window settings */ | ||
218 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
219 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
220 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
221 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
222 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
223 | p_dev->resource[0]->flags |= | ||
224 | pcmcia_io_cfg_data_width(io->flags); | ||
225 | p_dev->resource[0]->start = io->win[0].base; | ||
226 | p_dev->resource[0]->end = io->win[0].len; | ||
227 | if (io->nwin > 1) { | ||
228 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
229 | p_dev->resource[1]->start = io->win[1].base; | ||
230 | p_dev->resource[1]->end = io->win[1].len; | ||
231 | } | ||
232 | /* This reserves IO space but doesn't actually enable it */ | ||
233 | return pcmcia_request_io(p_dev); | ||
234 | } | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | |||
239 | /*====================================================================== | ||
240 | |||
241 | das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event | ||
242 | is received, to configure the PCMCIA socket, and to make the | ||
243 | device available to the system. | ||
244 | 165 | ||
245 | ======================================================================*/ | 166 | return pcmcia_request_io(p_dev); |
167 | } | ||
246 | 168 | ||
247 | static void das08_pcmcia_config(struct pcmcia_device *link) | 169 | static void das08_pcmcia_config(struct pcmcia_device *link) |
248 | { | 170 | { |
@@ -250,6 +172,8 @@ static void das08_pcmcia_config(struct pcmcia_device *link) | |||
250 | 172 | ||
251 | dev_dbg(&link->dev, "das08_pcmcia_config\n"); | 173 | dev_dbg(&link->dev, "das08_pcmcia_config\n"); |
252 | 174 | ||
175 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
176 | |||
253 | ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); | 177 | ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); |
254 | if (ret) { | 178 | if (ret) { |
255 | dev_warn(&link->dev, "no configuration found\n"); | 179 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -259,25 +183,10 @@ static void das08_pcmcia_config(struct pcmcia_device *link) | |||
259 | if (!link->irq) | 183 | if (!link->irq) |
260 | goto failed; | 184 | goto failed; |
261 | 185 | ||
262 | /* | 186 | ret = pcmcia_enable_device(link); |
263 | This actually configures the PCMCIA socket -- setting up | ||
264 | the I/O windows and the interrupt mapping, and putting the | ||
265 | card and host interface into "Memory and IO" mode. | ||
266 | */ | ||
267 | ret = pcmcia_request_configuration(link, &link->conf); | ||
268 | if (ret) | 187 | if (ret) |
269 | goto failed; | 188 | goto failed; |
270 | 189 | ||
271 | /* Finally, report what we've done */ | ||
272 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
273 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
274 | printk(", irq %u", link->irq); | ||
275 | if (link->resource[0]) | ||
276 | printk(", io %pR", link->resource[0]); | ||
277 | if (link->resource[1]) | ||
278 | printk(" & %pR", link->resource[1]); | ||
279 | printk("\n"); | ||
280 | |||
281 | return; | 190 | return; |
282 | 191 | ||
283 | failed: | 192 | failed: |
@@ -285,32 +194,12 @@ failed: | |||
285 | 194 | ||
286 | } /* das08_pcmcia_config */ | 195 | } /* das08_pcmcia_config */ |
287 | 196 | ||
288 | /*====================================================================== | ||
289 | |||
290 | After a card is removed, das08_pcmcia_release() will unregister the | ||
291 | device, and release the PCMCIA configuration. If the device is | ||
292 | still open, this will be postponed until it is closed. | ||
293 | |||
294 | ======================================================================*/ | ||
295 | |||
296 | static void das08_pcmcia_release(struct pcmcia_device *link) | 197 | static void das08_pcmcia_release(struct pcmcia_device *link) |
297 | { | 198 | { |
298 | dev_dbg(&link->dev, "das08_pcmcia_release\n"); | 199 | dev_dbg(&link->dev, "das08_pcmcia_release\n"); |
299 | pcmcia_disable_device(link); | 200 | pcmcia_disable_device(link); |
300 | } /* das08_pcmcia_release */ | 201 | } /* das08_pcmcia_release */ |
301 | 202 | ||
302 | /*====================================================================== | ||
303 | |||
304 | The card status event handler. Mostly, this schedules other | ||
305 | stuff to run after an event is received. | ||
306 | |||
307 | When a CARD_REMOVAL event is received, we immediately set a | ||
308 | private flag to block future accesses to this device. All the | ||
309 | functions that actually access the device should check this flag | ||
310 | to make sure the card is still present. | ||
311 | |||
312 | ======================================================================*/ | ||
313 | |||
314 | static int das08_pcmcia_suspend(struct pcmcia_device *link) | 203 | static int das08_pcmcia_suspend(struct pcmcia_device *link) |
315 | { | 204 | { |
316 | struct local_info_t *local = link->priv; | 205 | struct local_info_t *local = link->priv; |
@@ -348,9 +237,7 @@ struct pcmcia_driver das08_cs_driver = { | |||
348 | .resume = das08_pcmcia_resume, | 237 | .resume = das08_pcmcia_resume, |
349 | .id_table = das08_cs_id_table, | 238 | .id_table = das08_cs_id_table, |
350 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
351 | .drv = { | 240 | .name = "pcm-das08", |
352 | .name = "pcm-das08", | ||
353 | }, | ||
354 | }; | 241 | }; |
355 | 242 | ||
356 | static int __init init_das08_pcmcia_cs(void) | 243 | static int __init init_das08_pcmcia_cs(void) |
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index cc15666e5cc1..fc772a8a55c6 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c | |||
@@ -47,7 +47,6 @@ IRQ is assigned but not used. | |||
47 | 47 | ||
48 | #include <linux/ioport.h> | 48 | #include <linux/ioport.h> |
49 | 49 | ||
50 | #include <pcmcia/cs.h> | ||
51 | #include <pcmcia/cistpl.h> | 50 | #include <pcmcia/cistpl.h> |
52 | #include <pcmcia/cisreg.h> | 51 | #include <pcmcia/cisreg.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
@@ -435,47 +434,20 @@ static int dio700_detach(struct comedi_device *dev) | |||
435 | return 0; | 434 | return 0; |
436 | }; | 435 | }; |
437 | 436 | ||
438 | /* PCMCIA crap -- watch your words, please! */ | ||
439 | |||
440 | static void dio700_config(struct pcmcia_device *link); | 437 | static void dio700_config(struct pcmcia_device *link); |
441 | static void dio700_release(struct pcmcia_device *link); | 438 | static void dio700_release(struct pcmcia_device *link); |
442 | static int dio700_cs_suspend(struct pcmcia_device *p_dev); | 439 | static int dio700_cs_suspend(struct pcmcia_device *p_dev); |
443 | static int dio700_cs_resume(struct pcmcia_device *p_dev); | 440 | static int dio700_cs_resume(struct pcmcia_device *p_dev); |
444 | 441 | ||
445 | /* | ||
446 | The attach() and detach() entry points are used to create and destroy | ||
447 | "instances" of the driver, where each instance represents everything | ||
448 | needed to manage one actual PCMCIA card. | ||
449 | */ | ||
450 | |||
451 | static int dio700_cs_attach(struct pcmcia_device *); | 442 | static int dio700_cs_attach(struct pcmcia_device *); |
452 | static void dio700_cs_detach(struct pcmcia_device *); | 443 | static void dio700_cs_detach(struct pcmcia_device *); |
453 | 444 | ||
454 | /* | ||
455 | You'll also need to prototype all the functions that will actually | ||
456 | be used to talk to your device. See 'memory_cs' for a good example | ||
457 | of a fully self-sufficient driver; the other drivers rely more or | ||
458 | less on other parts of the kernel. | ||
459 | */ | ||
460 | |||
461 | struct local_info_t { | 445 | struct local_info_t { |
462 | struct pcmcia_device *link; | 446 | struct pcmcia_device *link; |
463 | int stop; | 447 | int stop; |
464 | struct bus_operations *bus; | 448 | struct bus_operations *bus; |
465 | }; | 449 | }; |
466 | 450 | ||
467 | /*====================================================================== | ||
468 | |||
469 | dio700_cs_attach() creates an "instance" of the driver, allocating | ||
470 | local data structures for one device. The device is registered | ||
471 | with Card Services. | ||
472 | |||
473 | The dev_link structure is initialized, but we don't actually | ||
474 | configure the card at this point -- we wait until we receive a | ||
475 | card insertion event. | ||
476 | |||
477 | ======================================================================*/ | ||
478 | |||
479 | static int dio700_cs_attach(struct pcmcia_device *link) | 451 | static int dio700_cs_attach(struct pcmcia_device *link) |
480 | { | 452 | { |
481 | struct local_info_t *local; | 453 | struct local_info_t *local; |
@@ -491,16 +463,6 @@ static int dio700_cs_attach(struct pcmcia_device *link) | |||
491 | local->link = link; | 463 | local->link = link; |
492 | link->priv = local; | 464 | link->priv = local; |
493 | 465 | ||
494 | /* | ||
495 | General socket configuration defaults can go here. In this | ||
496 | client, we assume very little, and rely on the CIS for almost | ||
497 | everything. In most clients, many details (i.e., number, sizes, | ||
498 | and attributes of IO windows) are fixed by the nature of the | ||
499 | device, and can be hard-wired here. | ||
500 | */ | ||
501 | link->conf.Attributes = 0; | ||
502 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
503 | |||
504 | pcmcia_cur_dev = link; | 466 | pcmcia_cur_dev = link; |
505 | 467 | ||
506 | dio700_config(link); | 468 | dio700_config(link); |
@@ -508,15 +470,6 @@ static int dio700_cs_attach(struct pcmcia_device *link) | |||
508 | return 0; | 470 | return 0; |
509 | } /* dio700_cs_attach */ | 471 | } /* dio700_cs_attach */ |
510 | 472 | ||
511 | /*====================================================================== | ||
512 | |||
513 | This deletes a driver "instance". The device is de-registered | ||
514 | with Card Services. If it has been released, all local data | ||
515 | structures are freed. Otherwise, the structures will be freed | ||
516 | when the device is released. | ||
517 | |||
518 | ======================================================================*/ | ||
519 | |||
520 | static void dio700_cs_detach(struct pcmcia_device *link) | 473 | static void dio700_cs_detach(struct pcmcia_device *link) |
521 | { | 474 | { |
522 | 475 | ||
@@ -532,54 +485,13 @@ static void dio700_cs_detach(struct pcmcia_device *link) | |||
532 | 485 | ||
533 | } /* dio700_cs_detach */ | 486 | } /* dio700_cs_detach */ |
534 | 487 | ||
535 | /*====================================================================== | ||
536 | |||
537 | dio700_config() is scheduled to run after a CARD_INSERTION event | ||
538 | is received, to configure the PCMCIA socket, and to make the | ||
539 | device available to the system. | ||
540 | |||
541 | ======================================================================*/ | ||
542 | |||
543 | static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, | 488 | static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, |
544 | cistpl_cftable_entry_t *cfg, | ||
545 | cistpl_cftable_entry_t *dflt, | ||
546 | unsigned int vcc, | ||
547 | void *priv_data) | 489 | void *priv_data) |
548 | { | 490 | { |
549 | if (cfg->index == 0) | 491 | if (p_dev->config_index == 0) |
550 | return -ENODEV; | 492 | return -EINVAL; |
551 | |||
552 | /* Does this card need audio output? */ | ||
553 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
554 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
555 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
556 | } | ||
557 | |||
558 | /* Do we need to allocate an interrupt? */ | ||
559 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
560 | |||
561 | /* IO window settings */ | ||
562 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
563 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
564 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
565 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
566 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
567 | p_dev->resource[0]->flags |= | ||
568 | pcmcia_io_cfg_data_width(io->flags); | ||
569 | p_dev->resource[0]->start = io->win[0].base; | ||
570 | p_dev->resource[0]->end = io->win[0].len; | ||
571 | if (io->nwin > 1) { | ||
572 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
573 | p_dev->resource[1]->start = io->win[1].base; | ||
574 | p_dev->resource[1]->end = io->win[1].len; | ||
575 | } | ||
576 | /* This reserves IO space but doesn't actually enable it */ | ||
577 | if (pcmcia_request_io(p_dev) != 0) | ||
578 | return -ENODEV; | ||
579 | } | ||
580 | 493 | ||
581 | /* If we got this far, we're cool! */ | 494 | return pcmcia_request_io(p_dev); |
582 | return 0; | ||
583 | } | 495 | } |
584 | 496 | ||
585 | static void dio700_config(struct pcmcia_device *link) | 497 | static void dio700_config(struct pcmcia_device *link) |
@@ -591,6 +503,9 @@ static void dio700_config(struct pcmcia_device *link) | |||
591 | 503 | ||
592 | dev_dbg(&link->dev, "dio700_config\n"); | 504 | dev_dbg(&link->dev, "dio700_config\n"); |
593 | 505 | ||
506 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO | | ||
507 | CONF_AUTO_SET_IO; | ||
508 | |||
594 | ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL); | 509 | ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL); |
595 | if (ret) { | 510 | if (ret) { |
596 | dev_warn(&link->dev, "no configuration found\n"); | 511 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -600,25 +515,10 @@ static void dio700_config(struct pcmcia_device *link) | |||
600 | if (!link->irq) | 515 | if (!link->irq) |
601 | goto failed; | 516 | goto failed; |
602 | 517 | ||
603 | /* | 518 | ret = pcmcia_enable_device(link); |
604 | This actually configures the PCMCIA socket -- setting up | ||
605 | the I/O windows and the interrupt mapping, and putting the | ||
606 | card and host interface into "Memory and IO" mode. | ||
607 | */ | ||
608 | ret = pcmcia_request_configuration(link, &link->conf); | ||
609 | if (ret != 0) | 519 | if (ret != 0) |
610 | goto failed; | 520 | goto failed; |
611 | 521 | ||
612 | /* Finally, report what we've done */ | ||
613 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
614 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
615 | printk(", irq %d", link->irq); | ||
616 | if (link->resource[0]) | ||
617 | printk(", io %pR", link->resource[0]); | ||
618 | if (link->resource[1]) | ||
619 | printk(" & %pR", link->resource[1]); | ||
620 | printk("\n"); | ||
621 | |||
622 | return; | 522 | return; |
623 | 523 | ||
624 | failed: | 524 | failed: |
@@ -634,18 +534,6 @@ static void dio700_release(struct pcmcia_device *link) | |||
634 | pcmcia_disable_device(link); | 534 | pcmcia_disable_device(link); |
635 | } /* dio700_release */ | 535 | } /* dio700_release */ |
636 | 536 | ||
637 | /*====================================================================== | ||
638 | |||
639 | The card status event handler. Mostly, this schedules other | ||
640 | stuff to run after an event is received. | ||
641 | |||
642 | When a CARD_REMOVAL event is received, we immediately set a | ||
643 | private flag to block future accesses to this device. All the | ||
644 | functions that actually access the device should check this flag | ||
645 | to make sure the card is still present. | ||
646 | |||
647 | ======================================================================*/ | ||
648 | |||
649 | static int dio700_cs_suspend(struct pcmcia_device *link) | 537 | static int dio700_cs_suspend(struct pcmcia_device *link) |
650 | { | 538 | { |
651 | struct local_info_t *local = link->priv; | 539 | struct local_info_t *local = link->priv; |
@@ -685,9 +573,7 @@ struct pcmcia_driver dio700_cs_driver = { | |||
685 | .resume = dio700_cs_resume, | 573 | .resume = dio700_cs_resume, |
686 | .id_table = dio700_cs_ids, | 574 | .id_table = dio700_cs_ids, |
687 | .owner = THIS_MODULE, | 575 | .owner = THIS_MODULE, |
688 | .drv = { | 576 | .name = "ni_daq_700", |
689 | .name = "ni_daq_700", | ||
690 | }, | ||
691 | }; | 577 | }; |
692 | 578 | ||
693 | static int __init init_dio700_cs(void) | 579 | static int __init init_dio700_cs(void) |
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 773ae2044e0e..c9c28584db67 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c | |||
@@ -48,7 +48,6 @@ the PCMCIA interface. | |||
48 | 48 | ||
49 | #include "8255.h" | 49 | #include "8255.h" |
50 | 50 | ||
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/cisreg.h> | 52 | #include <pcmcia/cisreg.h> |
54 | #include <pcmcia/ds.h> | 53 | #include <pcmcia/ds.h> |
@@ -187,47 +186,20 @@ static int dio24_detach(struct comedi_device *dev) | |||
187 | return 0; | 186 | return 0; |
188 | }; | 187 | }; |
189 | 188 | ||
190 | /* PCMCIA crap -- watch your words! */ | ||
191 | |||
192 | static void dio24_config(struct pcmcia_device *link); | 189 | static void dio24_config(struct pcmcia_device *link); |
193 | static void dio24_release(struct pcmcia_device *link); | 190 | static void dio24_release(struct pcmcia_device *link); |
194 | static int dio24_cs_suspend(struct pcmcia_device *p_dev); | 191 | static int dio24_cs_suspend(struct pcmcia_device *p_dev); |
195 | static int dio24_cs_resume(struct pcmcia_device *p_dev); | 192 | static int dio24_cs_resume(struct pcmcia_device *p_dev); |
196 | 193 | ||
197 | /* | ||
198 | The attach() and detach() entry points are used to create and destroy | ||
199 | "instances" of the driver, where each instance represents everything | ||
200 | needed to manage one actual PCMCIA card. | ||
201 | */ | ||
202 | |||
203 | static int dio24_cs_attach(struct pcmcia_device *); | 194 | static int dio24_cs_attach(struct pcmcia_device *); |
204 | static void dio24_cs_detach(struct pcmcia_device *); | 195 | static void dio24_cs_detach(struct pcmcia_device *); |
205 | 196 | ||
206 | /* | ||
207 | You'll also need to prototype all the functions that will actually | ||
208 | be used to talk to your device. See 'memory_cs' for a good example | ||
209 | of a fully self-sufficient driver; the other drivers rely more or | ||
210 | less on other parts of the kernel. | ||
211 | */ | ||
212 | |||
213 | struct local_info_t { | 197 | struct local_info_t { |
214 | struct pcmcia_device *link; | 198 | struct pcmcia_device *link; |
215 | int stop; | 199 | int stop; |
216 | struct bus_operations *bus; | 200 | struct bus_operations *bus; |
217 | }; | 201 | }; |
218 | 202 | ||
219 | /*====================================================================== | ||
220 | |||
221 | dio24_cs_attach() creates an "instance" of the driver, allocating | ||
222 | local data structures for one device. The device is registered | ||
223 | with Card Services. | ||
224 | |||
225 | The dev_link structure is initialized, but we don't actually | ||
226 | configure the card at this point -- we wait until we receive a | ||
227 | card insertion event. | ||
228 | |||
229 | ======================================================================*/ | ||
230 | |||
231 | static int dio24_cs_attach(struct pcmcia_device *link) | 203 | static int dio24_cs_attach(struct pcmcia_device *link) |
232 | { | 204 | { |
233 | struct local_info_t *local; | 205 | struct local_info_t *local; |
@@ -243,16 +215,6 @@ static int dio24_cs_attach(struct pcmcia_device *link) | |||
243 | local->link = link; | 215 | local->link = link; |
244 | link->priv = local; | 216 | link->priv = local; |
245 | 217 | ||
246 | /* | ||
247 | General socket configuration defaults can go here. In this | ||
248 | client, we assume very little, and rely on the CIS for almost | ||
249 | everything. In most clients, many details (i.e., number, sizes, | ||
250 | and attributes of IO windows) are fixed by the nature of the | ||
251 | device, and can be hard-wired here. | ||
252 | */ | ||
253 | link->conf.Attributes = 0; | ||
254 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
255 | |||
256 | pcmcia_cur_dev = link; | 218 | pcmcia_cur_dev = link; |
257 | 219 | ||
258 | dio24_config(link); | 220 | dio24_config(link); |
@@ -260,15 +222,6 @@ static int dio24_cs_attach(struct pcmcia_device *link) | |||
260 | return 0; | 222 | return 0; |
261 | } /* dio24_cs_attach */ | 223 | } /* dio24_cs_attach */ |
262 | 224 | ||
263 | /*====================================================================== | ||
264 | |||
265 | This deletes a driver "instance". The device is de-registered | ||
266 | with Card Services. If it has been released, all local data | ||
267 | structures are freed. Otherwise, the structures will be freed | ||
268 | when the device is released. | ||
269 | |||
270 | ======================================================================*/ | ||
271 | |||
272 | static void dio24_cs_detach(struct pcmcia_device *link) | 225 | static void dio24_cs_detach(struct pcmcia_device *link) |
273 | { | 226 | { |
274 | 227 | ||
@@ -284,54 +237,13 @@ static void dio24_cs_detach(struct pcmcia_device *link) | |||
284 | 237 | ||
285 | } /* dio24_cs_detach */ | 238 | } /* dio24_cs_detach */ |
286 | 239 | ||
287 | /*====================================================================== | ||
288 | |||
289 | dio24_config() is scheduled to run after a CARD_INSERTION event | ||
290 | is received, to configure the PCMCIA socket, and to make the | ||
291 | device available to the system. | ||
292 | |||
293 | ======================================================================*/ | ||
294 | |||
295 | static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, | 240 | static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, |
296 | cistpl_cftable_entry_t *cfg, | ||
297 | cistpl_cftable_entry_t *dflt, | ||
298 | unsigned int vcc, | ||
299 | void *priv_data) | 241 | void *priv_data) |
300 | { | 242 | { |
301 | if (cfg->index == 0) | 243 | if (p_dev->config_index == 0) |
302 | return -ENODEV; | 244 | return -EINVAL; |
303 | |||
304 | /* Does this card need audio output? */ | ||
305 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
306 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
307 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
308 | } | ||
309 | |||
310 | /* Do we need to allocate an interrupt? */ | ||
311 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
312 | |||
313 | /* IO window settings */ | ||
314 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
315 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
316 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
317 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
318 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
319 | p_dev->resource[0]->flags |= | ||
320 | pcmcia_io_cfg_data_width(io->flags); | ||
321 | p_dev->resource[0]->start = io->win[0].base; | ||
322 | p_dev->resource[0]->end = io->win[0].len; | ||
323 | if (io->nwin > 1) { | ||
324 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
325 | p_dev->resource[1]->start = io->win[1].base; | ||
326 | p_dev->resource[1]->end = io->win[1].len; | ||
327 | } | ||
328 | /* This reserves IO space but doesn't actually enable it */ | ||
329 | if (pcmcia_request_io(p_dev) != 0) | ||
330 | return -ENODEV; | ||
331 | } | ||
332 | 245 | ||
333 | /* If we got this far, we're cool! */ | 246 | return pcmcia_request_io(p_dev); |
334 | return 0; | ||
335 | } | 247 | } |
336 | 248 | ||
337 | static void dio24_config(struct pcmcia_device *link) | 249 | static void dio24_config(struct pcmcia_device *link) |
@@ -342,6 +254,9 @@ static void dio24_config(struct pcmcia_device *link) | |||
342 | 254 | ||
343 | dev_dbg(&link->dev, "dio24_config\n"); | 255 | dev_dbg(&link->dev, "dio24_config\n"); |
344 | 256 | ||
257 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO | | ||
258 | CONF_AUTO_SET_IO; | ||
259 | |||
345 | ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL); | 260 | ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL); |
346 | if (ret) { | 261 | if (ret) { |
347 | dev_warn(&link->dev, "no configuration found\n"); | 262 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -351,25 +266,10 @@ static void dio24_config(struct pcmcia_device *link) | |||
351 | if (!link->irq) | 266 | if (!link->irq) |
352 | goto failed; | 267 | goto failed; |
353 | 268 | ||
354 | /* | 269 | ret = pcmcia_enable_device(link); |
355 | This actually configures the PCMCIA socket -- setting up | ||
356 | the I/O windows and the interrupt mapping, and putting the | ||
357 | card and host interface into "Memory and IO" mode. | ||
358 | */ | ||
359 | ret = pcmcia_request_configuration(link, &link->conf); | ||
360 | if (ret) | 270 | if (ret) |
361 | goto failed; | 271 | goto failed; |
362 | 272 | ||
363 | /* Finally, report what we've done */ | ||
364 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
365 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
366 | printk(", irq %d", link->irq); | ||
367 | if (link->resource[0]) | ||
368 | printk(" & %pR", link->resource[0]); | ||
369 | if (link->resource[1]) | ||
370 | printk(" & %pR", link->resource[1]); | ||
371 | printk("\n"); | ||
372 | |||
373 | return; | 273 | return; |
374 | 274 | ||
375 | failed: | 275 | failed: |
@@ -385,18 +285,6 @@ static void dio24_release(struct pcmcia_device *link) | |||
385 | pcmcia_disable_device(link); | 285 | pcmcia_disable_device(link); |
386 | } /* dio24_release */ | 286 | } /* dio24_release */ |
387 | 287 | ||
388 | /*====================================================================== | ||
389 | |||
390 | The card status event handler. Mostly, this schedules other | ||
391 | stuff to run after an event is received. | ||
392 | |||
393 | When a CARD_REMOVAL event is received, we immediately set a | ||
394 | private flag to block future accesses to this device. All the | ||
395 | functions that actually access the device should check this flag | ||
396 | to make sure the card is still present. | ||
397 | |||
398 | ======================================================================*/ | ||
399 | |||
400 | static int dio24_cs_suspend(struct pcmcia_device *link) | 288 | static int dio24_cs_suspend(struct pcmcia_device *link) |
401 | { | 289 | { |
402 | struct local_info_t *local = link->priv; | 290 | struct local_info_t *local = link->priv; |
@@ -435,9 +323,7 @@ struct pcmcia_driver dio24_cs_driver = { | |||
435 | .resume = dio24_cs_resume, | 323 | .resume = dio24_cs_resume, |
436 | .id_table = dio24_cs_ids, | 324 | .id_table = dio24_cs_ids, |
437 | .owner = THIS_MODULE, | 325 | .owner = THIS_MODULE, |
438 | .drv = { | 326 | .name = "ni_daq_dio24", |
439 | .name = "ni_daq_dio24", | ||
440 | }, | ||
441 | }; | 327 | }; |
442 | 328 | ||
443 | static int __init init_dio24_cs(void) | 329 | static int __init init_dio24_cs(void) |
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 68c4ecbd93ae..6facbc8bf776 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c | |||
@@ -71,7 +71,6 @@ NI manuals: | |||
71 | #include "comedi_fc.h" | 71 | #include "comedi_fc.h" |
72 | #include "ni_labpc.h" | 72 | #include "ni_labpc.h" |
73 | 73 | ||
74 | #include <pcmcia/cs.h> | ||
75 | #include <pcmcia/cistpl.h> | 74 | #include <pcmcia/cistpl.h> |
76 | #include <pcmcia/cisreg.h> | 75 | #include <pcmcia/cisreg.h> |
77 | #include <pcmcia/ds.h> | 76 | #include <pcmcia/ds.h> |
@@ -153,59 +152,20 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) | |||
153 | return labpc_common_attach(dev, iobase, irq, 0); | 152 | return labpc_common_attach(dev, iobase, irq, 0); |
154 | } | 153 | } |
155 | 154 | ||
156 | /*====================================================================*/ | ||
157 | |||
158 | /* | ||
159 | The event() function is this driver's Card Services event handler. | ||
160 | It will be called by Card Services when an appropriate card status | ||
161 | event is received. The config() and release() entry points are | ||
162 | used to configure or release a socket, in response to card | ||
163 | insertion and ejection events. They are invoked from the dummy | ||
164 | event handler. | ||
165 | |||
166 | Kernel version 2.6.16 upwards uses suspend() and resume() functions | ||
167 | instead of an event() function. | ||
168 | */ | ||
169 | |||
170 | static void labpc_config(struct pcmcia_device *link); | 155 | static void labpc_config(struct pcmcia_device *link); |
171 | static void labpc_release(struct pcmcia_device *link); | 156 | static void labpc_release(struct pcmcia_device *link); |
172 | static int labpc_cs_suspend(struct pcmcia_device *p_dev); | 157 | static int labpc_cs_suspend(struct pcmcia_device *p_dev); |
173 | static int labpc_cs_resume(struct pcmcia_device *p_dev); | 158 | static int labpc_cs_resume(struct pcmcia_device *p_dev); |
174 | 159 | ||
175 | /* | ||
176 | The attach() and detach() entry points are used to create and destroy | ||
177 | "instances" of the driver, where each instance represents everything | ||
178 | needed to manage one actual PCMCIA card. | ||
179 | */ | ||
180 | |||
181 | static int labpc_cs_attach(struct pcmcia_device *); | 160 | static int labpc_cs_attach(struct pcmcia_device *); |
182 | static void labpc_cs_detach(struct pcmcia_device *); | 161 | static void labpc_cs_detach(struct pcmcia_device *); |
183 | 162 | ||
184 | /* | ||
185 | You'll also need to prototype all the functions that will actually | ||
186 | be used to talk to your device. See 'memory_cs' for a good example | ||
187 | of a fully self-sufficient driver; the other drivers rely more or | ||
188 | less on other parts of the kernel. | ||
189 | */ | ||
190 | |||
191 | struct local_info_t { | 163 | struct local_info_t { |
192 | struct pcmcia_device *link; | 164 | struct pcmcia_device *link; |
193 | int stop; | 165 | int stop; |
194 | struct bus_operations *bus; | 166 | struct bus_operations *bus; |
195 | }; | 167 | }; |
196 | 168 | ||
197 | /*====================================================================== | ||
198 | |||
199 | labpc_cs_attach() creates an "instance" of the driver, allocating | ||
200 | local data structures for one device. The device is registered | ||
201 | with Card Services. | ||
202 | |||
203 | The dev_link structure is initialized, but we don't actually | ||
204 | configure the card at this point -- we wait until we receive a | ||
205 | card insertion event. | ||
206 | |||
207 | ======================================================================*/ | ||
208 | |||
209 | static int labpc_cs_attach(struct pcmcia_device *link) | 169 | static int labpc_cs_attach(struct pcmcia_device *link) |
210 | { | 170 | { |
211 | struct local_info_t *local; | 171 | struct local_info_t *local; |
@@ -219,16 +179,6 @@ static int labpc_cs_attach(struct pcmcia_device *link) | |||
219 | local->link = link; | 179 | local->link = link; |
220 | link->priv = local; | 180 | link->priv = local; |
221 | 181 | ||
222 | /* | ||
223 | General socket configuration defaults can go here. In this | ||
224 | client, we assume very little, and rely on the CIS for almost | ||
225 | everything. In most clients, many details (i.e., number, sizes, | ||
226 | and attributes of IO windows) are fixed by the nature of the | ||
227 | device, and can be hard-wired here. | ||
228 | */ | ||
229 | link->conf.Attributes = 0; | ||
230 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
231 | |||
232 | pcmcia_cur_dev = link; | 182 | pcmcia_cur_dev = link; |
233 | 183 | ||
234 | labpc_config(link); | 184 | labpc_config(link); |
@@ -236,15 +186,6 @@ static int labpc_cs_attach(struct pcmcia_device *link) | |||
236 | return 0; | 186 | return 0; |
237 | } /* labpc_cs_attach */ | 187 | } /* labpc_cs_attach */ |
238 | 188 | ||
239 | /*====================================================================== | ||
240 | |||
241 | This deletes a driver "instance". The device is de-registered | ||
242 | with Card Services. If it has been released, all local data | ||
243 | structures are freed. Otherwise, the structures will be freed | ||
244 | when the device is released. | ||
245 | |||
246 | ======================================================================*/ | ||
247 | |||
248 | static void labpc_cs_detach(struct pcmcia_device *link) | 189 | static void labpc_cs_detach(struct pcmcia_device *link) |
249 | { | 190 | { |
250 | dev_dbg(&link->dev, "labpc_cs_detach\n"); | 191 | dev_dbg(&link->dev, "labpc_cs_detach\n"); |
@@ -263,54 +204,13 @@ static void labpc_cs_detach(struct pcmcia_device *link) | |||
263 | 204 | ||
264 | } /* labpc_cs_detach */ | 205 | } /* labpc_cs_detach */ |
265 | 206 | ||
266 | /*====================================================================== | ||
267 | |||
268 | labpc_config() is scheduled to run after a CARD_INSERTION event | ||
269 | is received, to configure the PCMCIA socket, and to make the | ||
270 | device available to the system. | ||
271 | |||
272 | ======================================================================*/ | ||
273 | |||
274 | static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, | 207 | static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, |
275 | cistpl_cftable_entry_t *cfg, | ||
276 | cistpl_cftable_entry_t *dflt, | ||
277 | unsigned int vcc, | ||
278 | void *priv_data) | 208 | void *priv_data) |
279 | { | 209 | { |
280 | if (cfg->index == 0) | 210 | if (p_dev->config_index == 0) |
281 | return -ENODEV; | 211 | return -EINVAL; |
282 | |||
283 | /* Does this card need audio output? */ | ||
284 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
285 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
286 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
287 | } | ||
288 | |||
289 | /* Do we need to allocate an interrupt? */ | ||
290 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; | ||
291 | |||
292 | /* IO window settings */ | ||
293 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
294 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
295 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
296 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
297 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
298 | p_dev->resource[0]->flags |= | ||
299 | pcmcia_io_cfg_data_width(io->flags); | ||
300 | p_dev->resource[0]->start = io->win[0].base; | ||
301 | p_dev->resource[0]->end = io->win[0].len; | ||
302 | if (io->nwin > 1) { | ||
303 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
304 | p_dev->resource[1]->start = io->win[1].base; | ||
305 | p_dev->resource[1]->end = io->win[1].len; | ||
306 | } | ||
307 | /* This reserves IO space but doesn't actually enable it */ | ||
308 | if (pcmcia_request_io(p_dev) != 0) | ||
309 | return -ENODEV; | ||
310 | } | ||
311 | 212 | ||
312 | /* If we got this far, we're cool! */ | 213 | return pcmcia_request_io(p_dev); |
313 | return 0; | ||
314 | } | 214 | } |
315 | 215 | ||
316 | 216 | ||
@@ -320,6 +220,9 @@ static void labpc_config(struct pcmcia_device *link) | |||
320 | 220 | ||
321 | dev_dbg(&link->dev, "labpc_config\n"); | 221 | dev_dbg(&link->dev, "labpc_config\n"); |
322 | 222 | ||
223 | link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ | | ||
224 | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; | ||
225 | |||
323 | ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL); | 226 | ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL); |
324 | if (ret) { | 227 | if (ret) { |
325 | dev_warn(&link->dev, "no configuration found\n"); | 228 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -329,25 +232,10 @@ static void labpc_config(struct pcmcia_device *link) | |||
329 | if (!link->irq) | 232 | if (!link->irq) |
330 | goto failed; | 233 | goto failed; |
331 | 234 | ||
332 | /* | 235 | ret = pcmcia_enable_device(link); |
333 | This actually configures the PCMCIA socket -- setting up | ||
334 | the I/O windows and the interrupt mapping, and putting the | ||
335 | card and host interface into "Memory and IO" mode. | ||
336 | */ | ||
337 | ret = pcmcia_request_configuration(link, &link->conf); | ||
338 | if (ret) | 236 | if (ret) |
339 | goto failed; | 237 | goto failed; |
340 | 238 | ||
341 | /* Finally, report what we've done */ | ||
342 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
343 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
344 | printk(", irq %d", link->irq); | ||
345 | if (link->resource[0]) | ||
346 | printk(" & %pR", link->resource[0]); | ||
347 | if (link->resource[1]) | ||
348 | printk(" & %pR", link->resource[1]); | ||
349 | printk("\n"); | ||
350 | |||
351 | return; | 239 | return; |
352 | 240 | ||
353 | failed: | 241 | failed: |
@@ -362,18 +250,6 @@ static void labpc_release(struct pcmcia_device *link) | |||
362 | pcmcia_disable_device(link); | 250 | pcmcia_disable_device(link); |
363 | } /* labpc_release */ | 251 | } /* labpc_release */ |
364 | 252 | ||
365 | /*====================================================================== | ||
366 | |||
367 | The card status event handler. Mostly, this schedules other | ||
368 | stuff to run after an event is received. | ||
369 | |||
370 | When a CARD_REMOVAL event is received, we immediately set a | ||
371 | private flag to block future accesses to this device. All the | ||
372 | functions that actually access the device should check this flag | ||
373 | to make sure the card is still present. | ||
374 | |||
375 | ======================================================================*/ | ||
376 | |||
377 | static int labpc_cs_suspend(struct pcmcia_device *link) | 253 | static int labpc_cs_suspend(struct pcmcia_device *link) |
378 | { | 254 | { |
379 | struct local_info_t *local = link->priv; | 255 | struct local_info_t *local = link->priv; |
@@ -391,8 +267,6 @@ static int labpc_cs_resume(struct pcmcia_device *link) | |||
391 | return 0; | 267 | return 0; |
392 | } /* labpc_cs_resume */ | 268 | } /* labpc_cs_resume */ |
393 | 269 | ||
394 | /*====================================================================*/ | ||
395 | |||
396 | static struct pcmcia_device_id labpc_cs_ids[] = { | 270 | static struct pcmcia_device_id labpc_cs_ids[] = { |
397 | /* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */ | 271 | /* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */ |
398 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103), /* daqcard-1200 */ | 272 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103), /* daqcard-1200 */ |
@@ -411,9 +285,7 @@ struct pcmcia_driver labpc_cs_driver = { | |||
411 | .resume = labpc_cs_resume, | 285 | .resume = labpc_cs_resume, |
412 | .id_table = labpc_cs_ids, | 286 | .id_table = labpc_cs_ids, |
413 | .owner = THIS_MODULE, | 287 | .owner = THIS_MODULE, |
414 | .drv = { | 288 | .name = "daqcard-1200", |
415 | .name = "daqcard-1200", | ||
416 | }, | ||
417 | }; | 289 | }; |
418 | 290 | ||
419 | static int __init init_labpc_cs(void) | 291 | static int __init init_labpc_cs(void) |
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 1f2426352eb5..49563273f605 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c | |||
@@ -48,7 +48,6 @@ See the notes in the ni_atmio.o driver. | |||
48 | #include "ni_stc.h" | 48 | #include "ni_stc.h" |
49 | #include "8255.h" | 49 | #include "8255.h" |
50 | 50 | ||
51 | #include <pcmcia/cs.h> | ||
52 | #include <pcmcia/cistpl.h> | 51 | #include <pcmcia/cistpl.h> |
53 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
54 | 53 | ||
@@ -263,11 +262,6 @@ static struct pcmcia_device *cur_dev = NULL; | |||
263 | 262 | ||
264 | static int cs_attach(struct pcmcia_device *link) | 263 | static int cs_attach(struct pcmcia_device *link) |
265 | { | 264 | { |
266 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; | ||
267 | link->resource[0]->end = 16; | ||
268 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
269 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
270 | |||
271 | cur_dev = link; | 265 | cur_dev = link; |
272 | 266 | ||
273 | mio_cs_config(link); | 267 | mio_cs_config(link); |
@@ -301,16 +295,12 @@ static int mio_cs_resume(struct pcmcia_device *link) | |||
301 | } | 295 | } |
302 | 296 | ||
303 | 297 | ||
304 | static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, | 298 | static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) |
305 | cistpl_cftable_entry_t *cfg, | ||
306 | cistpl_cftable_entry_t *dflt, | ||
307 | unsigned int vcc, | ||
308 | void *priv_data) | ||
309 | { | 299 | { |
310 | int base, ret; | 300 | int base, ret; |
311 | 301 | ||
312 | p_dev->resource[0]->end = cfg->io.win[0].len; | 302 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
313 | p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK; | 303 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; |
314 | 304 | ||
315 | for (base = 0x000; base < 0x400; base += 0x20) { | 305 | for (base = 0x000; base < 0x400; base += 0x20) { |
316 | p_dev->resource[0]->start = base; | 306 | p_dev->resource[0]->start = base; |
@@ -327,6 +317,7 @@ static void mio_cs_config(struct pcmcia_device *link) | |||
327 | int ret; | 317 | int ret; |
328 | 318 | ||
329 | DPRINTK("mio_cs_config(link=%p)\n", link); | 319 | DPRINTK("mio_cs_config(link=%p)\n", link); |
320 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
330 | 321 | ||
331 | ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL); | 322 | ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL); |
332 | if (ret) { | 323 | if (ret) { |
@@ -337,7 +328,7 @@ static void mio_cs_config(struct pcmcia_device *link) | |||
337 | if (!link->irq) | 328 | if (!link->irq) |
338 | dev_info(&link->dev, "no IRQ available\n"); | 329 | dev_info(&link->dev, "no IRQ available\n"); |
339 | 330 | ||
340 | ret = pcmcia_request_configuration(link, &link->conf); | 331 | ret = pcmcia_enable_device(link); |
341 | } | 332 | } |
342 | 333 | ||
343 | static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) | 334 | static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it) |
@@ -446,9 +437,7 @@ struct pcmcia_driver ni_mio_cs_driver = { | |||
446 | .resume = &mio_cs_resume, | 437 | .resume = &mio_cs_resume, |
447 | .id_table = ni_mio_cs_ids, | 438 | .id_table = ni_mio_cs_ids, |
448 | .owner = THIS_MODULE, | 439 | .owner = THIS_MODULE, |
449 | .drv = { | 440 | .name = "ni_mio_cs", |
450 | .name = "ni_mio_cs", | ||
451 | }, | ||
452 | }; | 441 | }; |
453 | 442 | ||
454 | int init_module(void) | 443 | int init_module(void) |
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index bf489d7f4990..ebba9bb47777 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c | |||
@@ -50,7 +50,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 | |||
50 | #include "../comedidev.h" | 50 | #include "../comedidev.h" |
51 | #include <linux/semaphore.h> | 51 | #include <linux/semaphore.h> |
52 | 52 | ||
53 | #include <pcmcia/cs.h> | ||
54 | #include <pcmcia/cistpl.h> | 53 | #include <pcmcia/cistpl.h> |
55 | #include <pcmcia/cisreg.h> | 54 | #include <pcmcia/cisreg.h> |
56 | #include <pcmcia/ds.h> | 55 | #include <pcmcia/ds.h> |
@@ -969,43 +968,14 @@ static int daqp_detach(struct comedi_device *dev) | |||
969 | 968 | ||
970 | ======================================================================*/ | 969 | ======================================================================*/ |
971 | 970 | ||
972 | /* | ||
973 | The event() function is this driver's Card Services event handler. | ||
974 | It will be called by Card Services when an appropriate card status | ||
975 | event is received. The config() and release() entry points are | ||
976 | used to configure or release a socket, in response to card | ||
977 | insertion and ejection events. | ||
978 | |||
979 | Kernel version 2.6.16 upwards uses suspend() and resume() functions | ||
980 | instead of an event() function. | ||
981 | */ | ||
982 | |||
983 | static void daqp_cs_config(struct pcmcia_device *link); | 971 | static void daqp_cs_config(struct pcmcia_device *link); |
984 | static void daqp_cs_release(struct pcmcia_device *link); | 972 | static void daqp_cs_release(struct pcmcia_device *link); |
985 | static int daqp_cs_suspend(struct pcmcia_device *p_dev); | 973 | static int daqp_cs_suspend(struct pcmcia_device *p_dev); |
986 | static int daqp_cs_resume(struct pcmcia_device *p_dev); | 974 | static int daqp_cs_resume(struct pcmcia_device *p_dev); |
987 | 975 | ||
988 | /* | ||
989 | The attach() and detach() entry points are used to create and destroy | ||
990 | "instances" of the driver, where each instance represents everything | ||
991 | needed to manage one actual PCMCIA card. | ||
992 | */ | ||
993 | |||
994 | static int daqp_cs_attach(struct pcmcia_device *); | 976 | static int daqp_cs_attach(struct pcmcia_device *); |
995 | static void daqp_cs_detach(struct pcmcia_device *); | 977 | static void daqp_cs_detach(struct pcmcia_device *); |
996 | 978 | ||
997 | /*====================================================================== | ||
998 | |||
999 | daqp_cs_attach() creates an "instance" of the driver, allocating | ||
1000 | local data structures for one device. The device is registered | ||
1001 | with Card Services. | ||
1002 | |||
1003 | The dev_link structure is initialized, but we don't actually | ||
1004 | configure the card at this point -- we wait until we receive a | ||
1005 | card insertion event. | ||
1006 | |||
1007 | ======================================================================*/ | ||
1008 | |||
1009 | static int daqp_cs_attach(struct pcmcia_device *link) | 979 | static int daqp_cs_attach(struct pcmcia_device *link) |
1010 | { | 980 | { |
1011 | struct local_info_t *local; | 981 | struct local_info_t *local; |
@@ -1031,30 +1001,11 @@ static int daqp_cs_attach(struct pcmcia_device *link) | |||
1031 | local->link = link; | 1001 | local->link = link; |
1032 | link->priv = local; | 1002 | link->priv = local; |
1033 | 1003 | ||
1034 | /* | ||
1035 | General socket configuration defaults can go here. In this | ||
1036 | client, we assume very little, and rely on the CIS for almost | ||
1037 | everything. In most clients, many details (i.e., number, sizes, | ||
1038 | and attributes of IO windows) are fixed by the nature of the | ||
1039 | device, and can be hard-wired here. | ||
1040 | */ | ||
1041 | link->conf.Attributes = 0; | ||
1042 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1043 | |||
1044 | daqp_cs_config(link); | 1004 | daqp_cs_config(link); |
1045 | 1005 | ||
1046 | return 0; | 1006 | return 0; |
1047 | } /* daqp_cs_attach */ | 1007 | } /* daqp_cs_attach */ |
1048 | 1008 | ||
1049 | /*====================================================================== | ||
1050 | |||
1051 | This deletes a driver "instance". The device is de-registered | ||
1052 | with Card Services. If it has been released, all local data | ||
1053 | structures are freed. Otherwise, the structures will be freed | ||
1054 | when the device is released. | ||
1055 | |||
1056 | ======================================================================*/ | ||
1057 | |||
1058 | static void daqp_cs_detach(struct pcmcia_device *link) | 1009 | static void daqp_cs_detach(struct pcmcia_device *link) |
1059 | { | 1010 | { |
1060 | struct local_info_t *dev = link->priv; | 1011 | struct local_info_t *dev = link->priv; |
@@ -1070,45 +1021,11 @@ static void daqp_cs_detach(struct pcmcia_device *link) | |||
1070 | 1021 | ||
1071 | } /* daqp_cs_detach */ | 1022 | } /* daqp_cs_detach */ |
1072 | 1023 | ||
1073 | /*====================================================================== | 1024 | static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) |
1074 | |||
1075 | daqp_cs_config() is scheduled to run after a CARD_INSERTION event | ||
1076 | is received, to configure the PCMCIA socket, and to make the | ||
1077 | device available to the system. | ||
1078 | |||
1079 | ======================================================================*/ | ||
1080 | |||
1081 | |||
1082 | static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, | ||
1083 | cistpl_cftable_entry_t *cfg, | ||
1084 | cistpl_cftable_entry_t *dflt, | ||
1085 | unsigned int vcc, | ||
1086 | void *priv_data) | ||
1087 | { | 1025 | { |
1088 | if (cfg->index == 0) | 1026 | if (p_dev->config_index == 0) |
1089 | return -ENODEV; | 1027 | return -EINVAL; |
1090 | 1028 | ||
1091 | /* Do we need to allocate an interrupt? */ | ||
1092 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
1093 | |||
1094 | /* IO window settings */ | ||
1095 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
1096 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
1097 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
1098 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
1099 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; | ||
1100 | p_dev->resource[0]->flags |= | ||
1101 | pcmcia_io_cfg_data_width(io->flags); | ||
1102 | p_dev->resource[0]->start = io->win[0].base; | ||
1103 | p_dev->resource[0]->end = io->win[0].len; | ||
1104 | if (io->nwin > 1) { | ||
1105 | p_dev->resource[1]->flags = p_dev->resource[0]->flags; | ||
1106 | p_dev->resource[1]->start = io->win[1].base; | ||
1107 | p_dev->resource[1]->end = io->win[1].len; | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | /* This reserves IO space but doesn't actually enable it */ | ||
1112 | return pcmcia_request_io(p_dev); | 1029 | return pcmcia_request_io(p_dev); |
1113 | } | 1030 | } |
1114 | 1031 | ||
@@ -1118,6 +1035,8 @@ static void daqp_cs_config(struct pcmcia_device *link) | |||
1118 | 1035 | ||
1119 | dev_dbg(&link->dev, "daqp_cs_config\n"); | 1036 | dev_dbg(&link->dev, "daqp_cs_config\n"); |
1120 | 1037 | ||
1038 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | ||
1039 | |||
1121 | ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL); | 1040 | ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL); |
1122 | if (ret) { | 1041 | if (ret) { |
1123 | dev_warn(&link->dev, "no configuration found\n"); | 1042 | dev_warn(&link->dev, "no configuration found\n"); |
@@ -1128,25 +1047,10 @@ static void daqp_cs_config(struct pcmcia_device *link) | |||
1128 | if (ret) | 1047 | if (ret) |
1129 | goto failed; | 1048 | goto failed; |
1130 | 1049 | ||
1131 | /* | 1050 | ret = pcmcia_enable_device(link); |
1132 | This actually configures the PCMCIA socket -- setting up | ||
1133 | the I/O windows and the interrupt mapping, and putting the | ||
1134 | card and host interface into "Memory and IO" mode. | ||
1135 | */ | ||
1136 | ret = pcmcia_request_configuration(link, &link->conf); | ||
1137 | if (ret) | 1051 | if (ret) |
1138 | goto failed; | 1052 | goto failed; |
1139 | 1053 | ||
1140 | /* Finally, report what we've done */ | ||
1141 | dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex); | ||
1142 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | ||
1143 | printk(", irq %u", link->irq); | ||
1144 | if (link->resource[0]) | ||
1145 | printk(" & %pR", link->resource[0]); | ||
1146 | if (link->resource[1]) | ||
1147 | printk(" & %pR", link->resource[1]); | ||
1148 | printk("\n"); | ||
1149 | |||
1150 | return; | 1054 | return; |
1151 | 1055 | ||
1152 | failed: | 1056 | failed: |
@@ -1161,18 +1065,6 @@ static void daqp_cs_release(struct pcmcia_device *link) | |||
1161 | pcmcia_disable_device(link); | 1065 | pcmcia_disable_device(link); |
1162 | } /* daqp_cs_release */ | 1066 | } /* daqp_cs_release */ |
1163 | 1067 | ||
1164 | /*====================================================================== | ||
1165 | |||
1166 | The card status event handler. Mostly, this schedules other | ||
1167 | stuff to run after an event is received. | ||
1168 | |||
1169 | When a CARD_REMOVAL event is received, we immediately set a | ||
1170 | private flag to block future accesses to this device. All the | ||
1171 | functions that actually access the device should check this flag | ||
1172 | to make sure the card is still present. | ||
1173 | |||
1174 | ======================================================================*/ | ||
1175 | |||
1176 | static int daqp_cs_suspend(struct pcmcia_device *link) | 1068 | static int daqp_cs_suspend(struct pcmcia_device *link) |
1177 | { | 1069 | { |
1178 | struct local_info_t *local = link->priv; | 1070 | struct local_info_t *local = link->priv; |
@@ -1212,9 +1104,7 @@ static struct pcmcia_driver daqp_cs_driver = { | |||
1212 | .resume = daqp_cs_resume, | 1104 | .resume = daqp_cs_resume, |
1213 | .id_table = daqp_cs_id_table, | 1105 | .id_table = daqp_cs_id_table, |
1214 | .owner = THIS_MODULE, | 1106 | .owner = THIS_MODULE, |
1215 | .drv = { | 1107 | .name = "quatech_daqp_cs", |
1216 | .name = "quatech_daqp_cs", | ||
1217 | }, | ||
1218 | }; | 1108 | }; |
1219 | 1109 | ||
1220 | int __init init_module(void) | 1110 | int __init init_module(void) |
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c index 19c335458653..6555891e149c 100644 --- a/drivers/staging/wlags49_h2/wl_cs.c +++ b/drivers/staging/wlags49_h2/wl_cs.c | |||
@@ -83,7 +83,6 @@ | |||
83 | #include <linux/if_arp.h> | 83 | #include <linux/if_arp.h> |
84 | #include <linux/ioport.h> | 84 | #include <linux/ioport.h> |
85 | 85 | ||
86 | #include <pcmcia/cs.h> | ||
87 | #include <pcmcia/cistpl.h> | 86 | #include <pcmcia/cistpl.h> |
88 | #include <pcmcia/cisreg.h> | 87 | #include <pcmcia/cisreg.h> |
89 | #include <pcmcia/ciscode.h> | 88 | #include <pcmcia/ciscode.h> |
@@ -147,10 +146,9 @@ static int wl_adapter_attach(struct pcmcia_device *link) | |||
147 | 146 | ||
148 | link->resource[0]->end = HCF_NUM_IO_PORTS; | 147 | link->resource[0]->end = HCF_NUM_IO_PORTS; |
149 | link->resource[0]->flags= IO_DATA_PATH_WIDTH_16; | 148 | link->resource[0]->flags= IO_DATA_PATH_WIDTH_16; |
150 | link->conf.Attributes = CONF_ENABLE_IRQ; | 149 | link->config_flags |= CONF_ENABLE_IRQ; |
151 | link->conf.IntType = INT_MEMORY_AND_IO; | 150 | link->config_index = 5; |
152 | link->conf.ConfigIndex = 5; | 151 | link->config_regs = PRESENT_OPTION; |
153 | link->conf.Present = PRESENT_OPTION; | ||
154 | 152 | ||
155 | link->priv = dev; | 153 | link->priv = dev; |
156 | lp = wl_priv(dev); | 154 | lp = wl_priv(dev); |
@@ -165,27 +163,6 @@ static int wl_adapter_attach(struct pcmcia_device *link) | |||
165 | 163 | ||
166 | 164 | ||
167 | 165 | ||
168 | /******************************************************************************* | ||
169 | * wl_adapter_detach() | ||
170 | ******************************************************************************* | ||
171 | * | ||
172 | * DESCRIPTION: | ||
173 | * | ||
174 | * This deletes a driver "instance". The device is de-registered with Card | ||
175 | * Services. If it has been released, then the net device is unregistered, and | ||
176 | * all local data structures are freed. Otherwise, the structures will be | ||
177 | * freed when the device is released. | ||
178 | * | ||
179 | * PARAMETERS: | ||
180 | * | ||
181 | * link - pointer to the dev_link_t structure representing the device to | ||
182 | * detach | ||
183 | * | ||
184 | * RETURNS: | ||
185 | * | ||
186 | * N/A | ||
187 | * | ||
188 | ******************************************************************************/ | ||
189 | static void wl_adapter_detach(struct pcmcia_device *link) | 166 | static void wl_adapter_detach(struct pcmcia_device *link) |
190 | { | 167 | { |
191 | struct net_device *dev = link->priv; | 168 | struct net_device *dev = link->priv; |
@@ -209,26 +186,6 @@ static void wl_adapter_detach(struct pcmcia_device *link) | |||
209 | /*============================================================================*/ | 186 | /*============================================================================*/ |
210 | 187 | ||
211 | 188 | ||
212 | /******************************************************************************* | ||
213 | * wl_adapter_release() | ||
214 | ******************************************************************************* | ||
215 | * | ||
216 | * DESCRIPTION: | ||
217 | * | ||
218 | * After a card is removed, this routine will release the PCMCIA | ||
219 | * configuration. If the device is still open, this will be postponed until it | ||
220 | * is closed. | ||
221 | * | ||
222 | * PARAMETERS: | ||
223 | * | ||
224 | * arg - a u_long representing a pointer to a dev_link_t structure for the | ||
225 | * device to be released. | ||
226 | * | ||
227 | * RETURNS: | ||
228 | * | ||
229 | * N/A | ||
230 | * | ||
231 | ******************************************************************************/ | ||
232 | void wl_adapter_release(struct pcmcia_device *link) | 189 | void wl_adapter_release(struct pcmcia_device *link) |
233 | { | 190 | { |
234 | DBG_FUNC("wl_adapter_release"); | 191 | DBG_FUNC("wl_adapter_release"); |
@@ -268,26 +225,6 @@ static int wl_adapter_resume(struct pcmcia_device *link) | |||
268 | return 0; | 225 | return 0; |
269 | } /* wl_adapter_resume */ | 226 | } /* wl_adapter_resume */ |
270 | 227 | ||
271 | /******************************************************************************* | ||
272 | * wl_adapter_insert() | ||
273 | ******************************************************************************* | ||
274 | * | ||
275 | * DESCRIPTION: | ||
276 | * | ||
277 | * wl_adapter_insert() is scheduled to run after a CARD_INSERTION event is | ||
278 | * received, to configure the PCMCIA socket, and to make the ethernet device | ||
279 | * available to the system. | ||
280 | * | ||
281 | * PARAMETERS: | ||
282 | * | ||
283 | * link - pointer to the dev_link_t structure representing the device to | ||
284 | * insert | ||
285 | * | ||
286 | * RETURNS: | ||
287 | * | ||
288 | * N/A | ||
289 | * | ||
290 | ******************************************************************************/ | ||
291 | void wl_adapter_insert(struct pcmcia_device *link) | 228 | void wl_adapter_insert(struct pcmcia_device *link) |
292 | { | 229 | { |
293 | struct net_device *dev; | 230 | struct net_device *dev; |
@@ -302,7 +239,7 @@ void wl_adapter_insert(struct pcmcia_device *link) | |||
302 | dev = link->priv; | 239 | dev = link->priv; |
303 | 240 | ||
304 | /* Do we need to allocate an interrupt? */ | 241 | /* Do we need to allocate an interrupt? */ |
305 | link->conf.Attributes |= CONF_ENABLE_IRQ; | 242 | link->config_flags |= CONF_ENABLE_IRQ; |
306 | link->io_lines = 6; | 243 | link->io_lines = 6; |
307 | 244 | ||
308 | ret = pcmcia_request_io(link); | 245 | ret = pcmcia_request_io(link); |
@@ -313,7 +250,7 @@ void wl_adapter_insert(struct pcmcia_device *link) | |||
313 | if (ret != 0) | 250 | if (ret != 0) |
314 | goto failed; | 251 | goto failed; |
315 | 252 | ||
316 | ret = pcmcia_request_configuration(link, &link->conf); | 253 | ret = pcmcia_enable_device(link); |
317 | if (ret != 0) | 254 | if (ret != 0) |
318 | goto failed; | 255 | goto failed; |
319 | 256 | ||
@@ -457,9 +394,7 @@ MODULE_DEVICE_TABLE(pcmcia, wl_adapter_ids); | |||
457 | 394 | ||
458 | static struct pcmcia_driver wlags49_driver = { | 395 | static struct pcmcia_driver wlags49_driver = { |
459 | .owner = THIS_MODULE, | 396 | .owner = THIS_MODULE, |
460 | .drv = { | 397 | .name = DRIVER_NAME, |
461 | .name = DRIVER_NAME, | ||
462 | }, | ||
463 | .probe = wl_adapter_attach, | 398 | .probe = wl_adapter_attach, |
464 | .remove = wl_adapter_detach, | 399 | .remove = wl_adapter_detach, |
465 | .id_table = wl_adapter_ids, | 400 | .id_table = wl_adapter_ids, |
diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h index 02f0a20e178a..cd129b3ee6c0 100644 --- a/drivers/staging/wlags49_h2/wl_internal.h +++ b/drivers/staging/wlags49_h2/wl_internal.h | |||
@@ -69,7 +69,6 @@ | |||
69 | ******************************************************************************/ | 69 | ******************************************************************************/ |
70 | #include <linux/version.h> | 70 | #include <linux/version.h> |
71 | #ifdef BUS_PCMCIA | 71 | #ifdef BUS_PCMCIA |
72 | #include <pcmcia/cs.h> | ||
73 | #include <pcmcia/cistpl.h> | 72 | #include <pcmcia/cistpl.h> |
74 | #include <pcmcia/cisreg.h> | 73 | #include <pcmcia/cisreg.h> |
75 | #include <pcmcia/ciscode.h> | 74 | #include <pcmcia/ciscode.h> |
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c index 88d0d472142f..8e3536acbf46 100644 --- a/drivers/staging/wlags49_h2/wl_main.c +++ b/drivers/staging/wlags49_h2/wl_main.c | |||
@@ -414,25 +414,6 @@ extern memimage fw_image; // firmware image to be downloaded | |||
414 | #endif /* HCF_STA */ | 414 | #endif /* HCF_STA */ |
415 | 415 | ||
416 | 416 | ||
417 | /******************************************************************************* | ||
418 | * wl_insert() | ||
419 | ******************************************************************************* | ||
420 | * | ||
421 | * DESCRIPTION: | ||
422 | * | ||
423 | * wl_insert() is scheduled to run after a CARD_INSERTION event is | ||
424 | * received, to configure the PCMCIA socket, and to make the ethernet device | ||
425 | * available to the system. | ||
426 | * | ||
427 | * PARAMETERS: | ||
428 | * | ||
429 | * dev - a pointer to the net_device struct of the wireless device | ||
430 | * | ||
431 | * RETURNS: | ||
432 | * | ||
433 | * TRUE or FALSE | ||
434 | * | ||
435 | ******************************************************************************/ | ||
436 | int wl_insert( struct net_device *dev ) | 417 | int wl_insert( struct net_device *dev ) |
437 | { | 418 | { |
438 | int result = 0; | 419 | int result = 0; |
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index a1900e502518..d005b9eeebbc 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/errno.h> /* error codes */ | 8 | #include <linux/errno.h> /* error codes */ |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | 10 | ||
11 | #include <pcmcia/cs.h> | ||
12 | #include <pcmcia/cistpl.h> | 11 | #include <pcmcia/cistpl.h> |
13 | #include <pcmcia/ds.h> | 12 | #include <pcmcia/ds.h> |
14 | 13 | ||
@@ -32,9 +31,6 @@ static int ixj_probe(struct pcmcia_device *p_dev) | |||
32 | { | 31 | { |
33 | dev_dbg(&p_dev->dev, "ixj_attach()\n"); | 32 | dev_dbg(&p_dev->dev, "ixj_attach()\n"); |
34 | /* Create new ixj device */ | 33 | /* Create new ixj device */ |
35 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
36 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; | ||
37 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | ||
38 | p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL); | 34 | p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL); |
39 | if (!p_dev->priv) { | 35 | if (!p_dev->priv) { |
40 | return -ENOMEM; | 36 | return -ENOMEM; |
@@ -111,40 +107,31 @@ failed: | |||
111 | return; | 107 | return; |
112 | } | 108 | } |
113 | 109 | ||
114 | static int ixj_config_check(struct pcmcia_device *p_dev, | 110 | static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data) |
115 | cistpl_cftable_entry_t *cfg, | ||
116 | cistpl_cftable_entry_t *dflt, | ||
117 | unsigned int vcc, | ||
118 | void *priv_data) | ||
119 | { | 111 | { |
120 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | 112 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
121 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | 113 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
122 | p_dev->resource[0]->start = io->win[0].base; | 114 | p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; |
123 | p_dev->resource[0]->end = io->win[0].len; | 115 | p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; |
124 | p_dev->io_lines = 3; | 116 | p_dev->io_lines = 3; |
125 | if (io->nwin == 2) { | 117 | |
126 | p_dev->resource[1]->start = io->win[1].base; | 118 | return pcmcia_request_io(p_dev); |
127 | p_dev->resource[1]->end = io->win[1].len; | ||
128 | } | ||
129 | if (!pcmcia_request_io(p_dev)) | ||
130 | return 0; | ||
131 | } | ||
132 | return -ENODEV; | ||
133 | } | 119 | } |
134 | 120 | ||
135 | static int ixj_config(struct pcmcia_device * link) | 121 | static int ixj_config(struct pcmcia_device * link) |
136 | { | 122 | { |
137 | IXJ *j; | 123 | IXJ *j; |
138 | ixj_info_t *info; | 124 | ixj_info_t *info; |
139 | cistpl_cftable_entry_t dflt = { 0 }; | ||
140 | 125 | ||
141 | info = link->priv; | 126 | info = link->priv; |
142 | dev_dbg(&link->dev, "ixj_config\n"); | 127 | dev_dbg(&link->dev, "ixj_config\n"); |
143 | 128 | ||
144 | if (pcmcia_loop_config(link, ixj_config_check, &dflt)) | 129 | link->config_flags = CONF_AUTO_SET_IO; |
130 | |||
131 | if (pcmcia_loop_config(link, ixj_config_check, NULL)) | ||
145 | goto failed; | 132 | goto failed; |
146 | 133 | ||
147 | if (pcmcia_request_configuration(link, &link->conf)) | 134 | if (pcmcia_enable_device(link)) |
148 | goto failed; | 135 | goto failed; |
149 | 136 | ||
150 | /* | 137 | /* |
@@ -178,9 +165,7 @@ MODULE_DEVICE_TABLE(pcmcia, ixj_ids); | |||
178 | 165 | ||
179 | static struct pcmcia_driver ixj_driver = { | 166 | static struct pcmcia_driver ixj_driver = { |
180 | .owner = THIS_MODULE, | 167 | .owner = THIS_MODULE, |
181 | .drv = { | 168 | .name = "ixj_cs", |
182 | .name = "ixj_cs", | ||
183 | }, | ||
184 | .probe = ixj_probe, | 169 | .probe = ixj_probe, |
185 | .remove = ixj_detach, | 170 | .remove = ixj_detach, |
186 | .id_table = ixj_ids, | 171 | .id_table = ixj_ids, |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 418163894775..afef7b0a4195 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <mach/ohci.h> | 26 | #include <mach/ohci.h> |
27 | #include <mach/pxa3xx-u2d.h> | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * UHC: USB Host Controller (OHCI-like) register definitions | 30 | * UHC: USB Host Controller (OHCI-like) register definitions |
@@ -235,6 +236,9 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev) | |||
235 | if (retval < 0) | 236 | if (retval < 0) |
236 | return retval; | 237 | return retval; |
237 | 238 | ||
239 | if (cpu_is_pxa3xx()) | ||
240 | pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self); | ||
241 | |||
238 | uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE; | 242 | uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE; |
239 | __raw_writel(uhchr, ohci->mmio_base + UHCHR); | 243 | __raw_writel(uhchr, ohci->mmio_base + UHCHR); |
240 | __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE); | 244 | __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE); |
@@ -251,6 +255,9 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) | |||
251 | 255 | ||
252 | inf = dev->platform_data; | 256 | inf = dev->platform_data; |
253 | 257 | ||
258 | if (cpu_is_pxa3xx()) | ||
259 | pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self); | ||
260 | |||
254 | if (inf->exit) | 261 | if (inf->exit) |
255 | inf->exit(dev); | 262 | inf->exit(dev); |
256 | 263 | ||
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 0e13a00eb2ed..3775c035a6c5 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | 22 | ||
23 | #include <pcmcia/cs.h> | ||
24 | #include <pcmcia/cistpl.h> | 23 | #include <pcmcia/cistpl.h> |
25 | #include <pcmcia/cisreg.h> | 24 | #include <pcmcia/cisreg.h> |
26 | #include <pcmcia/ds.h> | 25 | #include <pcmcia/ds.h> |
@@ -132,49 +131,12 @@ static void sl811_cs_release(struct pcmcia_device * link) | |||
132 | platform_device_unregister(&platform_dev); | 131 | platform_device_unregister(&platform_dev); |
133 | } | 132 | } |
134 | 133 | ||
135 | static int sl811_cs_config_check(struct pcmcia_device *p_dev, | 134 | static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) |
136 | cistpl_cftable_entry_t *cfg, | ||
137 | cistpl_cftable_entry_t *dflt, | ||
138 | unsigned int vcc, | ||
139 | void *priv_data) | ||
140 | { | 135 | { |
141 | if (cfg->index == 0) | 136 | if (p_dev->config_index == 0) |
142 | return -ENODEV; | 137 | return -EINVAL; |
143 | 138 | ||
144 | /* Use power settings for Vcc and Vpp if present */ | 139 | return pcmcia_request_io(p_dev); |
145 | /* Note that the CIS values need to be rescaled */ | ||
146 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
147 | if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc) | ||
148 | return -ENODEV; | ||
149 | } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
150 | if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc) | ||
151 | return -ENODEV; | ||
152 | } | ||
153 | |||
154 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
155 | p_dev->conf.Vpp = | ||
156 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
157 | else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
158 | p_dev->conf.Vpp = | ||
159 | dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
160 | |||
161 | /* we need an interrupt */ | ||
162 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
163 | |||
164 | /* IO window settings */ | ||
165 | p_dev->resource[0]->end = p_dev->resource[1]->end = 0; | ||
166 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
167 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
168 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
169 | |||
170 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
171 | p_dev->resource[0]->start = io->win[0].base; | ||
172 | p_dev->resource[0]->end = io->win[0].len; | ||
173 | |||
174 | return pcmcia_request_io(p_dev); | ||
175 | } | ||
176 | pcmcia_disable_device(p_dev); | ||
177 | return -ENODEV; | ||
178 | } | 140 | } |
179 | 141 | ||
180 | 142 | ||
@@ -185,6 +147,9 @@ static int sl811_cs_config(struct pcmcia_device *link) | |||
185 | 147 | ||
186 | dev_dbg(&link->dev, "sl811_cs_config\n"); | 148 | dev_dbg(&link->dev, "sl811_cs_config\n"); |
187 | 149 | ||
150 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP | | ||
151 | CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO; | ||
152 | |||
188 | if (pcmcia_loop_config(link, sl811_cs_config_check, NULL)) | 153 | if (pcmcia_loop_config(link, sl811_cs_config_check, NULL)) |
189 | goto failed; | 154 | goto failed; |
190 | 155 | ||
@@ -195,18 +160,10 @@ static int sl811_cs_config(struct pcmcia_device *link) | |||
195 | if (!link->irq) | 160 | if (!link->irq) |
196 | goto failed; | 161 | goto failed; |
197 | 162 | ||
198 | ret = pcmcia_request_configuration(link, &link->conf); | 163 | ret = pcmcia_enable_device(link); |
199 | if (ret) | 164 | if (ret) |
200 | goto failed; | 165 | goto failed; |
201 | 166 | ||
202 | dev_info(&link->dev, "index 0x%02x: ", | ||
203 | link->conf.ConfigIndex); | ||
204 | if (link->conf.Vpp) | ||
205 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); | ||
206 | printk(", irq %d", link->irq); | ||
207 | printk(", io %pR", link->resource[0]); | ||
208 | printk("\n"); | ||
209 | |||
210 | if (sl811_hc_init(parent, link->resource[0]->start, link->irq) | 167 | if (sl811_hc_init(parent, link->resource[0]->start, link->irq) |
211 | < 0) { | 168 | < 0) { |
212 | failed: | 169 | failed: |
@@ -227,9 +184,6 @@ static int sl811_cs_probe(struct pcmcia_device *link) | |||
227 | local->p_dev = link; | 184 | local->p_dev = link; |
228 | link->priv = local; | 185 | link->priv = local; |
229 | 186 | ||
230 | link->conf.Attributes = 0; | ||
231 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
232 | |||
233 | return sl811_cs_config(link); | 187 | return sl811_cs_config(link); |
234 | } | 188 | } |
235 | 189 | ||
@@ -241,9 +195,7 @@ MODULE_DEVICE_TABLE(pcmcia, sl811_ids); | |||
241 | 195 | ||
242 | static struct pcmcia_driver sl811_cs_driver = { | 196 | static struct pcmcia_driver sl811_cs_driver = { |
243 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
244 | .drv = { | 198 | .name = "sl811_cs", |
245 | .name = "sl811_cs", | ||
246 | }, | ||
247 | .probe = sl811_cs_probe, | 199 | .probe = sl811_cs_probe, |
248 | .remove = sl811_cs_detach, | 200 | .remove = sl811_cs_detach, |
249 | .id_table = sl811_ids, | 201 | .id_table = sl811_ids, |
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 7c8008225ee3..17927b1f9334 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -127,7 +127,10 @@ static void handle_tx(struct vhost_net *net) | |||
127 | size_t len, total_len = 0; | 127 | size_t len, total_len = 0; |
128 | int err, wmem; | 128 | int err, wmem; |
129 | size_t hdr_size; | 129 | size_t hdr_size; |
130 | struct socket *sock = rcu_dereference(vq->private_data); | 130 | struct socket *sock; |
131 | |||
132 | sock = rcu_dereference_check(vq->private_data, | ||
133 | lockdep_is_held(&vq->mutex)); | ||
131 | if (!sock) | 134 | if (!sock) |
132 | return; | 135 | return; |
133 | 136 | ||
@@ -582,7 +585,10 @@ static void vhost_net_disable_vq(struct vhost_net *n, | |||
582 | static void vhost_net_enable_vq(struct vhost_net *n, | 585 | static void vhost_net_enable_vq(struct vhost_net *n, |
583 | struct vhost_virtqueue *vq) | 586 | struct vhost_virtqueue *vq) |
584 | { | 587 | { |
585 | struct socket *sock = vq->private_data; | 588 | struct socket *sock; |
589 | |||
590 | sock = rcu_dereference_protected(vq->private_data, | ||
591 | lockdep_is_held(&vq->mutex)); | ||
586 | if (!sock) | 592 | if (!sock) |
587 | return; | 593 | return; |
588 | if (vq == n->vqs + VHOST_NET_VQ_TX) { | 594 | if (vq == n->vqs + VHOST_NET_VQ_TX) { |
@@ -598,7 +604,8 @@ static struct socket *vhost_net_stop_vq(struct vhost_net *n, | |||
598 | struct socket *sock; | 604 | struct socket *sock; |
599 | 605 | ||
600 | mutex_lock(&vq->mutex); | 606 | mutex_lock(&vq->mutex); |
601 | sock = vq->private_data; | 607 | sock = rcu_dereference_protected(vq->private_data, |
608 | lockdep_is_held(&vq->mutex)); | ||
602 | vhost_net_disable_vq(n, vq); | 609 | vhost_net_disable_vq(n, vq); |
603 | rcu_assign_pointer(vq->private_data, NULL); | 610 | rcu_assign_pointer(vq->private_data, NULL); |
604 | mutex_unlock(&vq->mutex); | 611 | mutex_unlock(&vq->mutex); |
@@ -736,7 +743,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
736 | } | 743 | } |
737 | 744 | ||
738 | /* start polling new socket */ | 745 | /* start polling new socket */ |
739 | oldsock = vq->private_data; | 746 | oldsock = rcu_dereference_protected(vq->private_data, |
747 | lockdep_is_held(&vq->mutex)); | ||
740 | if (sock != oldsock) { | 748 | if (sock != oldsock) { |
741 | vhost_net_disable_vq(n, vq); | 749 | vhost_net_disable_vq(n, vq); |
742 | rcu_assign_pointer(vq->private_data, sock); | 750 | rcu_assign_pointer(vq->private_data, sock); |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index dd3d6f7406f8..8b5a1b33d0fe 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -320,7 +320,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev) | |||
320 | vhost_dev_cleanup(dev); | 320 | vhost_dev_cleanup(dev); |
321 | 321 | ||
322 | memory->nregions = 0; | 322 | memory->nregions = 0; |
323 | dev->memory = memory; | 323 | RCU_INIT_POINTER(dev->memory, memory); |
324 | return 0; | 324 | return 0; |
325 | } | 325 | } |
326 | 326 | ||
@@ -352,8 +352,9 @@ void vhost_dev_cleanup(struct vhost_dev *dev) | |||
352 | fput(dev->log_file); | 352 | fput(dev->log_file); |
353 | dev->log_file = NULL; | 353 | dev->log_file = NULL; |
354 | /* No one will access memory at this point */ | 354 | /* No one will access memory at this point */ |
355 | kfree(dev->memory); | 355 | kfree(rcu_dereference_protected(dev->memory, |
356 | dev->memory = NULL; | 356 | lockdep_is_held(&dev->mutex))); |
357 | RCU_INIT_POINTER(dev->memory, NULL); | ||
357 | if (dev->mm) | 358 | if (dev->mm) |
358 | mmput(dev->mm); | 359 | mmput(dev->mm); |
359 | dev->mm = NULL; | 360 | dev->mm = NULL; |
@@ -440,14 +441,22 @@ static int vq_access_ok(unsigned int num, | |||
440 | /* Caller should have device mutex but not vq mutex */ | 441 | /* Caller should have device mutex but not vq mutex */ |
441 | int vhost_log_access_ok(struct vhost_dev *dev) | 442 | int vhost_log_access_ok(struct vhost_dev *dev) |
442 | { | 443 | { |
443 | return memory_access_ok(dev, dev->memory, 1); | 444 | struct vhost_memory *mp; |
445 | |||
446 | mp = rcu_dereference_protected(dev->memory, | ||
447 | lockdep_is_held(&dev->mutex)); | ||
448 | return memory_access_ok(dev, mp, 1); | ||
444 | } | 449 | } |
445 | 450 | ||
446 | /* Verify access for write logging. */ | 451 | /* Verify access for write logging. */ |
447 | /* Caller should have vq mutex and device mutex */ | 452 | /* Caller should have vq mutex and device mutex */ |
448 | static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) | 453 | static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) |
449 | { | 454 | { |
450 | return vq_memory_access_ok(log_base, vq->dev->memory, | 455 | struct vhost_memory *mp; |
456 | |||
457 | mp = rcu_dereference_protected(vq->dev->memory, | ||
458 | lockdep_is_held(&vq->mutex)); | ||
459 | return vq_memory_access_ok(log_base, mp, | ||
451 | vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) && | 460 | vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) && |
452 | (!vq->log_used || log_access_ok(log_base, vq->log_addr, | 461 | (!vq->log_used || log_access_ok(log_base, vq->log_addr, |
453 | sizeof *vq->used + | 462 | sizeof *vq->used + |
@@ -487,7 +496,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
487 | kfree(newmem); | 496 | kfree(newmem); |
488 | return -EFAULT; | 497 | return -EFAULT; |
489 | } | 498 | } |
490 | oldmem = d->memory; | 499 | oldmem = rcu_dereference_protected(d->memory, |
500 | lockdep_is_held(&d->mutex)); | ||
491 | rcu_assign_pointer(d->memory, newmem); | 501 | rcu_assign_pointer(d->memory, newmem); |
492 | synchronize_rcu(); | 502 | synchronize_rcu(); |
493 | kfree(oldmem); | 503 | kfree(oldmem); |
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index afd77295971c..af3c11ded5fd 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h | |||
@@ -106,7 +106,7 @@ struct vhost_virtqueue { | |||
106 | * vhost_work execution acts instead of rcu_read_lock() and the end of | 106 | * vhost_work execution acts instead of rcu_read_lock() and the end of |
107 | * vhost_work execution acts instead of rcu_read_lock(). | 107 | * vhost_work execution acts instead of rcu_read_lock(). |
108 | * Writers use virtqueue mutex. */ | 108 | * Writers use virtqueue mutex. */ |
109 | void *private_data; | 109 | void __rcu *private_data; |
110 | /* Log write descriptors */ | 110 | /* Log write descriptors */ |
111 | void __user *log_base; | 111 | void __user *log_base; |
112 | struct vhost_log log[VHOST_NET_MAX_SG]; | 112 | struct vhost_log log[VHOST_NET_MAX_SG]; |
@@ -116,7 +116,7 @@ struct vhost_dev { | |||
116 | /* Readers use RCU to access memory table pointer | 116 | /* Readers use RCU to access memory table pointer |
117 | * log base pointer and features. | 117 | * log base pointer and features. |
118 | * Writers use mutex below.*/ | 118 | * Writers use mutex below.*/ |
119 | struct vhost_memory *memory; | 119 | struct vhost_memory __rcu *memory; |
120 | struct mm_struct *mm; | 120 | struct mm_struct *mm; |
121 | struct mutex mutex; | 121 | struct mutex mutex; |
122 | unsigned acked_features; | 122 | unsigned acked_features; |
@@ -173,7 +173,11 @@ enum { | |||
173 | 173 | ||
174 | static inline int vhost_has_feature(struct vhost_dev *dev, int bit) | 174 | static inline int vhost_has_feature(struct vhost_dev *dev, int bit) |
175 | { | 175 | { |
176 | unsigned acked_features = rcu_dereference(dev->acked_features); | 176 | unsigned acked_features; |
177 | |||
178 | acked_features = | ||
179 | rcu_dereference_index_check(dev->acked_features, | ||
180 | lockdep_is_held(&dev->mutex)); | ||
177 | return acked_features & (1 << bit); | 181 | return acked_features & (1 << bit); |
178 | } | 182 | } |
179 | 183 | ||
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c index a31a77ff6f3d..cea6403ae71c 100644 --- a/drivers/video/pxa168fb.c +++ b/drivers/video/pxa168fb.c | |||
@@ -784,12 +784,53 @@ failed: | |||
784 | return ret; | 784 | return ret; |
785 | } | 785 | } |
786 | 786 | ||
787 | static int __devexit pxa168fb_remove(struct platform_device *pdev) | ||
788 | { | ||
789 | struct pxa168fb_info *fbi = platform_get_drvdata(pdev); | ||
790 | struct fb_info *info; | ||
791 | int irq; | ||
792 | unsigned int data; | ||
793 | |||
794 | if (!fbi) | ||
795 | return 0; | ||
796 | |||
797 | /* disable DMA transfer */ | ||
798 | data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
799 | data &= ~CFG_GRA_ENA_MASK; | ||
800 | writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0); | ||
801 | |||
802 | info = fbi->info; | ||
803 | |||
804 | unregister_framebuffer(info); | ||
805 | |||
806 | writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA); | ||
807 | |||
808 | if (info->cmap.len) | ||
809 | fb_dealloc_cmap(&info->cmap); | ||
810 | |||
811 | irq = platform_get_irq(pdev, 0); | ||
812 | free_irq(irq, fbi); | ||
813 | |||
814 | dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), | ||
815 | info->screen_base, info->fix.smem_start); | ||
816 | |||
817 | iounmap(fbi->reg_base); | ||
818 | |||
819 | clk_disable(fbi->clk); | ||
820 | clk_put(fbi->clk); | ||
821 | |||
822 | framebuffer_release(info); | ||
823 | |||
824 | return 0; | ||
825 | } | ||
826 | |||
787 | static struct platform_driver pxa168fb_driver = { | 827 | static struct platform_driver pxa168fb_driver = { |
788 | .driver = { | 828 | .driver = { |
789 | .name = "pxa168-fb", | 829 | .name = "pxa168-fb", |
790 | .owner = THIS_MODULE, | 830 | .owner = THIS_MODULE, |
791 | }, | 831 | }, |
792 | .probe = pxa168fb_probe, | 832 | .probe = pxa168fb_probe, |
833 | .remove = __devexit_p(pxa168fb_remove), | ||
793 | }; | 834 | }; |
794 | 835 | ||
795 | static int __init pxa168fb_init(void) | 836 | static int __init pxa168fb_init(void) |
@@ -798,6 +839,12 @@ static int __init pxa168fb_init(void) | |||
798 | } | 839 | } |
799 | module_init(pxa168fb_init); | 840 | module_init(pxa168fb_init); |
800 | 841 | ||
842 | static void __exit pxa168fb_exit(void) | ||
843 | { | ||
844 | platform_driver_unregister(&pxa168fb_driver); | ||
845 | } | ||
846 | module_exit(pxa168fb_exit); | ||
847 | |||
801 | MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " | 848 | MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " |
802 | "Green Wan <gwan@marvell.com>"); | 849 | "Green Wan <gwan@marvell.com>"); |
803 | MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); | 850 | MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); |
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index f2d9e667972d..f885c868a04d 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/irq.h> | ||
34 | 35 | ||
35 | #include <linux/vlynq.h> | 36 | #include <linux/vlynq.h> |
36 | 37 | ||
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 2a410170eca6..909923800a02 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/cpu.h> | 64 | #include <linux/cpu.h> |
65 | #include <linux/smp.h> | 65 | #include <linux/smp.h> |
66 | #include <linux/fs.h> | 66 | #include <linux/fs.h> |
67 | #include <linux/irq.h> | ||
67 | 68 | ||
68 | #include <asm/mipsregs.h> | 69 | #include <asm/mipsregs.h> |
69 | #include <asm/uasm.h> | 70 | #include <asm/uasm.h> |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 13365ba35218..7d24b0d94ed4 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -338,30 +338,29 @@ static void unmask_evtchn(int port) | |||
338 | 338 | ||
339 | static int find_unbound_irq(void) | 339 | static int find_unbound_irq(void) |
340 | { | 340 | { |
341 | int irq; | 341 | struct irq_data *data; |
342 | struct irq_desc *desc; | 342 | int irq, res; |
343 | 343 | ||
344 | for (irq = 0; irq < nr_irqs; irq++) { | 344 | for (irq = 0; irq < nr_irqs; irq++) { |
345 | desc = irq_to_desc(irq); | 345 | data = irq_get_irq_data(irq); |
346 | /* only 0->15 have init'd desc; handle irq > 16 */ | 346 | /* only 0->15 have init'd desc; handle irq > 16 */ |
347 | if (desc == NULL) | 347 | if (!data) |
348 | break; | 348 | break; |
349 | if (desc->chip == &no_irq_chip) | 349 | if (data->chip == &no_irq_chip) |
350 | break; | 350 | break; |
351 | if (desc->chip != &xen_dynamic_chip) | 351 | if (data->chip != &xen_dynamic_chip) |
352 | continue; | 352 | continue; |
353 | if (irq_info[irq].type == IRQT_UNBOUND) | 353 | if (irq_info[irq].type == IRQT_UNBOUND) |
354 | break; | 354 | return irq; |
355 | } | 355 | } |
356 | 356 | ||
357 | if (irq == nr_irqs) | 357 | if (irq == nr_irqs) |
358 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | 358 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
359 | 359 | ||
360 | desc = irq_to_desc_alloc_node(irq, 0); | 360 | res = irq_alloc_desc_at(irq, 0); |
361 | if (WARN_ON(desc == NULL)) | ||
362 | return -1; | ||
363 | 361 | ||
364 | dynamic_irq_init_keep_chip_data(irq); | 362 | if (WARN_ON(res != irq)) |
363 | return -1; | ||
365 | 364 | ||
366 | return irq; | 365 | return irq; |
367 | } | 366 | } |
@@ -495,7 +494,7 @@ static void unbind_from_irq(unsigned int irq) | |||
495 | if (irq_info[irq].type != IRQT_UNBOUND) { | 494 | if (irq_info[irq].type != IRQT_UNBOUND) { |
496 | irq_info[irq] = mk_unbound_info(); | 495 | irq_info[irq] = mk_unbound_info(); |
497 | 496 | ||
498 | dynamic_irq_cleanup(irq); | 497 | irq_free_desc(irq); |
499 | } | 498 | } |
500 | 499 | ||
501 | spin_unlock(&irq_mapping_update_lock); | 500 | spin_unlock(&irq_mapping_update_lock); |