diff options
author | Tejun Heo <htejun@gmail.com> | 2007-01-20 02:00:28 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-09 17:39:37 -0500 |
commit | 24dc5f33ea4b504cfbd23fa159a4cacba8e4d800 (patch) | |
tree | d76de456157f555c9a65b83f426fd805fee1e846 /drivers/ata/sata_mv.c | |
parent | f0d36efdc624beb3d9e29b9ab9e9537bf0f25d5b (diff) |
libata: update libata LLDs to use devres
Update libata LLDs to use devres. Core layer is already converted to
support managed LLDs. This patch simplifies initialization and fixes
many resource related bugs in init failure and detach path. For
example, all converted drivers now handle ata_device_add() failure
gracefully without excessive resource rollback code.
As most resources are released automatically on driver detach, many
drivers don't need or can do with much simpler ->{port|host}_stop().
In general, stop callbacks are need iff port or host needs to be given
commands to shut it down. Note that freezing is enough in many cases
and ports are automatically frozen before being detached.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r-- | drivers/ata/sata_mv.c | 142 |
1 files changed, 29 insertions, 113 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index aae0b5201c1e..c073e453dcdd 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <scsi/scsi_host.h> | 34 | #include <scsi/scsi_host.h> |
35 | #include <scsi/scsi_cmnd.h> | 35 | #include <scsi/scsi_cmnd.h> |
36 | #include <linux/libata.h> | 36 | #include <linux/libata.h> |
37 | #include <asm/io.h> | ||
38 | 37 | ||
39 | #define DRV_NAME "sata_mv" | 38 | #define DRV_NAME "sata_mv" |
40 | #define DRV_VERSION "0.7" | 39 | #define DRV_VERSION "0.7" |
@@ -342,7 +341,6 @@ static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | |||
342 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | 341 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); |
343 | static void mv_phy_reset(struct ata_port *ap); | 342 | static void mv_phy_reset(struct ata_port *ap); |
344 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep); | 343 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep); |
345 | static void mv_host_stop(struct ata_host *host); | ||
346 | static int mv_port_start(struct ata_port *ap); | 344 | static int mv_port_start(struct ata_port *ap); |
347 | static void mv_port_stop(struct ata_port *ap); | 345 | static void mv_port_stop(struct ata_port *ap); |
348 | static void mv_qc_prep(struct ata_queued_cmd *qc); | 346 | static void mv_qc_prep(struct ata_queued_cmd *qc); |
@@ -418,7 +416,6 @@ static const struct ata_port_operations mv5_ops = { | |||
418 | 416 | ||
419 | .port_start = mv_port_start, | 417 | .port_start = mv_port_start, |
420 | .port_stop = mv_port_stop, | 418 | .port_stop = mv_port_stop, |
421 | .host_stop = mv_host_stop, | ||
422 | }; | 419 | }; |
423 | 420 | ||
424 | static const struct ata_port_operations mv6_ops = { | 421 | static const struct ata_port_operations mv6_ops = { |
@@ -446,7 +443,6 @@ static const struct ata_port_operations mv6_ops = { | |||
446 | 443 | ||
447 | .port_start = mv_port_start, | 444 | .port_start = mv_port_start, |
448 | .port_stop = mv_port_stop, | 445 | .port_stop = mv_port_stop, |
449 | .host_stop = mv_host_stop, | ||
450 | }; | 446 | }; |
451 | 447 | ||
452 | static const struct ata_port_operations mv_iie_ops = { | 448 | static const struct ata_port_operations mv_iie_ops = { |
@@ -474,7 +470,6 @@ static const struct ata_port_operations mv_iie_ops = { | |||
474 | 470 | ||
475 | .port_start = mv_port_start, | 471 | .port_start = mv_port_start, |
476 | .port_stop = mv_port_stop, | 472 | .port_stop = mv_port_stop, |
477 | .host_stop = mv_host_stop, | ||
478 | }; | 473 | }; |
479 | 474 | ||
480 | static const struct ata_port_info mv_port_info[] = { | 475 | static const struct ata_port_info mv_port_info[] = { |
@@ -809,35 +804,6 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | |||
809 | } | 804 | } |
810 | } | 805 | } |
811 | 806 | ||
812 | /** | ||
813 | * mv_host_stop - Host specific cleanup/stop routine. | ||
814 | * @host: host data structure | ||
815 | * | ||
816 | * Disable ints, cleanup host memory, call general purpose | ||
817 | * host_stop. | ||
818 | * | ||
819 | * LOCKING: | ||
820 | * Inherited from caller. | ||
821 | */ | ||
822 | static void mv_host_stop(struct ata_host *host) | ||
823 | { | ||
824 | struct mv_host_priv *hpriv = host->private_data; | ||
825 | struct pci_dev *pdev = to_pci_dev(host->dev); | ||
826 | |||
827 | if (hpriv->hp_flags & MV_HP_FLAG_MSI) { | ||
828 | pci_disable_msi(pdev); | ||
829 | } else { | ||
830 | pci_intx(pdev, 0); | ||
831 | } | ||
832 | kfree(hpriv); | ||
833 | ata_host_stop(host); | ||
834 | } | ||
835 | |||
836 | static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) | ||
837 | { | ||
838 | dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); | ||
839 | } | ||
840 | |||
841 | static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) | 807 | static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) |
842 | { | 808 | { |
843 | u32 cfg = readl(port_mmio + EDMA_CFG_OFS); | 809 | u32 cfg = readl(port_mmio + EDMA_CFG_OFS); |
@@ -883,22 +849,21 @@ static int mv_port_start(struct ata_port *ap) | |||
883 | void __iomem *port_mmio = mv_ap_base(ap); | 849 | void __iomem *port_mmio = mv_ap_base(ap); |
884 | void *mem; | 850 | void *mem; |
885 | dma_addr_t mem_dma; | 851 | dma_addr_t mem_dma; |
886 | int rc = -ENOMEM; | 852 | int rc; |
887 | 853 | ||
888 | pp = kmalloc(sizeof(*pp), GFP_KERNEL); | 854 | pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); |
889 | if (!pp) | 855 | if (!pp) |
890 | goto err_out; | 856 | return -ENOMEM; |
891 | memset(pp, 0, sizeof(*pp)); | ||
892 | 857 | ||
893 | mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, | 858 | mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, |
894 | GFP_KERNEL); | 859 | GFP_KERNEL); |
895 | if (!mem) | 860 | if (!mem) |
896 | goto err_out_pp; | 861 | return -ENOMEM; |
897 | memset(mem, 0, MV_PORT_PRIV_DMA_SZ); | 862 | memset(mem, 0, MV_PORT_PRIV_DMA_SZ); |
898 | 863 | ||
899 | rc = ata_pad_alloc(ap, dev); | 864 | rc = ata_pad_alloc(ap, dev); |
900 | if (rc) | 865 | if (rc) |
901 | goto err_out_priv; | 866 | return rc; |
902 | 867 | ||
903 | /* First item in chunk of DMA memory: | 868 | /* First item in chunk of DMA memory: |
904 | * 32-slot command request table (CRQB), 32 bytes each in size | 869 | * 32-slot command request table (CRQB), 32 bytes each in size |
@@ -951,13 +916,6 @@ static int mv_port_start(struct ata_port *ap) | |||
951 | */ | 916 | */ |
952 | ap->private_data = pp; | 917 | ap->private_data = pp; |
953 | return 0; | 918 | return 0; |
954 | |||
955 | err_out_priv: | ||
956 | mv_priv_free(pp, dev); | ||
957 | err_out_pp: | ||
958 | kfree(pp); | ||
959 | err_out: | ||
960 | return rc; | ||
961 | } | 919 | } |
962 | 920 | ||
963 | /** | 921 | /** |
@@ -971,18 +929,11 @@ err_out: | |||
971 | */ | 929 | */ |
972 | static void mv_port_stop(struct ata_port *ap) | 930 | static void mv_port_stop(struct ata_port *ap) |
973 | { | 931 | { |
974 | struct device *dev = ap->host->dev; | ||
975 | struct mv_port_priv *pp = ap->private_data; | ||
976 | unsigned long flags; | 932 | unsigned long flags; |
977 | 933 | ||
978 | spin_lock_irqsave(&ap->host->lock, flags); | 934 | spin_lock_irqsave(&ap->host->lock, flags); |
979 | mv_stop_dma(ap); | 935 | mv_stop_dma(ap); |
980 | spin_unlock_irqrestore(&ap->host->lock, flags); | 936 | spin_unlock_irqrestore(&ap->host->lock, flags); |
981 | |||
982 | ap->private_data = NULL; | ||
983 | ata_pad_free(ap, dev); | ||
984 | mv_priv_free(pp, dev); | ||
985 | kfree(pp); | ||
986 | } | 937 | } |
987 | 938 | ||
988 | /** | 939 | /** |
@@ -2342,49 +2293,41 @@ static void mv_print_info(struct ata_probe_ent *probe_ent) | |||
2342 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2293 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
2343 | { | 2294 | { |
2344 | static int printed_version = 0; | 2295 | static int printed_version = 0; |
2345 | struct ata_probe_ent *probe_ent = NULL; | 2296 | struct device *dev = &pdev->dev; |
2297 | struct ata_probe_ent *probe_ent; | ||
2346 | struct mv_host_priv *hpriv; | 2298 | struct mv_host_priv *hpriv; |
2347 | unsigned int board_idx = (unsigned int)ent->driver_data; | 2299 | unsigned int board_idx = (unsigned int)ent->driver_data; |
2348 | void __iomem *mmio_base; | 2300 | void __iomem *mmio_base; |
2349 | int pci_dev_busy = 0, rc; | 2301 | int rc; |
2350 | 2302 | ||
2351 | if (!printed_version++) | 2303 | if (!printed_version++) |
2352 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); | 2304 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); |
2353 | 2305 | ||
2354 | rc = pci_enable_device(pdev); | 2306 | rc = pcim_enable_device(pdev); |
2355 | if (rc) { | 2307 | if (rc) |
2356 | return rc; | 2308 | return rc; |
2357 | } | ||
2358 | pci_set_master(pdev); | 2309 | pci_set_master(pdev); |
2359 | 2310 | ||
2360 | rc = pci_request_regions(pdev, DRV_NAME); | 2311 | rc = pci_request_regions(pdev, DRV_NAME); |
2361 | if (rc) { | 2312 | if (rc) { |
2362 | pci_dev_busy = 1; | 2313 | pcim_pin_device(pdev); |
2363 | goto err_out; | 2314 | return rc; |
2364 | } | 2315 | } |
2365 | 2316 | ||
2366 | probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); | 2317 | probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL); |
2367 | if (probe_ent == NULL) { | 2318 | if (probe_ent == NULL) |
2368 | rc = -ENOMEM; | 2319 | return -ENOMEM; |
2369 | goto err_out_regions; | ||
2370 | } | ||
2371 | 2320 | ||
2372 | memset(probe_ent, 0, sizeof(*probe_ent)); | ||
2373 | probe_ent->dev = pci_dev_to_dev(pdev); | 2321 | probe_ent->dev = pci_dev_to_dev(pdev); |
2374 | INIT_LIST_HEAD(&probe_ent->node); | 2322 | INIT_LIST_HEAD(&probe_ent->node); |
2375 | 2323 | ||
2376 | mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0); | 2324 | mmio_base = pcim_iomap(pdev, MV_PRIMARY_BAR, 0); |
2377 | if (mmio_base == NULL) { | 2325 | if (mmio_base == NULL) |
2378 | rc = -ENOMEM; | 2326 | return -ENOMEM; |
2379 | goto err_out_free_ent; | ||
2380 | } | ||
2381 | 2327 | ||
2382 | hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); | 2328 | hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); |
2383 | if (!hpriv) { | 2329 | if (!hpriv) |
2384 | rc = -ENOMEM; | 2330 | return -ENOMEM; |
2385 | goto err_out_iounmap; | ||
2386 | } | ||
2387 | memset(hpriv, 0, sizeof(*hpriv)); | ||
2388 | 2331 | ||
2389 | probe_ent->sht = mv_port_info[board_idx].sht; | 2332 | probe_ent->sht = mv_port_info[board_idx].sht; |
2390 | probe_ent->port_flags = mv_port_info[board_idx].flags; | 2333 | probe_ent->port_flags = mv_port_info[board_idx].flags; |
@@ -2399,48 +2342,21 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2399 | 2342 | ||
2400 | /* initialize adapter */ | 2343 | /* initialize adapter */ |
2401 | rc = mv_init_host(pdev, probe_ent, board_idx); | 2344 | rc = mv_init_host(pdev, probe_ent, board_idx); |
2402 | if (rc) { | 2345 | if (rc) |
2403 | goto err_out_hpriv; | 2346 | return rc; |
2404 | } | ||
2405 | 2347 | ||
2406 | /* Enable interrupts */ | 2348 | /* Enable interrupts */ |
2407 | if (msi && pci_enable_msi(pdev) == 0) { | 2349 | if (msi && !pci_enable_msi(pdev)) |
2408 | hpriv->hp_flags |= MV_HP_FLAG_MSI; | ||
2409 | } else { | ||
2410 | pci_intx(pdev, 1); | 2350 | pci_intx(pdev, 1); |
2411 | } | ||
2412 | 2351 | ||
2413 | mv_dump_pci_cfg(pdev, 0x68); | 2352 | mv_dump_pci_cfg(pdev, 0x68); |
2414 | mv_print_info(probe_ent); | 2353 | mv_print_info(probe_ent); |
2415 | 2354 | ||
2416 | if (ata_device_add(probe_ent) == 0) { | 2355 | if (ata_device_add(probe_ent) == 0) |
2417 | rc = -ENODEV; /* No devices discovered */ | 2356 | return -ENODEV; |
2418 | goto err_out_dev_add; | ||
2419 | } | ||
2420 | 2357 | ||
2421 | kfree(probe_ent); | 2358 | devm_kfree(dev, probe_ent); |
2422 | return 0; | 2359 | return 0; |
2423 | |||
2424 | err_out_dev_add: | ||
2425 | if (MV_HP_FLAG_MSI & hpriv->hp_flags) { | ||
2426 | pci_disable_msi(pdev); | ||
2427 | } else { | ||
2428 | pci_intx(pdev, 0); | ||
2429 | } | ||
2430 | err_out_hpriv: | ||
2431 | kfree(hpriv); | ||
2432 | err_out_iounmap: | ||
2433 | pci_iounmap(pdev, mmio_base); | ||
2434 | err_out_free_ent: | ||
2435 | kfree(probe_ent); | ||
2436 | err_out_regions: | ||
2437 | pci_release_regions(pdev); | ||
2438 | err_out: | ||
2439 | if (!pci_dev_busy) { | ||
2440 | pci_disable_device(pdev); | ||
2441 | } | ||
2442 | |||
2443 | return rc; | ||
2444 | } | 2360 | } |
2445 | 2361 | ||
2446 | static int __init mv_init(void) | 2362 | static int __init mv_init(void) |